npm package: @hardanonymous/marquee-selector
Description: A framework-agnostic marquee selection library with drag & text selection protection
Author: hardanonymous
Latest version: 0.0.6

# Marquee Selector

[![npm version](https://img.shields.io/npm/v/@hardanonymous/marquee-selector.svg)](https://www.npmjs.com/package/@hardanonymous/marquee-selector)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## 🎮 Demo

體驗線上 Demo：[Marquee Selector Demo](https://hard25670559.github.io/MarqueeSelectorVanillaJSExample/)

## ✨ 特性

- 🎯 **框架無關**：純 Vanilla JavaScript 實現，可在任何前端框架中使用
- 🎨 **多目標支援**：可同時追蹤多組不同的選取目標，各有獨立的回調
- 🛡️ **智能保護機制**：
  - 自動保護可拖拽元素（`draggable="true"`）
  - 保護文字選取區域（input、textarea、contenteditable 等）
- 🔄 **完整生命週期**：提供 `onSelectionStart`、`onSelectionChange`、`onSelectionEnd`、`onClearClick` 回調
- 📍 **精確碰撞檢測**：支援滾動容器，使用 AABB 算法進行精確的碰撞檢測
- 💾 **記憶體優化**：使用 WeakMap 快取選取狀態，避免記憶體洩漏
- 🎨 **CSS 可定制**：通過 CSS 變數輕鬆定制外觀

## 📦 安裝

```bash
npm install @hardanonymous/marquee-selector
```

或使用 yarn：

```bash
yarn add @hardanonymous/marquee-selector
```

## 🚀 快速開始

```typescript
import { MarqueeSelector } from "@hardanonymous/marquee-selector";
import "@hardanonymous/marquee-selector/style.css";

// 1. 初始化
const marquee = new MarqueeSelector({
  container: document.body,
});

// 2. 添加目標配置
marquee.addTarget({
  selector: ".item",
  onSelectionChange: (elements) => {
    console.log("選取變化:", elements);
    elements.forEach((el) => el.classList.add("selected"));
  },
  onClearClick: (elements) => {
    console.log("清除選取");
    elements.forEach((el) => el.classList.remove("selected"));
  },
});

// 3. 啟用框選
marquee.enable();
```

## 📚 使用範例

### Vue 3

```vue
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import { MarqueeSelector } from "@hardanonymous/marquee-selector";
import "@hardanonymous/marquee-selector/style.css";

const containerRef = ref<HTMLElement>();
const selectedIds = ref<number[]>([]);
let marquee: MarqueeSelector | null = null;

onMounted(() => {
  if (containerRef.value) {
    marquee = new MarqueeSelector({
      container: containerRef.value,
    });

    marquee.addTarget({
      selector: ".item",
      onSelectionChange: (elements) => {
        selectedIds.value = elements.map((el) =>
          Number(el.getAttribute("data-id"))
        );
      },
    });

    marquee.enable();
  }
});

onUnmounted(() => {
  marquee?.destroy();
});
</script>

<template>
  <div ref="containerRef">
    <div
      v-for="item in items"
      :key="item.id"
      :data-id="item.id"
      class="item"
      :class="{ selected: selectedIds.includes(item.id) }"
    >
      {{ item.name }}
    </div>
  </div>
</template>
```

### React

```tsx
import { useEffect, useRef, useState } from "react";
import { MarqueeSelector } from "@hardanonymous/marquee-selector";
import "@hardanonymous/marquee-selector/style.css";

function App() {
  const containerRef = useRef<HTMLDivElement>(null);
  const [selectedIds, setSelectedIds] = useState<number[]>([]);

  useEffect(() => {
    if (!containerRef.current) return;

    const marquee = new MarqueeSelector({
      container: containerRef.current,
    });

    marquee.addTarget({
      selector: ".item",
      onSelectionChange: (elements) => {
        const ids = elements.map((el) => Number(el.getAttribute("data-id")));
        setSelectedIds(ids);
      },
    });

    marquee.enable();

    return () => marquee.destroy();
  }, []);

  return (
    <div ref={containerRef}>
      {items.map((item) => (
        <div
          key={item.id}
          data-id={item.id}
          className={`item ${selectedIds.includes(item.id) ? "selected" : ""}`}
        >
          {item.name}
        </div>
      ))}
    </div>
  );
}
```

## 📖 完整文檔

查看 [完整文檔](./docs/README.md) 了解：

- 詳細的 API 參考
- 進階使用方式
- 與拖拽功能整合
- 工作原理說明
- 效能優化建議
- 常見問題解答

## 🎨 自定義樣式

通過 CSS 變數自定義框選框外觀：

```css
:root {
  --marquee-border-width: 2px;
  --marquee-border-style: dashed;
  --marquee-border-color: #ff0000;
  --marquee-bg-color: rgba(255, 0, 0, 0.15);
  --marquee-z-index: 10000;
}
```

## 🤝 貢獻

歡迎提交 Issue 和 Pull Request！

## 📄 授權

MIT License - 詳見 [LICENSE](./LICENSE) 文件

## 🔗 相關連結

- [GitHub Repository](https://github.com/hard25670559/marquee-selector)
- [npm Package](https://www.npmjs.com/package/@hardanonymous/marquee-selector)
- [問題回報](https://github.com/hard25670559/marquee-selector/issues)