npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vue3-modal-manager

v2.0.3

Published

A flexible and powerful modal manager for Vue 3

Downloads

24

Readme

vue3-modal-manager

一個完整的、類型安全的 Vue.js modal管理系統,提供靈活的modal創建、管理和交互功能。

✨ 主要特性

  • 雙模式支援: 固定modal (fixed) 和可拖拽modal (draggable)
  • 類型安全: 完整的 TypeScript 支援,方法重載確保類型安全
  • Vue.js 整合: 無縫的 Vue.js 插件整合,支援組件動態載入
  • 拖拽功能: 拖拽移動
  • 調整大小: 8方向調整大小功能
  • 層級管理: z-index 管理和置頂功能
  • 容器支援: 支援在指定容器中打開modal
  • 事件系統: 完整的自訂事件支援
  • 邊界計算: 自動計算邊界限制,防止超出容器範圍

📁 專案結構

lib/
├── core/
│   └── ModalManager.ts        # 核心管理器
├── features/
│   ├── ModalResize.ts         # 調整大小功能
│   └── ModalDrag.ts           # 拖拽功能
├── types/
│   ├── modal.params.ts        # 核心類型定義
│   ├── modal.resize.ts        # 調整大小類型
│   ├── modal.drag.ts          # 拖拽類型
│   └── index.ts               # 類型統一匯出
└── index.ts                   # 主要入口檔案

🚀 快速開始

安裝和初始化

// main.ts
import { createApp } from 'vue'
import { createModalManager } from './lib'
import App from './App.vue'

// 創建modal管理器
const modalManager = createModalManager([
  {
    name: 'LoginModal',
    component: () => import('./components/LoginModal.vue'),
  },
  {
    name: 'SettingsModal',
    component: () => import('./components/SettingsModal.vue'),
  },
])

const app = createApp(App)

// 安裝插件
app.use(modalManager)

app.mount('#app')

基本使用

// 在組件中使用
import { useModalManager } from './lib'

export default {
  setup() {
    const modalManager = useModalManager()

    // 打開固定modal
    const openFixedModal = async () => {
      const result = await modalManager.openModal('LoginModal', 'fixed', {
        direction: 'center',
        props: {
          title: '登入',
          message: '請輸入您的憑證',
        },
        events: {
          confirm: (data) => console.log('登入成功', data),
          cancel: () => console.log('取消登入'),
        },
      })

      if (result.success) {
        console.log('modal已開啟:', result.modalId)
      }
    }

    // 打開可拖拽modal
    const openDraggableModal = async () => {
      await modalManager.openModal('SettingsModal', 'draggable', {
        drag: true,
        resize: true,
        position: {
          top: '100px',
          left: '200px',
        },
        props: {
          title: '設定',
          data: { theme: 'dark' },
        },
      })
    }

    return {
      openFixedModal,
      openDraggableModal,
    }
  },
}

📖 API 文檔

ModalManager

openModal(name, mode, params)

打開modal的主要方法,支援方法重載確保類型安全。

固定modal

await modalManager.openModal('LoginModal', 'fixed', {
  direction?: 'center' | 'top' | 'bottom' | 'left' | 'right',
  id?: string,              // 目標容器ID
  props?: Record<string, any>,
  events?: Record<string, Function>
})

可拖拽modal

await modalManager.openModal('SettingsModal', 'draggable', {
  drag?: boolean,           // 啟用拖拽功能
  resize?: boolean,         // 啟用調整大小功能
  position?: {              // 自訂位置
    top?: string,
    left?: string,
    right?: string,
    bottom?: string
  },
  id?: string,              // 目標容器ID
  props?: Record<string, any>,
  events?: Record<string, Function>
})

其他方法

// 關閉指定modal
modalManager.closeModal(modalId: string): boolean

// 關閉所有modal
modalManager.removeAllModal(): number

// 移動modal到指定容器
modalManager.moveToLayers(modalId: string, targetId: string): boolean

// 獲取所有開啟的modal
modalManager.getOpenModals(): modalInfo[]

// 檢查modal是否存在
modalManager.hasModal(modalId: string): boolean

// 根據名稱查找modal
modalManager.findModalsByName(name: string): modalInfo[]

// 獲取modal數量
modalManager.getModalCount(): number

🎨 modal組件範例

基本modal組件

