DropLayer
一次拖拽落到不同区域做不同的事(画布「导入并放置」、素材面板「只导入」)。XDropLayer 在应用顶层挂一个,在 window 上接所有拖拽:拖着东西进窗口就画出接得住它的区,指到的那块加深并亮出提示,松手交给那块的 onDrop;落在区外的一律不收,也拦住浏览器「打开文件」。
区由各布局组件用 useDropZone 登记,组件卸载自动注销——拖放层不认识业务。为什么不让各区自己监听:dragenter / dragleave 在子元素进出时成对乱跳,各区各算会闪;重叠的区谁接说不清;落在所有区之外时也没人拦浏览器的默认行为。
ts
import { useDropZone } from '@xwink/ui'
useDropZone({
rect: () => panel.value?.getBoundingClientRect(), // 拖动中每次现量,拿不到就不画不收
accepts: ['files'],
hint: '松手只导入素材库', // 缺省取 useUiLocale().dropLayer.hint
icon: 'ph:tray-arrow-down',
priority: 10, // 重叠时大的先得;同级先登记的先得(里层组件先挂载)
onDrop: (kind, transfer, at) => importFiles(transfer.files),
})
多区与优先级
整层不接指针,命中按坐标算,落点下的元素照常收到 dragover。文字只收从别的窗口拖来的:页面里自己选中文字拖动不是导入。
画布与浮在上面的素材库
从桌面拖一个文件,或从别的窗口拖一段文字进来
素材库
(只收文件)
(只收文件)
自定义拖放类型
内置 files / text,其余由宿主写 MIME:页面里拖出时 setData 用同一个串,登记区在 accepts 里点名才收。必须全小写——浏览器把 dataTransfer.types 一律转成小写。
拖卡片标记完成
需求评审
接口联调
发版检查
已完成
换掉提示
区里的提示可经 #hint 插槽换掉,作用域参数是 { zone, kind, active, hint }(hint 是算好的文案);虚线框与底色走 --ui-primary,换主题色即跟着变。
命中、排序、认类型与「是否拖出窗口」的判定都导出成纯函数(hitDropZone、sortDropZones、dragKindOf、dragLeftWindow 等),宿主自己写拖放交互时复用同一套判定。
API
Slots
| 插槽 | 说明 |
|---|---|
hint | — |
XDropLayer 没有 props,class 等属性落在铺满视口的层根上(只在拖动中渲染)。useDropZone(options) 的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
rect | () => DOMRect | undefined | 此刻的范围(视口坐标),拖动中每次现量 |
accepts | DragKind[] | 'files' / 'text' / 全小写的自定义 MIME |
hint | string | (kind) => string | 指到时的提示,可按拖的东西换说法 |
icon | string | 提示前的图标(Iconify 名) |
priority | number | 重叠时大的先得,默认 0 |
onDrop | (kind, transfer: DataTransfer, at: DropPoint) => void | 松手时调用,at 是视口坐标 |