<template>
  <div class="modal-content">
    <!-- 拖拽把手 (可選) -->
    <div v-if="showDragHandle" :modalDraggableArea="modalId" class="modal-header drag-handle">
      <h3>{{ title }}</h3>
      <button @click="$emit('closed')">×</button>
    </div>

    <!-- modal內容 -->
    <div class="modal-body">
      <p>{{ content }}</p>
    </div>

    <!-- modal底部 -->
    <div class="modal-footer">
      <button @click="handleConfirm" class="btn-primary"> 確認 </button>
      <button @click="$emit('closed')" class="btn-secondary"> 取消 </button>
    </div>
  </div>
</template>

<script setup lang="ts">
interface Props {
  modalId: string
  title?: string
  content?: string
  showDragHandle?: boolean
}

const props = defineProps<Props>()

const emit = defineEmits<{
  closed: []
  confirm: [data: any]
}>()

const handleConfirm = () => {
  emit('confirm', { message: '確認操作' })
  emit('closed')
}
</script>

🎪 事件系統

拖拽事件

// 監聽拖拽事件
modalInfo.container.addEventListener('modal-drag', (e) => {
  console.log('拖拽中:', e.detail.x, e.detail.y)
})

modalInfo.container.addEventListener('modal-drag-end', (e) => {
  console.log('拖拽結束:', e.detail.x, e.detail.y)
})

調整大小事件

// 監聽調整大小事件
modalInfo.container.addEventListener('modal-resize', (e) => {
  console.log('調整中:', e.detail.width, e.detail.height)
})

modalInfo.container.addEventListener('modal-resize-end', (e) => {
  console.log('調整完成:', e.detail.width, e.detail.height)
})

🎯 進階使用

在指定容器中打開modal

// HTML
<div id="custom-container" style="position: relative;">
  <!-- modal將在這個容器中打開 -->
</div>

// JavaScript
await modalManager.openModal('MyModal', 'draggable', {
  id: 'custom-container',
  drag: true
})

自訂事件處理

await modalManager.openModal('DataModal', 'draggable', {
  props: {
    data: { id: 1, name: 'Test' },
  },
  events: {
    save: (data) => {
      console.log('儲存資料:', data)
      // 處理儲存邏輯
    },
    delete: () => {
      console.log('刪除資料')
      // 處理刪除邏輯
    },
    export: (format) => {
      console.log('匯出格式:', format)
      // 處理匯出邏輯
    },
  },
})

多modal管理

// 打開多個modal
const modals = await Promise.all([
  modalManager.openModal('Modal1', 'draggable', { drag: true }),
  modalManager.openModal('Modal2', 'draggable', { resize: true }),
  modalManager.openModal('Modal3', 'fixed', { direction: 'top' }),
])

// 查看所有開啟的modal
const openModals = modalManager.getOpenModals()
console.log(`目前有 ${openModals.length} 個modal開啟`)

// 關閉所有modal
const closedCount = modalManager.removeAllModal()
console.log(`關閉了 ${closedCount} 個modal`)

🔧 類型定義

核心類型

// modal模式
type modalMode = 'fixed' | 'draggable'

// 固定modal參數
interface fixedModalParams {
  direction?: 'center' | 'top' | 'bottom' | 'left' | 'right'
  id?: string
  props?: Record<string, any>
  events?: Record<string, Function>
}

// 可拖拽模modal參數
interface draggableModalParams {
  drag?: boolean
  resize?: boolean
  position?: {
    top?: string
    left?: string
    right?: string
    bottom?: string
  }
  id?: string
  props?: Record<string, any>
  events?: Record<string, Function>
}

// modal資訊
interface modalInfo {
  id: string
  name: string
  container: HTMLElement
  boxElement: HTMLElement
  resize?: ModalResize | null
  drag?: ModalDrag | null
}

📋 瀏覽器支援

  • Chrome 87+ (支援 CSS inset 屬性)
  • Firefox 66+
  • Safari 14.1+
  • Edge 87+

🤝 貢獻

歡迎提交 Issue 和 Pull Request!

📄 授權

MIT License


📝 更新日誌

v2.0.0

  • 🔧 修復初始位置跳躍問題
  • ✨ 重構架構,提升類型安全性
  • 🚀 改進 handles 位置更新機制
  • 💡 優化程式碼結構和可維護性
  • 📦 完整的功能模組化

v1.0.0

  • 🎉 初始版本發布
  • ✨ 基礎modal管理功能