@lumal/icons-vue 0.0.2-beta → 0.0.4-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # @lumal/icons-vue
2
+
3
+ ## 0.0.4-beta (2026-10-20)
4
+
5
+ ### Minor Changes
6
+
7
+ - LumalIcon 增加 morph 和 morphSpring,复用通用转换并动态加载官方 Vue 绑定;SSR、减少动画或加载失败时保留静态图标。
8
+ - 图标选择器及弹窗公开 group-select 插槽与类型,允许消费应用接入 UI 分组控件,不在图标包中依赖 Element Plus。
9
+
10
+ ### Patch Changes
11
+
12
+ - 修复名称换行、弹窗分页与尺寸布局,补充选择回写、组件复用和动画清理测试。
13
+ - 同步 @lumal/icons 至 0.0.4-beta,保持静态图标不加载 Morphicons 引擎。
14
+
15
+ ## 0.0.3-beta (2026-10-16)
16
+
17
+ ### Patch Changes
18
+
19
+ - 修复直接传入 component、Iconify 和 local-svg 图标定义时的分支解析。
20
+ - 图标选择弹窗增加 Teleport、键盘焦点约束与焦点恢复,并使用 useTemplateRef。
21
+ - 明确 SVG 仅接受可信静态资源,格式校验不等于安全净化。
22
+
23
+ ## 0.0.2-beta (2026-08-01)
24
+
25
+ - Version bump only, to stay in lockstep with the other @lumal packages.
package/README.md CHANGED
@@ -14,3 +14,44 @@ import '@lumal/icons-vue/style.css'
14
14
  ```
15
15
 
16
16
  SVG 改色、渐变、合成、Data URI 和注册表等纯 TypeScript 能力由 `@lumal/icons` 提供。
17
+
18
+ ## 选择器布局
19
+
20
+ `LumalIconPicker` 的 `pageSize` 默认 48;启用 `showLabels` 时格子会加宽,名称完整换行显示。搜索和原生分组控件高度一致,默认 32px,可跟随 `--el-component-size` 调整,不引入 Element Plus 运行时。
21
+
22
+ `LumalIconPickerDialog` 每页 48 个图标,桌面为 8 列,小屏幕为 6 或 4 列,完整页面不会出现不足一行的尾行;末页按实际剩余数量展示。Admin 图标库默认每页 72 个,可切换到 96 个。
23
+
24
+ 弹窗高度随视口限制固定,搜索、分组切换或末页图标变少不会改变外框高度;头尾固定,中间内容独立滚动,并预留滚动条宽度。
25
+
26
+ ## 分组控件适配
27
+
28
+ `LumalIconPicker` 默认使用原生分组下拉框,不强制依赖 Element Plus。`LumalIconPicker` 与 `LumalIconPickerDialog` 都提供 `group-select` 插槽,接收 `{ modelValue, groups, setGroup }`;类型 `LumalIconPickerGroupSelectSlotProps` 从本包导出。
29
+
30
+ Vue + Element Plus 应用可在该插槽内使用 `ElSelect` / `ElOption`,将 `modelValue` 作为当前值,并在更新时调用 `setGroup`。弹窗中的下拉层应设置 `:teleported="false"`,避免离开弹窗的焦点边界。Element Plus 组件、样式及 `@element-plus/icons-vue` 图标集由应用自行引入,不进入两个图标包的依赖。
31
+
32
+ 分组插槽外层不使用原生 `label` 包裹,避免内联选项层选择后再次激活控件;自定义分组控件应保留 `aria-label` 等可访问名称。
33
+
34
+ Admin 已接入 Element Plus 分组控件,并将官方图标集预生成为应用侧可信 SVG,按需注册到 `element-plus` 分组。所有图标仍通过 `LumalIcon` 渲染,完整 Vue 组件图标集不进入运行时。
35
+
36
+ Admin 的 Iconify 分组预置 16 个离线示例图标,包含 15 个 Lucide 常用图标及原有徽标,支持中文搜索;数据与许可留在应用侧,不引入整套图标集依赖或远程请求。
37
+
38
+ ## 状态形变
39
+
40
+ 当前源码在同一个 `LumalIcon` 中提供可选形变;已发布版本请以安装包的声明文件为准。
41
+
42
+ ```vue
43
+ <LumalIcon :name="iconName" morph morph-spring="smooth" :size="20" />
44
+ ```
45
+
46
+ - `morph?: boolean` 默认 `false`。
47
+ - `morphSpring?: LumalIconMorphSpring` 默认 `'smooth'`;从本包导出该类型,可选 `'smooth' | 'snappy' | 'bouncy'`。
48
+ - 首次直接显示,后续形状变化才播放。保留实例,不使用 `:key="iconName"`;连续切换从中间形状继续,改色或缩放不重播。
49
+ - 支持带有效 `viewBox` 的可信单色 SVG(注册名称、直接定义、SVG 字符串)。组件、Iconify、渐变及无法保真转换的 SVG 保持静态渲染。
50
+ - 复用 `@lumal/icons/morph` 的通用转换,再按需加载 `morphicons@2.0.0` 官方 Vue 绑定;填充归一化就绪前、SSR 和加载失败时均保留原始静态 SVG。静态消费者不加载引擎,ESM/CJS 均可消费。
51
+ - 遵守系统减少动画设置,关闭、卸载和失败时清理动画。保留尺寸、颜色继承和标题;图标按钮仍需提供 `aria-label`。
52
+
53
+ 形变不限定 Vue:非 Vue 项目可使用 `@lumal/icons/morph` 的 `createIconMorph` DOM 控制器或 `prepareIconMorph` 转换数据,并安装其可选 Morphicons peer。Vue 包已将 Morphicons 作为依赖,内核静态入口仍无强制运行时依赖。SVG/Data URI 输出和选择器不受影响。
54
+
55
+ Admin 图标示例新增懒加载的“形变动画”标签,并在主题、侧栏、内容最大化和表格全屏入口使用状态形变。完整边界见仓库 `docs/icons.md`。
56
+
57
+ `LumalIcon` 接受注册名或直接 `IconDefinition`(component / iconify / local-svg)。SVG 使用 HTML 渲染,仅接受可信静态资源;注册和渲染不自动净化,单色格式校验不是完整 sanitizer。图标选择弹窗通过 Teleport 挂载到 body,约束 Tab、支持 Escape,并在关闭/卸载时恢复焦点。
@@ -1,2 +1,2 @@
1
- .lumal-icon[data-v-d5c4f92d]{width:var(--lumal-icon-size);height:var(--lumal-icon-size);vertical-align:-.125em;justify-content:center;align-items:center;line-height:1;display:inline-flex}.lumal-icon__svg[data-v-d5c4f92d],.lumal-icon__component[data-v-d5c4f92d]{width:100%;height:100%}.lumal-icon__svg[data-v-d5c4f92d] svg{width:100%;height:100%;display:block}.lumal-icon-picker[data-v-937c0d9c]{gap:12px;display:grid}.lumal-icon-picker__toolbar[data-v-937c0d9c]{grid-template-columns:minmax(0,1fr) minmax(140px,200px);gap:12px;display:grid}.lumal-icon-picker__field[data-v-937c0d9c]{gap:6px;display:grid}.lumal-icon-picker__field-label[data-v-937c0d9c],.lumal-icon-picker__summary[data-v-937c0d9c],.lumal-icon-picker__empty[data-v-937c0d9c]{color:var(--el-text-color-secondary,CanvasText);font-size:13px}.lumal-icon-picker__field input[data-v-937c0d9c],.lumal-icon-picker__field select[data-v-937c0d9c],.lumal-icon-picker__pagination button[data-v-937c0d9c]{border:1px solid var(--el-border-color,currentColor);border-radius:var(--lumal-radius-base,8px);min-height:44px;color:var(--el-text-color-primary,CanvasText);background:var(--el-bg-color,Canvas);padding:0 12px}.lumal-icon-picker__summary[data-v-937c0d9c],.lumal-icon-picker__empty[data-v-937c0d9c]{margin:0}.lumal-icon-picker__grid[data-v-937c0d9c]{grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:8px;display:grid}.lumal-icon-picker__item[data-v-937c0d9c]{border:1px solid var(--el-border-color-lighter,currentColor);border-radius:var(--lumal-radius-small,6px);min-width:44px;min-height:52px;color:var(--el-text-color-regular,CanvasText);background:var(--el-bg-color,Canvas);cursor:pointer;transition:border-color var(--lumal-motion-fast,.16s), background-color var(--lumal-motion-fast,.16s);flex-direction:column;justify-content:center;align-items:center;gap:6px;padding:8px;display:inline-flex}.lumal-icon-picker__item[data-v-937c0d9c]:hover,.lumal-icon-picker__item.is-selected[data-v-937c0d9c]{border-color:var(--el-color-primary,Highlight);background:var(--el-color-primary-light-9,Canvas)}.lumal-icon-picker__item[data-v-937c0d9c]:focus-visible,.lumal-icon-picker__field input[data-v-937c0d9c]:focus-visible,.lumal-icon-picker__field select[data-v-937c0d9c]:focus-visible,.lumal-icon-picker__pagination button[data-v-937c0d9c]:focus-visible{outline:2px solid var(--el-color-primary,Highlight);outline-offset:2px}.lumal-icon-picker__item span[data-v-937c0d9c]{text-overflow:ellipsis;white-space:nowrap;max-width:100%;font-size:11px;overflow:hidden}.lumal-icon-picker__pagination[data-v-937c0d9c]{justify-content:center;align-items:center;gap:12px;display:flex}.lumal-icon-picker__pagination button[data-v-937c0d9c]:disabled{cursor:not-allowed;opacity:.5}@media (width<=640px){.lumal-icon-picker__toolbar[data-v-937c0d9c]{grid-template-columns:minmax(0,1fr)}}@media (prefers-reduced-motion:reduce){.lumal-icon-picker__item[data-v-937c0d9c]{transition:none}}.lumal-icon-picker-dialog[data-v-9bd629e7]{z-index:var(--lumal-z-dialog,500);background:color-mix(in srgb, CanvasText 48%, transparent);justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.lumal-icon-picker-dialog__body[data-v-9bd629e7]{border-radius:var(--lumal-radius-large,12px);width:min(680px,100%);max-height:min(680px,88dvh);color:var(--el-text-color-primary,CanvasText);background:var(--el-bg-color,Canvas);box-shadow:var(--lumal-shadow-dialog,0 18px 48px color-mix(in srgb, CanvasText 18%, transparent));display:grid;overflow:hidden}.lumal-icon-picker-dialog__header[data-v-9bd629e7],.lumal-icon-picker-dialog__footer[data-v-9bd629e7]{justify-content:space-between;align-items:center;gap:12px;min-height:56px;padding:12px 20px;display:flex}.lumal-icon-picker-dialog__header[data-v-9bd629e7]{border-bottom:1px solid var(--el-border-color-lighter,currentColor)}.lumal-icon-picker-dialog__header h3[data-v-9bd629e7]{margin:0;font-size:17px}.lumal-icon-picker-dialog__content[data-v-9bd629e7]{min-height:0;padding:20px;overflow:auto}.lumal-icon-picker-dialog__footer[data-v-9bd629e7]{border-top:1px solid var(--el-border-color-lighter,currentColor);justify-content:flex-end}.lumal-icon-picker-dialog button[data-v-9bd629e7]{border:1px solid var(--el-border-color,currentColor);border-radius:var(--lumal-radius-base,8px);min-width:44px;min-height:44px;color:inherit;background:var(--el-bg-color,Canvas);cursor:pointer;padding:0 14px}.lumal-icon-picker-dialog button.is-primary[data-v-9bd629e7]{border-color:var(--el-color-primary,Highlight);color:var(--el-color-white,HighlightText);background:var(--el-color-primary,Highlight)}.lumal-icon-picker-dialog button[data-v-9bd629e7]:disabled{cursor:not-allowed;opacity:.5}@media (width<=640px){.lumal-icon-picker-dialog[data-v-9bd629e7]{align-items:flex-end;padding:0}.lumal-icon-picker-dialog__body[data-v-9bd629e7]{border-radius:var(--lumal-radius-large,12px) var(--lumal-radius-large,12px) 0 0;max-height:92dvh}}
1
+ .lumal-icon[data-v-42fa0af8]{width:var(--lumal-icon-size);height:var(--lumal-icon-size);vertical-align:-.125em;justify-content:center;align-items:center;line-height:1;display:inline-flex}.lumal-icon__svg[data-v-42fa0af8],.lumal-icon__component[data-v-42fa0af8]{width:100%;height:100%}.lumal-icon__svg[data-v-42fa0af8] svg{width:100%;height:100%;display:block}.lumal-icon-picker[data-v-0b9c266c]{gap:12px;min-width:0;display:grid}.lumal-icon-picker__toolbar[data-v-0b9c266c]{grid-template-columns:minmax(0,1fr) minmax(140px,200px);align-items:start;gap:12px;display:grid}.lumal-icon-picker__field[data-v-0b9c266c]{gap:6px;min-width:0;display:grid}.lumal-icon-picker__field-label[data-v-0b9c266c],.lumal-icon-picker__summary[data-v-0b9c266c],.lumal-icon-picker__empty[data-v-0b9c266c]{color:var(--el-text-color-secondary,CanvasText);font-size:13px}.lumal-icon-picker__field input[data-v-0b9c266c],.lumal-icon-picker__field select[data-v-0b9c266c],.lumal-icon-picker__pagination button[data-v-0b9c266c]{box-sizing:border-box;height:var(--el-component-size,32px);min-height:var(--el-component-size,32px);border:1px solid var(--el-border-color,currentColor);border-radius:var(--lumal-radius-base,8px);color:var(--el-text-color-primary,CanvasText);background:var(--el-bg-color,Canvas);font:inherit;font-size:var(--lumal-font-size-base,14px);padding:0 12px}.lumal-icon-picker__field input[data-v-0b9c266c],.lumal-icon-picker__field select[data-v-0b9c266c]{width:100%;min-width:0}.lumal-icon-picker__summary[data-v-0b9c266c],.lumal-icon-picker__empty[data-v-0b9c266c]{margin:0}.lumal-icon-picker__grid[data-v-0b9c266c]{grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:8px;display:grid}.lumal-icon-picker--show-labels .lumal-icon-picker__grid[data-v-0b9c266c]{grid-template-columns:repeat(auto-fill,minmax(min(96px,100%),1fr));grid-auto-rows:minmax(84px,auto)}.lumal-icon-picker__item[data-v-0b9c266c]{border:1px solid var(--el-border-color-lighter,currentColor);border-radius:var(--lumal-radius-small,6px);min-width:44px;min-height:52px;color:var(--el-text-color-regular,CanvasText);background:var(--el-bg-color,Canvas);cursor:pointer;transition:border-color var(--lumal-motion-fast,.16s), background-color var(--lumal-motion-fast,.16s);flex-direction:column;justify-content:center;align-items:center;gap:6px;padding:8px;display:inline-flex}.lumal-icon-picker__item[data-v-0b9c266c]:hover,.lumal-icon-picker__item.is-selected[data-v-0b9c266c]{border-color:var(--el-color-primary,Highlight);background:var(--el-color-primary-light-9,Canvas)}.lumal-icon-picker__item[data-v-0b9c266c]:focus-visible,.lumal-icon-picker__field input[data-v-0b9c266c]:focus-visible,.lumal-icon-picker__field select[data-v-0b9c266c]:focus-visible,.lumal-icon-picker__pagination button[data-v-0b9c266c]:focus-visible{outline:2px solid var(--el-color-primary,Highlight);outline-offset:2px}.lumal-icon-picker__item-label[data-v-0b9c266c]{width:100%;max-width:100%;font-size:calc(var(--lumal-font-size-base,14px) - 2px);text-align:center;white-space:normal;overflow-wrap:anywhere;line-height:1.4}.lumal-icon-picker__pagination[data-v-0b9c266c]{justify-content:center;align-items:center;gap:12px;display:flex}.lumal-icon-picker__pagination button[data-v-0b9c266c]:disabled{cursor:not-allowed;opacity:.5}@media (width<=640px){.lumal-icon-picker__toolbar[data-v-0b9c266c]{grid-template-columns:minmax(0,1fr)}}@media (prefers-reduced-motion:reduce){.lumal-icon-picker__item[data-v-0b9c266c]{transition:none}}.lumal-icon-picker-dialog[data-v-ee548916]{z-index:var(--lumal-z-dialog,500);background:color-mix(in srgb, CanvasText 48%, transparent);justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.lumal-icon-picker-dialog__body[data-v-ee548916]{border-radius:var(--lumal-radius-large,12px);width:min(680px,100%);height:min(680px,88dvh);color:var(--el-text-color-primary,CanvasText);background:var(--el-bg-color,Canvas);box-shadow:var(--lumal-shadow-dialog,0 18px 48px color-mix(in srgb, CanvasText 18%, transparent));grid-template-rows:auto minmax(0,1fr) auto;display:grid;overflow:hidden}.lumal-icon-picker-dialog__header[data-v-ee548916],.lumal-icon-picker-dialog__footer[data-v-ee548916]{justify-content:space-between;align-items:center;gap:12px;min-height:56px;padding:12px 20px;display:flex}.lumal-icon-picker-dialog__header[data-v-ee548916]{border-bottom:1px solid var(--el-border-color-lighter,currentColor)}.lumal-icon-picker-dialog__header h3[data-v-ee548916]{margin:0;font-size:17px}.lumal-icon-picker-dialog__content[data-v-ee548916]{scrollbar-gutter:stable;min-height:0;padding:20px;overflow:auto}.lumal-icon-picker-dialog__content[data-v-ee548916] .lumal-icon-picker__grid{grid-template-columns:repeat(8,minmax(0,1fr))}.lumal-icon-picker-dialog__footer[data-v-ee548916]{border-top:1px solid var(--el-border-color-lighter,currentColor);justify-content:flex-end}.lumal-icon-picker-dialog button[data-v-ee548916]{border:1px solid var(--el-border-color,currentColor);border-radius:var(--lumal-radius-base,8px);min-width:44px;min-height:44px;color:inherit;background:var(--el-bg-color,Canvas);cursor:pointer;padding:0 14px}.lumal-icon-picker-dialog button.is-primary[data-v-ee548916]{border-color:var(--el-color-primary,Highlight);color:var(--el-color-white,HighlightText);background:var(--el-color-primary,Highlight)}.lumal-icon-picker-dialog button[data-v-ee548916]:disabled{cursor:not-allowed;opacity:.5}@media (width<=640px){.lumal-icon-picker-dialog[data-v-ee548916]{align-items:flex-end;padding:0}.lumal-icon-picker-dialog__body[data-v-ee548916]{border-radius:var(--lumal-radius-large,12px) var(--lumal-radius-large,12px) 0 0;height:min(680px,92dvh)}}@media (width<=480px){.lumal-icon-picker-dialog__content[data-v-ee548916] .lumal-icon-picker__grid{grid-template-columns:repeat(6,minmax(0,1fr))}}@media (width<=360px){.lumal-icon-picker-dialog__content[data-v-ee548916] .lumal-icon-picker__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
2
2
  /*$vite$:1*/
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("vue"),t=require("@iconify/vue"),n=require("@lumal/icons");function r(){let t=(0,e.shallowRef)(0);(0,e.onScopeDispose)((0,n.subscribeIconRegistry)(()=>{t.value+=1}));let r=(0,e.computed)(()=>(t.value,(0,n.getRegisteredIconDefinitions)())),i=(0,e.computed)(()=>(t.value,(0,n.getRegisteredIconGroups)()));function a(e){return t.value,(0,n.resolveIconDefinition)(e)}return{groups:i,icons:r,resolve:a}}var i=[`title`],a=[`innerHTML`],o=(0,e.defineComponent)({__name:`LumalIcon`,props:{name:{},icon:{},size:{},color:{},gradient:{},title:{}},setup(o){let s=o,c=`lumal-icon-gradient-${(0,e.useId)()}`,l=r(),u=(0,e.computed)(()=>{if(s.name)return l.resolve(s.name)}),d=(0,e.computed)(()=>{let e=s.icon,t=u.value?.svgText??(typeof e==`string`&&e.trim().startsWith(`<svg`)?e:``)??(typeof e==`object`&&e&&`svgText`in e?String(e.svgText??``):``);return t?s.gradient?(0,n.applySvgGradient)(t,{...s.gradient,id:s.gradient.id??c}):(0,n.recolorSvgString)(t,s.color):``}),f=(0,e.computed)(()=>{let e=u.value?.component;if(typeof e==`function`||typeof e==`object`&&e)return e;if(typeof s.icon==`object`&&s.icon&&`component`in s.icon){let e=s.icon.component;return typeof e==`function`||typeof e==`object`&&e?e:void 0}return typeof s.icon==`function`||typeof s.icon==`object`?s.icon:void 0}),p=(0,e.computed)(()=>{if(u.value?.source===`iconify`)return u.value.icon;if(typeof s.icon==`object`&&s.icon&&`source`in s.icon&&s.icon.source===`iconify`)return s.icon.icon}),m=(0,e.computed)(()=>({"--lumal-icon-size":typeof s.size==`number`?`${s.size}px`:s.size??`1em`,color:s.color})),h=(0,e.computed)(()=>!!(d.value||f.value||p.value)),g=(0,e.computed)(()=>s.title??u.value?.label);return(n,r)=>h.value?((0,e.openBlock)(),(0,e.createElementBlock)(`span`,{key:0,class:`lumal-icon`,style:(0,e.normalizeStyle)(m.value),title:g.value,"aria-hidden":`true`},[f.value?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(f.value),{key:0,class:`lumal-icon__component`})):p.value?((0,e.openBlock)(),(0,e.createBlock)((0,e.unref)(t.Icon),{key:1,class:`lumal-icon__component`,icon:p.value},null,8,[`icon`])):((0,e.openBlock)(),(0,e.createElementBlock)(`span`,{key:2,class:`lumal-icon__svg`,innerHTML:d.value},null,8,a))],12,i)):(0,e.createCommentVNode)(``,!0)}}),s=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},c=s(o,[[`__scopeId`,`data-v-d5c4f92d`]]),l={class:`lumal-icon-picker`},u={class:`lumal-icon-picker__toolbar`},d={key:0,class:`lumal-icon-picker__field`},f={key:1,class:`lumal-icon-picker__field`},p=[`value`],m={class:`lumal-icon-picker__summary`,role:`status`},h={key:0,class:`lumal-icon-picker__grid`,role:`listbox`,"aria-label":`图标列表`},g=[`aria-label`,`aria-selected`,`title`,`onClick`],_={key:0},v={key:1,class:`lumal-icon-picker__empty`},y={key:2,class:`lumal-icon-picker__pagination`},b=[`disabled`],x=[`disabled`],S=s((0,e.defineComponent)({__name:`LumalIconPicker`,props:(0,e.mergeModels)({group:{default:``},pageSize:{default:48},searchable:{type:Boolean,default:!0},showLabels:{type:Boolean,default:!1},storageKey:{default:``}},{modelValue:{},modelModifiers:{}}),emits:(0,e.mergeModels)([`select`],[`update:modelValue`]),setup(t,{emit:n}){let i=t,a=n,o=(0,e.useModel)(t,`modelValue`),s=(0,e.ref)(``),S=(0,e.ref)(i.group),C=(0,e.ref)(1),w=(0,e.computed)(()=>Math.max(1,i.pageSize)),T=r(),E=T.icons,D=(0,e.computed)(()=>{let e=T.groups.value,t=new Set(e.map(e=>e.key)),n=E.value.map(e=>e.group).filter(e=>typeof e==`string`&&!t.has(e)).filter((e,t,n)=>n.indexOf(e)===t).map(e=>({key:e,label:e}));return[...e,...n]}),O=(0,e.computed)(()=>{let e=s.value.trim().toLocaleLowerCase();return E.value.filter(t=>{let n=!S.value||t.group===S.value,r=!e||t.key.toLocaleLowerCase().includes(e)||t.label?.toLocaleLowerCase().includes(e);return n&&r})}),k=(0,e.computed)(()=>Math.max(1,Math.ceil(O.value.length/w.value))),A=(0,e.computed)(()=>{let e=(C.value-1)*w.value;return O.value.slice(e,e+w.value)});(0,e.watch)([s,S,w],()=>{C.value=1}),(0,e.watch)(()=>i.group,e=>{S.value=e}),(0,e.watch)(k,e=>{C.value=Math.min(C.value,e)}),i.storageKey&&typeof localStorage<`u`&&!o.value&&(o.value=localStorage.getItem(i.storageKey)??void 0);function j(e){o.value=e.key,i.storageKey&&typeof localStorage<`u`&&localStorage.setItem(i.storageKey,e.key),a(`select`,e)}return(n,r)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,l,[(0,e.createElementVNode)(`div`,u,[t.searchable?((0,e.openBlock)(),(0,e.createElementBlock)(`label`,d,[r[4]||=(0,e.createElementVNode)(`span`,{class:`lumal-icon-picker__field-label`},`搜索图标`,-1),(0,e.withDirectives)((0,e.createElementVNode)(`input`,{"onUpdate:modelValue":r[0]||=e=>s.value=e,type:`search`,placeholder:`输入名称或 key`},null,512),[[e.vModelText,s.value]])])):(0,e.createCommentVNode)(``,!0),D.value.length?((0,e.openBlock)(),(0,e.createElementBlock)(`label`,f,[r[6]||=(0,e.createElementVNode)(`span`,{class:`lumal-icon-picker__field-label`},`图标分组`,-1),(0,e.withDirectives)((0,e.createElementVNode)(`select`,{"onUpdate:modelValue":r[1]||=e=>S.value=e},[r[5]||=(0,e.createElementVNode)(`option`,{value:``},`全部分组`,-1),((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(D.value,t=>((0,e.openBlock)(),(0,e.createElementBlock)(`option`,{key:t.key,value:t.key},(0,e.toDisplayString)(t.label),9,p))),128))],512),[[e.vModelSelect,S.value]])])):(0,e.createCommentVNode)(``,!0)]),(0,e.createElementVNode)(`p`,m,` 共 `+(0,e.toDisplayString)(O.value.length)+` 个图标 `,1),A.value.length?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,h,[((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(A.value,n=>((0,e.openBlock)(),(0,e.createElementBlock)(`button`,{key:n.key,class:(0,e.normalizeClass)([`lumal-icon-picker__item`,{"is-selected":o.value===n.key}]),type:`button`,role:`option`,"aria-label":n.label||n.key,"aria-selected":o.value===n.key,title:n.label||n.key,onClick:e=>j(n)},[(0,e.createVNode)(c,{name:n.key},null,8,[`name`]),t.showLabels?((0,e.openBlock)(),(0,e.createElementBlock)(`span`,_,(0,e.toDisplayString)(n.label||n.key),1)):(0,e.createCommentVNode)(``,!0)],10,g))),128))])):((0,e.openBlock)(),(0,e.createElementBlock)(`p`,v,` 未找到匹配图标 `)),k.value>1?((0,e.openBlock)(),(0,e.createElementBlock)(`footer`,y,[(0,e.createElementVNode)(`button`,{type:`button`,disabled:C.value<=1,onClick:r[2]||=e=>--C.value},` 上一页 `,8,b),(0,e.createElementVNode)(`span`,null,`第 `+(0,e.toDisplayString)(C.value)+` / `+(0,e.toDisplayString)(k.value)+` 页`,1),(0,e.createElementVNode)(`button`,{type:`button`,disabled:C.value>=k.value,onClick:r[3]||=e=>C.value+=1},` 下一页 `,8,x)])):(0,e.createCommentVNode)(``,!0)]))}}),[[`__scopeId`,`data-v-937c0d9c`]]),C=[`aria-label`],w={class:`lumal-icon-picker-dialog__header`},T={class:`lumal-icon-picker-dialog__content`},E={class:`lumal-icon-picker-dialog__footer`},D=[`disabled`],O=s((0,e.defineComponent)({__name:`LumalIconPickerDialog`,props:(0,e.mergeModels)({cancelText:{default:`取消`},confirmText:{default:`确认选择`},title:{default:`选择图标`}},{visible:{type:Boolean,default:!1},visibleModifiers:{},modelValue:{},modelModifiers:{}}),emits:(0,e.mergeModels)([`cancel`,`confirm`],[`update:visible`,`update:modelValue`]),setup(t,{emit:n}){let r=n,i=(0,e.useModel)(t,`visible`),a=(0,e.useModel)(t,`modelValue`),o=(0,e.ref)(``),s=(0,e.ref)();(0,e.watch)(i,async t=>{t&&(o.value=a.value??``,await(0,e.nextTick)(),s.value?.focus())},{immediate:!0});function c(){i.value=!1,r(`cancel`)}function l(){o.value&&(a.value=o.value,i.value=!1,r(`confirm`,o.value))}return(n,r)=>i.value?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{key:0,class:`lumal-icon-picker-dialog`,role:`presentation`,onMousedown:(0,e.withModifiers)(c,[`self`])},[(0,e.createElementVNode)(`section`,{ref_key:`dialogRef`,ref:s,class:`lumal-icon-picker-dialog__body`,role:`dialog`,"aria-modal":`true`,"aria-label":t.title,tabindex:`-1`,onKeydown:(0,e.withKeys)(c,[`esc`])},[(0,e.createElementVNode)(`header`,w,[(0,e.createElementVNode)(`h3`,null,(0,e.toDisplayString)(t.title),1),(0,e.createElementVNode)(`button`,{type:`button`,"aria-label":`关闭图标选择器`,onClick:c},` × `)]),(0,e.createElementVNode)(`div`,T,[(0,e.createVNode)(S,{modelValue:o.value,"onUpdate:modelValue":r[0]||=e=>o.value=e},null,8,[`modelValue`])]),(0,e.createElementVNode)(`footer`,E,[(0,e.createElementVNode)(`button`,{type:`button`,onClick:c},(0,e.toDisplayString)(t.cancelText),1),(0,e.createElementVNode)(`button`,{type:`button`,class:`is-primary`,disabled:!o.value,onClick:l},(0,e.toDisplayString)(t.confirmText),9,D)])],40,C)],32)):(0,e.createCommentVNode)(``,!0)}}),[[`__scopeId`,`data-v-9bd629e7`]]);exports.LumalIcon=c,exports.LumalIconPicker=S,exports.LumalIconPickerDialog=O,exports.useIconRegistry=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("vue"),t=require("@iconify/vue"),n=require("@lumal/icons"),r=require("@lumal/icons/morph");var i;function a(){return i??=import(`morphicons/vue`).then(e=>({MorphIcon:e.MorphIcon})).catch(e=>{throw i=void 0,e}),i}function o(t,n){let i=(0,e.shallowRef)(!1),o=(0,e.shallowRef)(!1),s=(0,e.shallowRef)(),c;return(0,e.onMounted)(()=>{i.value=!0}),(0,e.watch)([i,()=>(0,e.toValue)(n)],([e,t],n,r)=>{if(o.value=!1,!e||!t)return;let i=typeof window.matchMedia==`function`?window.matchMedia(`(prefers-reduced-motion: reduce)`):void 0,a=()=>{o.value=i?.matches??!1};a(),typeof i?.addEventListener==`function`?i.addEventListener(`change`,a):i?.addListener?.(a),r(()=>{typeof i?.removeEventListener==`function`?i.removeEventListener(`change`,a):i?.removeListener?.(a)})},{flush:`sync`}),(0,e.watch)([i,o,()=>(0,e.toValue)(t),()=>(0,e.toValue)(n)],async([e,t,n,i],o,l)=>{let u=!1;if(l(()=>{u=!0}),!e||t||!i||!n){s.value=void 0;return}try{let e=await(0,r.prepareIconMorph)(n);if(u)return;if(!e){s.value=void 0;return}if(c??=await a(),u)return;s.value={...e,icon:s.value?.shape===e.shape?s.value.icon:e.icon,component:c.MorphIcon}}catch{u||(s.value=void 0)}},{immediate:!0}),{state:s,reset:()=>{s.value=void 0}}}function s(){let t=(0,e.shallowRef)(0);(0,e.onScopeDispose)((0,n.subscribeIconRegistry)(()=>{t.value+=1}));let r=(0,e.computed)(()=>(t.value,(0,n.getRegisteredIconDefinitions)())),i=(0,e.computed)(()=>(t.value,(0,n.getRegisteredIconGroups)()));function a(e){return t.value,(0,n.resolveIconDefinition)(e)}return{groups:i,icons:r,resolve:a}}var c=[`title`],l=[`innerHTML`],u=(0,e.defineComponent)({__name:`LumalIcon`,props:{name:{},icon:{},size:{},color:{},gradient:{},title:{},morph:{type:Boolean},morphSpring:{}},setup(r){let i=r,a=`lumal-icon-gradient-${(0,e.useId)()}`,u=s(),d=(0,e.computed)(()=>{let e=i.name?u.resolve(i.name):void 0;if(e)return e;let t=i.icon;return t&&typeof t==`object`&&`source`in t&&`key`in t?t:void 0}),f=(0,e.computed)(()=>{let e=i.icon;return d.value?.svgText??(typeof e==`string`&&e.trim().startsWith(`<svg`)?e:``)}),p=(0,e.computed)(()=>{let e=f.value;return e?i.gradient?(0,n.applySvgGradient)(e,{...i.gradient,id:i.gradient.id??a}):(0,n.recolorSvgString)(e,i.color):``}),m=(0,e.computed)(()=>{if(d.value){let t=d.value.source===`component`?d.value.component:void 0;return typeof t==`function`||typeof t==`object`&&t?(0,e.toRaw)(t):void 0}return typeof i.icon==`function`||typeof i.icon==`object`?(0,e.toRaw)(i.icon):void 0}),h=(0,e.computed)(()=>{if(d.value?.source===`iconify`)return d.value.icon}),{state:g,reset:_}=o(f,()=>i.morph===!0&&!i.gradient&&!m.value&&!h.value);(0,e.onErrorCaptured)(()=>{if(g.value)return _(),!1});let v=(0,e.computed)(()=>({"--lumal-icon-size":typeof i.size==`number`?`${i.size}px`:i.size??`1em`,color:i.color})),y=(0,e.computed)(()=>!!(p.value||m.value||h.value)),b=(0,e.computed)(()=>i.title??d.value?.label);return(n,i)=>y.value?((0,e.openBlock)(),(0,e.createElementBlock)(`span`,{key:0,class:`lumal-icon`,style:(0,e.normalizeStyle)(v.value),title:b.value,"aria-hidden":`true`},[m.value?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(m.value),{key:0,class:`lumal-icon__component`})):h.value?((0,e.openBlock)(),(0,e.createBlock)((0,e.unref)(t.Icon),{key:1,class:`lumal-icon__component`,icon:h.value},null,8,[`icon`])):(0,e.unref)(g)?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)((0,e.unref)(g).component),{key:2,class:`lumal-icon__component`,icon:(0,e.unref)(g).icon,spring:r.morphSpring??`smooth`,color:(0,e.unref)(g).color,"stroke-width":(0,e.unref)(g).strokeWidth,"stroke-linecap":(0,e.unref)(g).linecap,"stroke-linejoin":(0,e.unref)(g).linejoin,"reduced-motion":`user`,size:`100%`},null,8,[`icon`,`spring`,`color`,`stroke-width`,`stroke-linecap`,`stroke-linejoin`])):((0,e.openBlock)(),(0,e.createElementBlock)(`span`,{key:3,class:`lumal-icon__svg`,innerHTML:p.value},null,8,l))],12,c)):(0,e.createCommentVNode)(``,!0)}}),d=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},f=d(u,[[`__scopeId`,`data-v-42fa0af8`]]),p={class:`lumal-icon-picker__toolbar`},m={key:0,class:`lumal-icon-picker__field`},h={key:1,class:`lumal-icon-picker__field`},g=[`value`],_={class:`lumal-icon-picker__summary`,role:`status`},v={key:0,class:`lumal-icon-picker__grid`,role:`listbox`,"aria-label":`图标列表`},y=[`aria-label`,`aria-selected`,`title`,`onClick`],b={key:0,class:`lumal-icon-picker__item-label`},x={key:1,class:`lumal-icon-picker__empty`},S={key:2,class:`lumal-icon-picker__pagination`},C=[`disabled`],w=[`disabled`],T=d((0,e.defineComponent)({__name:`LumalIconPicker`,props:(0,e.mergeModels)({group:{default:``},pageSize:{default:48},searchable:{type:Boolean,default:!0},showLabels:{type:Boolean,default:!1},storageKey:{default:``}},{modelValue:{},modelModifiers:{}}),emits:(0,e.mergeModels)([`select`],[`update:modelValue`]),setup(t,{emit:n}){let r=t,i=n,a=(0,e.useModel)(t,`modelValue`),o=(0,e.shallowRef)(``),c=(0,e.shallowRef)(r.group),l=(0,e.shallowRef)(1),u=(0,e.computed)(()=>Math.max(1,r.pageSize)),d=s(),T=d.icons,E=(0,e.computed)(()=>{let e=d.groups.value,t=new Set(e.map(e=>e.key)),n=T.value.map(e=>e.group).filter(e=>typeof e==`string`&&!t.has(e)).filter((e,t,n)=>n.indexOf(e)===t).map(e=>({key:e,label:e}));return[...e,...n]}),D=(0,e.computed)(()=>{let e=o.value.trim().toLocaleLowerCase();return T.value.filter(t=>{let n=!c.value||t.group===c.value,r=!e||t.key.toLocaleLowerCase().includes(e)||t.label?.toLocaleLowerCase().includes(e);return n&&r})}),O=(0,e.computed)(()=>Math.max(1,Math.ceil(D.value.length/u.value))),k=(0,e.computed)(()=>{let e=(l.value-1)*u.value;return D.value.slice(e,e+u.value)});function A(e){c.value=e}(0,e.watch)([o,c,u],()=>{l.value=1}),(0,e.watch)(()=>r.group,e=>{c.value=e}),(0,e.watch)(O,e=>{l.value=Math.min(l.value,e)}),r.storageKey&&typeof localStorage<`u`&&!a.value&&(a.value=localStorage.getItem(r.storageKey)??void 0);function j(e){a.value=e.key,r.storageKey&&typeof localStorage<`u`&&localStorage.setItem(r.storageKey,e.key),i(`select`,e)}return(n,r)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{class:(0,e.normalizeClass)([`lumal-icon-picker`,{"lumal-icon-picker--show-labels":t.showLabels}])},[(0,e.createElementVNode)(`div`,p,[t.searchable?((0,e.openBlock)(),(0,e.createElementBlock)(`label`,m,[r[4]||=(0,e.createElementVNode)(`span`,{class:`lumal-icon-picker__field-label`},`搜索图标`,-1),(0,e.withDirectives)((0,e.createElementVNode)(`input`,{"onUpdate:modelValue":r[0]||=e=>o.value=e,type:`search`,"aria-label":`搜索图标`,placeholder:`输入名称或 key`},null,512),[[e.vModelText,o.value]])])):(0,e.createCommentVNode)(``,!0),E.value.length?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,h,[r[6]||=(0,e.createElementVNode)(`span`,{class:`lumal-icon-picker__field-label`},`图标分组`,-1),(0,e.renderSlot)(n.$slots,`group-select`,{modelValue:c.value,groups:E.value,setGroup:A},()=>[(0,e.withDirectives)((0,e.createElementVNode)(`select`,{"onUpdate:modelValue":r[1]||=e=>c.value=e,"aria-label":`图标分组`},[r[5]||=(0,e.createElementVNode)(`option`,{value:``},` 全部分组 `,-1),((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(E.value,t=>((0,e.openBlock)(),(0,e.createElementBlock)(`option`,{key:t.key,value:t.key},(0,e.toDisplayString)(t.label),9,g))),128))],512),[[e.vModelSelect,c.value]])],!0)])):(0,e.createCommentVNode)(``,!0)]),(0,e.createElementVNode)(`p`,_,` 共 `+(0,e.toDisplayString)(D.value.length)+` 个图标 `,1),k.value.length?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,v,[((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(k.value,n=>((0,e.openBlock)(),(0,e.createElementBlock)(`button`,{key:n.key,class:(0,e.normalizeClass)([`lumal-icon-picker__item`,{"is-selected":a.value===n.key}]),type:`button`,role:`option`,"aria-label":n.label||n.key,"aria-selected":a.value===n.key,title:n.label||n.key,onClick:e=>j(n)},[(0,e.createVNode)(f,{name:n.key,size:28},null,8,[`name`]),t.showLabels?((0,e.openBlock)(),(0,e.createElementBlock)(`span`,b,(0,e.toDisplayString)(n.label||n.key),1)):(0,e.createCommentVNode)(``,!0)],10,y))),128))])):((0,e.openBlock)(),(0,e.createElementBlock)(`p`,x,` 未找到匹配图标 `)),O.value>1?((0,e.openBlock)(),(0,e.createElementBlock)(`footer`,S,[(0,e.createElementVNode)(`button`,{type:`button`,disabled:l.value<=1,onClick:r[2]||=e=>--l.value},` 上一页 `,8,C),(0,e.createElementVNode)(`span`,null,`第 `+(0,e.toDisplayString)(l.value)+` / `+(0,e.toDisplayString)(O.value)+` 页`,1),(0,e.createElementVNode)(`button`,{type:`button`,disabled:l.value>=O.value,onClick:r[3]||=e=>l.value+=1},` 下一页 `,8,w)])):(0,e.createCommentVNode)(``,!0)],2))}}),[[`__scopeId`,`data-v-0b9c266c`]]),E=[`aria-label`],D={class:`lumal-icon-picker-dialog__header`},O={class:`lumal-icon-picker-dialog__content`},k={class:`lumal-icon-picker-dialog__footer`},A=[`disabled`],j=d((0,e.defineComponent)({__name:`LumalIconPickerDialog`,props:(0,e.mergeModels)({cancelText:{default:`取消`},confirmText:{default:`确认选择`},title:{default:`选择图标`}},{visible:{type:Boolean,default:!1},visibleModifiers:{},modelValue:{},modelModifiers:{}}),emits:(0,e.mergeModels)([`cancel`,`confirm`],[`update:visible`,`update:modelValue`]),setup(t,{emit:n}){let r=n,i=(0,e.useModel)(t,`visible`),a=(0,e.useModel)(t,`modelValue`),o=(0,e.shallowRef)(``),s=(0,e.useTemplateRef)(`dialogRef`),c;function l(e){i.value&&s.value&&!s.value.contains(e.target)&&s.value.focus()}function u(e){if(e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),d()),e.key!==`Tab`)return;let t=[...s.value?.querySelectorAll(`button, input, select, textarea, a[href], [tabindex]`)??[]].filter(e=>e.tabIndex>=0&&!e.matches(`:disabled`)&&!e.closest(`[hidden], [inert]`)),n=t[0],r=t.at(-1);(!n||(e.shiftKey?document.activeElement===n||document.activeElement===s.value:document.activeElement===r||document.activeElement===s.value))&&(e.preventDefault(),(e.shiftKey?r:n)?.focus())}(0,e.watch)(i,async t=>{if(!(typeof document>`u`)){if(!t){document.removeEventListener(`focusin`,l);let t=c;await(0,e.nextTick)(),!i.value&&t?.isConnected&&t.focus();return}c=document.activeElement instanceof HTMLElement?document.activeElement:void 0,o.value=a.value??``,await(0,e.nextTick)(),i.value&&(s.value?.focus(),document.addEventListener(`focusin`,l))}},{immediate:!0}),(0,e.onBeforeUnmount)(()=>{document.removeEventListener(`focusin`,l),c?.isConnected&&c.focus()});function d(){i.value=!1,r(`cancel`)}function p(){o.value&&(a.value=o.value,i.value=!1,r(`confirm`,o.value))}return(n,r)=>((0,e.openBlock)(),(0,e.createBlock)(e.Teleport,{to:`body`},[i.value?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{key:0,class:`lumal-icon-picker-dialog`,role:`presentation`,onMousedown:(0,e.withModifiers)(d,[`self`])},[(0,e.createElementVNode)(`section`,{ref_key:`dialogRef`,ref:s,class:`lumal-icon-picker-dialog__body`,role:`dialog`,"aria-modal":`true`,"aria-label":t.title,tabindex:`-1`,onKeydown:u},[(0,e.createElementVNode)(`header`,D,[(0,e.createElementVNode)(`h3`,null,(0,e.toDisplayString)(t.title),1),(0,e.createElementVNode)(`button`,{type:`button`,"aria-label":`关闭图标选择器`,title:`关闭图标选择器`,onClick:d},[(0,e.createVNode)(f,{name:`lumal:close`,size:18})])]),(0,e.createElementVNode)(`div`,O,[(0,e.createVNode)(T,{modelValue:o.value,"onUpdate:modelValue":r[0]||=e=>o.value=e},(0,e.createSlots)({_:2},[n.$slots[`group-select`]?{name:`group-select`,fn:(0,e.withCtx)(t=>[(0,e.renderSlot)(n.$slots,`group-select`,(0,e.normalizeProps)((0,e.guardReactiveProps)(t)),void 0,!0)]),key:`0`}:void 0]),1032,[`modelValue`])]),(0,e.createElementVNode)(`footer`,k,[(0,e.createElementVNode)(`button`,{type:`button`,onClick:d},(0,e.toDisplayString)(t.cancelText),1),(0,e.createElementVNode)(`button`,{type:`button`,class:`is-primary`,disabled:!o.value,onClick:p},(0,e.toDisplayString)(t.confirmText),9,A)])],40,E)],32)):(0,e.createCommentVNode)(``,!0)]))}}),[[`__scopeId`,`data-v-ee548916`]]);exports.LumalIcon=f,exports.LumalIconPicker=T,exports.LumalIconPickerDialog=j,exports.useIconRegistry=s;
package/dist/index.js CHANGED
@@ -1,25 +1,84 @@
1
- import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createVNode as o, defineComponent as s, mergeModels as c, nextTick as l, normalizeClass as u, normalizeStyle as d, onScopeDispose as f, openBlock as p, ref as m, renderList as h, resolveDynamicComponent as g, shallowRef as _, toDisplayString as v, unref as y, useId as b, useModel as x, vModelSelect as S, vModelText as C, watch as w, withDirectives as T, withKeys as E, withModifiers as D } from "vue";
2
- import { Icon as O } from "@iconify/vue";
3
- import { applySvgGradient as k, getRegisteredIconDefinitions as A, getRegisteredIconGroups as j, recolorSvgString as M, resolveIconDefinition as N, subscribeIconRegistry as ee } from "@lumal/icons";
1
+ import { Fragment as e, Teleport as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createSlots as s, createVNode as c, defineComponent as l, guardReactiveProps as u, mergeModels as d, nextTick as f, normalizeClass as p, normalizeProps as m, normalizeStyle as h, onBeforeUnmount as g, onErrorCaptured as _, onMounted as v, onScopeDispose as y, openBlock as b, renderList as x, renderSlot as S, resolveDynamicComponent as C, shallowRef as w, toDisplayString as T, toRaw as E, toValue as D, unref as O, useId as k, useModel as A, useTemplateRef as ee, vModelSelect as j, vModelText as M, watch as N, withCtx as te, withDirectives as P, withModifiers as ne } from "vue";
2
+ import { Icon as F } from "@iconify/vue";
3
+ import { applySvgGradient as I, getRegisteredIconDefinitions as L, getRegisteredIconGroups as R, recolorSvgString as z, resolveIconDefinition as B, subscribeIconRegistry as V } from "@lumal/icons";
4
+ import { prepareIconMorph as H } from "@lumal/icons/morph";
5
+ //#region src/runtime/morph.ts
6
+ var U;
7
+ function W() {
8
+ return U ??= import("morphicons/vue").then((e) => ({ MorphIcon: e.MorphIcon })).catch((e) => {
9
+ throw U = void 0, e;
10
+ }), U;
11
+ }
12
+ //#endregion
13
+ //#region src/composables/useIconMorph.ts
14
+ function G(e, t) {
15
+ let n = w(!1), r = w(!1), i = w(), a;
16
+ return v(() => {
17
+ n.value = !0;
18
+ }), N([n, () => D(t)], ([e, t], n, i) => {
19
+ if (r.value = !1, !e || !t) return;
20
+ let a = typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : void 0, o = () => {
21
+ r.value = a?.matches ?? !1;
22
+ };
23
+ o(), typeof a?.addEventListener == "function" ? a.addEventListener("change", o) : a?.addListener?.(o), i(() => {
24
+ typeof a?.removeEventListener == "function" ? a.removeEventListener("change", o) : a?.removeListener?.(o);
25
+ });
26
+ }, { flush: "sync" }), N([
27
+ n,
28
+ r,
29
+ () => D(e),
30
+ () => D(t)
31
+ ], async ([e, t, n, r], o, s) => {
32
+ let c = !1;
33
+ if (s(() => {
34
+ c = !0;
35
+ }), !e || t || !r || !n) {
36
+ i.value = void 0;
37
+ return;
38
+ }
39
+ try {
40
+ let e = await H(n);
41
+ if (c) return;
42
+ if (!e) {
43
+ i.value = void 0;
44
+ return;
45
+ }
46
+ if (a ??= await W(), c) return;
47
+ i.value = {
48
+ ...e,
49
+ icon: i.value?.shape === e.shape ? i.value.icon : e.icon,
50
+ component: a.MorphIcon
51
+ };
52
+ } catch {
53
+ c || (i.value = void 0);
54
+ }
55
+ }, { immediate: !0 }), {
56
+ state: i,
57
+ reset: () => {
58
+ i.value = void 0;
59
+ }
60
+ };
61
+ }
62
+ //#endregion
4
63
  //#region src/composables/useIconRegistry.ts
5
- function P() {
6
- let e = _(0);
7
- f(ee(() => {
64
+ function K() {
65
+ let e = w(0);
66
+ y(V(() => {
8
67
  e.value += 1;
9
68
  }));
10
- let n = t(() => (e.value, A())), r = t(() => (e.value, j()));
69
+ let t = n(() => (e.value, L())), r = n(() => (e.value, R()));
11
70
  function i(t) {
12
- return e.value, N(t);
71
+ return e.value, B(t);
13
72
  }
14
73
  return {
15
74
  groups: r,
16
- icons: n,
75
+ icons: t,
17
76
  resolve: i
18
77
  };
19
78
  }
20
79
  //#endregion
21
80
  //#region src/components/LumalIcon.vue?vue&type=script&setup=true&lang.ts
22
- var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
81
+ var q = ["title"], J = ["innerHTML"], Y = /*@__PURE__*/ l({
23
82
  __name: "LumalIcon",
24
83
  props: {
25
84
  name: {},
@@ -27,83 +86,113 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
27
86
  size: {},
28
87
  color: {},
29
88
  gradient: {},
30
- title: {}
89
+ title: {},
90
+ morph: { type: Boolean },
91
+ morphSpring: {}
31
92
  },
32
93
  setup(e) {
33
- let a = e, o = `lumal-icon-gradient-${b()}`, s = P(), c = t(() => {
34
- if (a.name) return s.resolve(a.name);
35
- }), l = t(() => {
36
- let e = a.icon, t = c.value?.svgText ?? (typeof e == "string" && e.trim().startsWith("<svg") ? e : "") ?? (typeof e == "object" && e && "svgText" in e ? String(e.svgText ?? "") : "");
37
- return t ? a.gradient ? k(t, {
38
- ...a.gradient,
39
- id: a.gradient.id ?? o
40
- }) : M(t, a.color) : "";
41
- }), u = t(() => {
42
- let e = c.value?.component;
43
- if (typeof e == "function" || typeof e == "object" && e) return e;
44
- if (typeof a.icon == "object" && a.icon && "component" in a.icon) {
45
- let e = a.icon.component;
46
- return typeof e == "function" || typeof e == "object" && e ? e : void 0;
94
+ let t = e, o = `lumal-icon-gradient-${k()}`, s = K(), c = n(() => {
95
+ let e = t.name ? s.resolve(t.name) : void 0;
96
+ if (e) return e;
97
+ let n = t.icon;
98
+ return n && typeof n == "object" && "source" in n && "key" in n ? n : void 0;
99
+ }), l = n(() => {
100
+ let e = t.icon;
101
+ return c.value?.svgText ?? (typeof e == "string" && e.trim().startsWith("<svg") ? e : "");
102
+ }), u = n(() => {
103
+ let e = l.value;
104
+ return e ? t.gradient ? I(e, {
105
+ ...t.gradient,
106
+ id: t.gradient.id ?? o
107
+ }) : z(e, t.color) : "";
108
+ }), d = n(() => {
109
+ if (c.value) {
110
+ let e = c.value.source === "component" ? c.value.component : void 0;
111
+ return typeof e == "function" || typeof e == "object" && e ? E(e) : void 0;
47
112
  }
48
- return typeof a.icon == "function" || typeof a.icon == "object" ? a.icon : void 0;
49
- }), f = t(() => {
113
+ return typeof t.icon == "function" || typeof t.icon == "object" ? E(t.icon) : void 0;
114
+ }), f = n(() => {
50
115
  if (c.value?.source === "iconify") return c.value.icon;
51
- if (typeof a.icon == "object" && a.icon && "source" in a.icon && a.icon.source === "iconify") return a.icon.icon;
52
- }), m = t(() => ({
53
- "--lumal-icon-size": typeof a.size == "number" ? `${a.size}px` : a.size ?? "1em",
54
- color: a.color
55
- })), h = t(() => !!(l.value || u.value || f.value)), _ = t(() => a.title ?? c.value?.label);
56
- return (e, t) => h.value ? (p(), i("span", {
116
+ }), { state: p, reset: m } = G(l, () => t.morph === !0 && !t.gradient && !d.value && !f.value);
117
+ _(() => {
118
+ if (p.value) return m(), !1;
119
+ });
120
+ let g = n(() => ({
121
+ "--lumal-icon-size": typeof t.size == "number" ? `${t.size}px` : t.size ?? "1em",
122
+ color: t.color
123
+ })), v = n(() => !!(u.value || d.value || f.value)), y = n(() => t.title ?? c.value?.label);
124
+ return (t, n) => v.value ? (b(), a("span", {
57
125
  key: 0,
58
126
  class: "lumal-icon",
59
- style: d(m.value),
60
- title: _.value,
127
+ style: h(g.value),
128
+ title: y.value,
61
129
  "aria-hidden": "true"
62
- }, [u.value ? (p(), n(g(u.value), {
130
+ }, [d.value ? (b(), r(C(d.value), {
63
131
  key: 0,
64
132
  class: "lumal-icon__component"
65
- })) : f.value ? (p(), n(y(O), {
133
+ })) : f.value ? (b(), r(O(F), {
66
134
  key: 1,
67
135
  class: "lumal-icon__component",
68
136
  icon: f.value
69
- }, null, 8, ["icon"])) : (p(), i("span", {
137
+ }, null, 8, ["icon"])) : O(p) ? (b(), r(C(O(p).component), {
70
138
  key: 2,
139
+ class: "lumal-icon__component",
140
+ icon: O(p).icon,
141
+ spring: e.morphSpring ?? "smooth",
142
+ color: O(p).color,
143
+ "stroke-width": O(p).strokeWidth,
144
+ "stroke-linecap": O(p).linecap,
145
+ "stroke-linejoin": O(p).linejoin,
146
+ "reduced-motion": "user",
147
+ size: "100%"
148
+ }, null, 8, [
149
+ "icon",
150
+ "spring",
151
+ "color",
152
+ "stroke-width",
153
+ "stroke-linecap",
154
+ "stroke-linejoin"
155
+ ])) : (b(), a("span", {
156
+ key: 3,
71
157
  class: "lumal-icon__svg",
72
- innerHTML: l.value
73
- }, null, 8, I))], 12, F)) : r("", !0);
158
+ innerHTML: u.value
159
+ }, null, 8, J))], 12, q)) : i("", !0);
74
160
  }
75
- }), R = (e, t) => {
161
+ }), X = (e, t) => {
76
162
  let n = e.__vccOpts || e;
77
163
  for (let [e, r] of t) n[e] = r;
78
164
  return n;
79
- }, z = /*#__PURE__*/ R(L, [["__scopeId", "data-v-d5c4f92d"]]), B = { class: "lumal-icon-picker" }, V = { class: "lumal-icon-picker__toolbar" }, H = {
165
+ }, Z = /*#__PURE__*/ X(Y, [["__scopeId", "data-v-42fa0af8"]]), re = { class: "lumal-icon-picker__toolbar" }, ie = {
80
166
  key: 0,
81
167
  class: "lumal-icon-picker__field"
82
- }, U = {
168
+ }, ae = {
83
169
  key: 1,
84
170
  class: "lumal-icon-picker__field"
85
- }, W = ["value"], G = {
171
+ }, oe = ["value"], se = {
86
172
  class: "lumal-icon-picker__summary",
87
173
  role: "status"
88
- }, K = {
174
+ }, ce = {
89
175
  key: 0,
90
176
  class: "lumal-icon-picker__grid",
91
177
  role: "listbox",
92
178
  "aria-label": "图标列表"
93
- }, q = [
179
+ }, le = [
94
180
  "aria-label",
95
181
  "aria-selected",
96
182
  "title",
97
183
  "onClick"
98
- ], J = { key: 0 }, Y = {
184
+ ], ue = {
185
+ key: 0,
186
+ class: "lumal-icon-picker__item-label"
187
+ }, de = {
99
188
  key: 1,
100
189
  class: "lumal-icon-picker__empty"
101
- }, X = {
190
+ }, fe = {
102
191
  key: 2,
103
192
  class: "lumal-icon-picker__pagination"
104
- }, Z = ["disabled"], Q = ["disabled"], $ = /*#__PURE__*/ R(/* @__PURE__ */ s({
193
+ }, pe = ["disabled"], me = ["disabled"], Q = /*#__PURE__*/ X(/* @__PURE__ */ l({
105
194
  __name: "LumalIconPicker",
106
- props: /*@__PURE__*/ c({
195
+ props: /*@__PURE__*/ d({
107
196
  group: { default: "" },
108
197
  pageSize: { default: 48 },
109
198
  searchable: {
@@ -119,76 +208,90 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
119
208
  modelValue: {},
120
209
  modelModifiers: {}
121
210
  }),
122
- emits: /*@__PURE__*/ c(["select"], ["update:modelValue"]),
123
- setup(n, { emit: s }) {
124
- let c = n, l = s, d = x(n, "modelValue"), f = m(""), g = m(c.group), _ = m(1), y = t(() => Math.max(1, c.pageSize)), b = P(), E = b.icons, D = t(() => {
125
- let e = b.groups.value, t = new Set(e.map((e) => e.key)), n = E.value.map((e) => e.group).filter((e) => typeof e == "string" && !t.has(e)).filter((e, t, n) => n.indexOf(e) === t).map((e) => ({
211
+ emits: /*@__PURE__*/ d(["select"], ["update:modelValue"]),
212
+ setup(t, { emit: r }) {
213
+ let s = t, l = r, u = A(t, "modelValue"), d = w(""), f = w(s.group), m = w(1), h = n(() => Math.max(1, s.pageSize)), g = K(), _ = g.icons, v = n(() => {
214
+ let e = g.groups.value, t = new Set(e.map((e) => e.key)), n = _.value.map((e) => e.group).filter((e) => typeof e == "string" && !t.has(e)).filter((e, t, n) => n.indexOf(e) === t).map((e) => ({
126
215
  key: e,
127
216
  label: e
128
217
  }));
129
218
  return [...e, ...n];
130
- }), O = t(() => {
131
- let e = f.value.trim().toLocaleLowerCase();
132
- return E.value.filter((t) => {
133
- let n = !g.value || t.group === g.value, r = !e || t.key.toLocaleLowerCase().includes(e) || t.label?.toLocaleLowerCase().includes(e);
219
+ }), y = n(() => {
220
+ let e = d.value.trim().toLocaleLowerCase();
221
+ return _.value.filter((t) => {
222
+ let n = !f.value || t.group === f.value, r = !e || t.key.toLocaleLowerCase().includes(e) || t.label?.toLocaleLowerCase().includes(e);
134
223
  return n && r;
135
224
  });
136
- }), k = t(() => Math.max(1, Math.ceil(O.value.length / y.value))), A = t(() => {
137
- let e = (_.value - 1) * y.value;
138
- return O.value.slice(e, e + y.value);
225
+ }), C = n(() => Math.max(1, Math.ceil(y.value.length / h.value))), E = n(() => {
226
+ let e = (m.value - 1) * h.value;
227
+ return y.value.slice(e, e + h.value);
139
228
  });
140
- w([
229
+ function D(e) {
230
+ f.value = e;
231
+ }
232
+ N([
233
+ d,
141
234
  f,
142
- g,
143
- y
235
+ h
144
236
  ], () => {
145
- _.value = 1;
146
- }), w(() => c.group, (e) => {
147
- g.value = e;
148
- }), w(k, (e) => {
149
- _.value = Math.min(_.value, e);
150
- }), c.storageKey && typeof localStorage < "u" && !d.value && (d.value = localStorage.getItem(c.storageKey) ?? void 0);
151
- function j(e) {
152
- d.value = e.key, c.storageKey && typeof localStorage < "u" && localStorage.setItem(c.storageKey, e.key), l("select", e);
237
+ m.value = 1;
238
+ }), N(() => s.group, (e) => {
239
+ f.value = e;
240
+ }), N(C, (e) => {
241
+ m.value = Math.min(m.value, e);
242
+ }), s.storageKey && typeof localStorage < "u" && !u.value && (u.value = localStorage.getItem(s.storageKey) ?? void 0);
243
+ function O(e) {
244
+ u.value = e.key, s.storageKey && typeof localStorage < "u" && localStorage.setItem(s.storageKey, e.key), l("select", e);
153
245
  }
154
- return (t, s) => (p(), i("div", B, [
155
- a("div", V, [n.searchable ? (p(), i("label", H, [s[4] ||= a("span", { class: "lumal-icon-picker__field-label" }, "搜索图标", -1), T(a("input", {
156
- "onUpdate:modelValue": s[0] ||= (e) => f.value = e,
246
+ return (n, r) => (b(), a("div", { class: p(["lumal-icon-picker", { "lumal-icon-picker--show-labels": t.showLabels }]) }, [
247
+ o("div", re, [t.searchable ? (b(), a("label", ie, [r[4] ||= o("span", { class: "lumal-icon-picker__field-label" }, "搜索图标", -1), P(o("input", {
248
+ "onUpdate:modelValue": r[0] ||= (e) => d.value = e,
157
249
  type: "search",
250
+ "aria-label": "搜索图标",
158
251
  placeholder: "输入名称或 key"
159
- }, null, 512), [[C, f.value]])])) : r("", !0), D.value.length ? (p(), i("label", U, [s[6] ||= a("span", { class: "lumal-icon-picker__field-label" }, "图标分组", -1), T(a("select", { "onUpdate:modelValue": s[1] ||= (e) => g.value = e }, [s[5] ||= a("option", { value: "" }, "全部分组", -1), (p(!0), i(e, null, h(D.value, (e) => (p(), i("option", {
252
+ }, null, 512), [[M, d.value]])])) : i("", !0), v.value.length ? (b(), a("div", ae, [r[6] ||= o("span", { class: "lumal-icon-picker__field-label" }, "图标分组", -1), S(n.$slots, "group-select", {
253
+ modelValue: f.value,
254
+ groups: v.value,
255
+ setGroup: D
256
+ }, () => [P(o("select", {
257
+ "onUpdate:modelValue": r[1] ||= (e) => f.value = e,
258
+ "aria-label": "图标分组"
259
+ }, [r[5] ||= o("option", { value: "" }, " 全部分组 ", -1), (b(!0), a(e, null, x(v.value, (e) => (b(), a("option", {
160
260
  key: e.key,
161
261
  value: e.key
162
- }, v(e.label), 9, W))), 128))], 512), [[S, g.value]])])) : r("", !0)]),
163
- a("p", G, " 共 " + v(O.value.length) + " 个图标 ", 1),
164
- A.value.length ? (p(), i("div", K, [(p(!0), i(e, null, h(A.value, (e) => (p(), i("button", {
262
+ }, T(e.label), 9, oe))), 128))], 512), [[j, f.value]])], !0)])) : i("", !0)]),
263
+ o("p", se, " 共 " + T(y.value.length) + " 个图标 ", 1),
264
+ E.value.length ? (b(), a("div", ce, [(b(!0), a(e, null, x(E.value, (e) => (b(), a("button", {
165
265
  key: e.key,
166
- class: u(["lumal-icon-picker__item", { "is-selected": d.value === e.key }]),
266
+ class: p(["lumal-icon-picker__item", { "is-selected": u.value === e.key }]),
167
267
  type: "button",
168
268
  role: "option",
169
269
  "aria-label": e.label || e.key,
170
- "aria-selected": d.value === e.key,
270
+ "aria-selected": u.value === e.key,
171
271
  title: e.label || e.key,
172
- onClick: (t) => j(e)
173
- }, [o(z, { name: e.key }, null, 8, ["name"]), n.showLabels ? (p(), i("span", J, v(e.label || e.key), 1)) : r("", !0)], 10, q))), 128))])) : (p(), i("p", Y, " 未找到匹配图标 ")),
174
- k.value > 1 ? (p(), i("footer", X, [
175
- a("button", {
272
+ onClick: (t) => O(e)
273
+ }, [c(Z, {
274
+ name: e.key,
275
+ size: 28
276
+ }, null, 8, ["name"]), t.showLabels ? (b(), a("span", ue, T(e.label || e.key), 1)) : i("", !0)], 10, le))), 128))])) : (b(), a("p", de, " 未找到匹配图标 ")),
277
+ C.value > 1 ? (b(), a("footer", fe, [
278
+ o("button", {
176
279
  type: "button",
177
- disabled: _.value <= 1,
178
- onClick: s[2] ||= (e) => --_.value
179
- }, " 上一页 ", 8, Z),
180
- a("span", null, "第 " + v(_.value) + " / " + v(k.value) + " 页", 1),
181
- a("button", {
280
+ disabled: m.value <= 1,
281
+ onClick: r[2] ||= (e) => --m.value
282
+ }, " 上一页 ", 8, pe),
283
+ o("span", null, "第 " + T(m.value) + " / " + T(C.value) + " 页", 1),
284
+ o("button", {
182
285
  type: "button",
183
- disabled: _.value >= k.value,
184
- onClick: s[3] ||= (e) => _.value += 1
185
- }, " 下一页 ", 8, Q)
186
- ])) : r("", !0)
187
- ]));
286
+ disabled: m.value >= C.value,
287
+ onClick: r[3] ||= (e) => m.value += 1
288
+ }, " 下一页 ", 8, me)
289
+ ])) : i("", !0)
290
+ ], 2));
188
291
  }
189
- }), [["__scopeId", "data-v-937c0d9c"]]), te = ["aria-label"], ne = { class: "lumal-icon-picker-dialog__header" }, re = { class: "lumal-icon-picker-dialog__content" }, ie = { class: "lumal-icon-picker-dialog__footer" }, ae = ["disabled"], oe = /*#__PURE__*/ R(/* @__PURE__ */ s({
292
+ }), [["__scopeId", "data-v-0b9c266c"]]), he = ["aria-label"], ge = { class: "lumal-icon-picker-dialog__header" }, $ = { class: "lumal-icon-picker-dialog__content" }, _e = { class: "lumal-icon-picker-dialog__footer" }, ve = ["disabled"], ye = /*#__PURE__*/ X(/* @__PURE__ */ l({
190
293
  __name: "LumalIconPickerDialog",
191
- props: /*@__PURE__*/ c({
294
+ props: /*@__PURE__*/ d({
192
295
  cancelText: { default: "取消" },
193
296
  confirmText: { default: "确认选择" },
194
297
  title: { default: "选择图标" }
@@ -201,53 +304,79 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
201
304
  modelValue: {},
202
305
  modelModifiers: {}
203
306
  }),
204
- emits: /*@__PURE__*/ c(["cancel", "confirm"], ["update:visible", "update:modelValue"]),
205
- setup(e, { emit: t }) {
206
- let n = t, s = x(e, "visible"), c = x(e, "modelValue"), u = m(""), d = m();
207
- w(s, async (e) => {
208
- e && (u.value = c.value ?? "", await l(), d.value?.focus());
209
- }, { immediate: !0 });
210
- function f() {
211
- s.value = !1, n("cancel");
307
+ emits: /*@__PURE__*/ d(["cancel", "confirm"], ["update:visible", "update:modelValue"]),
308
+ setup(e, { emit: n }) {
309
+ let l = n, d = A(e, "visible"), p = A(e, "modelValue"), h = w(""), _ = ee("dialogRef"), v;
310
+ function y(e) {
311
+ d.value && _.value && !_.value.contains(e.target) && _.value.focus();
312
+ }
313
+ function x(e) {
314
+ if (e.key === "Escape" && (e.preventDefault(), e.stopPropagation(), C()), e.key !== "Tab") return;
315
+ let t = [..._.value?.querySelectorAll("button, input, select, textarea, a[href], [tabindex]") ?? []].filter((e) => e.tabIndex >= 0 && !e.matches(":disabled") && !e.closest("[hidden], [inert]")), n = t[0], r = t.at(-1);
316
+ (!n || (e.shiftKey ? document.activeElement === n || document.activeElement === _.value : document.activeElement === r || document.activeElement === _.value)) && (e.preventDefault(), (e.shiftKey ? r : n)?.focus());
317
+ }
318
+ N(d, async (e) => {
319
+ if (!(typeof document > "u")) {
320
+ if (!e) {
321
+ document.removeEventListener("focusin", y);
322
+ let e = v;
323
+ await f(), !d.value && e?.isConnected && e.focus();
324
+ return;
325
+ }
326
+ v = document.activeElement instanceof HTMLElement ? document.activeElement : void 0, h.value = p.value ?? "", await f(), d.value && (_.value?.focus(), document.addEventListener("focusin", y));
327
+ }
328
+ }, { immediate: !0 }), g(() => {
329
+ document.removeEventListener("focusin", y), v?.isConnected && v.focus();
330
+ });
331
+ function C() {
332
+ d.value = !1, l("cancel");
212
333
  }
213
- function h() {
214
- u.value && (c.value = u.value, s.value = !1, n("confirm", u.value));
334
+ function E() {
335
+ h.value && (p.value = h.value, d.value = !1, l("confirm", h.value));
215
336
  }
216
- return (t, n) => s.value ? (p(), i("div", {
337
+ return (n, l) => (b(), r(t, { to: "body" }, [d.value ? (b(), a("div", {
217
338
  key: 0,
218
339
  class: "lumal-icon-picker-dialog",
219
340
  role: "presentation",
220
- onMousedown: D(f, ["self"])
221
- }, [a("section", {
341
+ onMousedown: ne(C, ["self"])
342
+ }, [o("section", {
222
343
  ref_key: "dialogRef",
223
- ref: d,
344
+ ref: _,
224
345
  class: "lumal-icon-picker-dialog__body",
225
346
  role: "dialog",
226
347
  "aria-modal": "true",
227
348
  "aria-label": e.title,
228
349
  tabindex: "-1",
229
- onKeydown: E(f, ["esc"])
350
+ onKeydown: x
230
351
  }, [
231
- a("header", ne, [a("h3", null, v(e.title), 1), a("button", {
352
+ o("header", ge, [o("h3", null, T(e.title), 1), o("button", {
232
353
  type: "button",
233
354
  "aria-label": "关闭图标选择器",
234
- onClick: f
235
- }, " × ")]),
236
- a("div", re, [o($, {
237
- modelValue: u.value,
238
- "onUpdate:modelValue": n[0] ||= (e) => u.value = e
239
- }, null, 8, ["modelValue"])]),
240
- a("footer", ie, [a("button", {
355
+ title: "关闭图标选择器",
356
+ onClick: C
357
+ }, [c(Z, {
358
+ name: "lumal:close",
359
+ size: 18
360
+ })])]),
361
+ o("div", $, [c(Q, {
362
+ modelValue: h.value,
363
+ "onUpdate:modelValue": l[0] ||= (e) => h.value = e
364
+ }, s({ _: 2 }, [n.$slots["group-select"] ? {
365
+ name: "group-select",
366
+ fn: te((e) => [S(n.$slots, "group-select", m(u(e)), void 0, !0)]),
367
+ key: "0"
368
+ } : void 0]), 1032, ["modelValue"])]),
369
+ o("footer", _e, [o("button", {
241
370
  type: "button",
242
- onClick: f
243
- }, v(e.cancelText), 1), a("button", {
371
+ onClick: C
372
+ }, T(e.cancelText), 1), o("button", {
244
373
  type: "button",
245
374
  class: "is-primary",
246
- disabled: !u.value,
247
- onClick: h
248
- }, v(e.confirmText), 9, ae)])
249
- ], 40, te)], 32)) : r("", !0);
375
+ disabled: !h.value,
376
+ onClick: E
377
+ }, T(e.confirmText), 9, ve)])
378
+ ], 40, he)], 32)) : i("", !0)]));
250
379
  }
251
- }), [["__scopeId", "data-v-9bd629e7"]]);
380
+ }), [["__scopeId", "data-v-ee548916"]]);
252
381
  //#endregion
253
- export { z as LumalIcon, $ as LumalIconPicker, oe as LumalIconPickerDialog, P as useIconRegistry };
382
+ export { Z as LumalIcon, Q as LumalIconPicker, ye as LumalIconPickerDialog, K as useIconRegistry };
@@ -1,5 +1,6 @@
1
1
  import type { IconDefinition, IconGradientOptions } from '@lumal/icons';
2
2
  import type { Component } from 'vue';
3
+ import type { LumalIconMorphSpring } from '../types';
3
4
  /***********************属性定义*********************/
4
5
  type __VLS_Props = {
5
6
  name?: string;
@@ -8,6 +9,8 @@ type __VLS_Props = {
8
9
  color?: string;
9
10
  gradient?: IconGradientOptions;
10
11
  title?: string;
12
+ morph?: boolean;
13
+ morphSpring?: LumalIconMorphSpring;
11
14
  };
12
15
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
16
  declare const _default: typeof __VLS_export;
@@ -1 +1 @@
1
- {"version":3,"file":"LumalIcon.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIcon.vue"],"names":[],"mappings":"AAuIA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAMpC,kDAAkD;AAClD,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,MAAM,CAAA;IACrD,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAC;AAyJF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"LumalIcon.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIcon.vue"],"names":[],"mappings":"AAgKA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AACpC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAOpD,kDAAkD;AAClD,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,MAAM,CAAA;IACrD,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,oBAAoB,CAAA;CACnC,CAAC;AA6LF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1,4 +1,6 @@
1
1
  import type { IconDefinition } from '@lumal/icons';
2
+ import type { LumalIconPickerGroupSelectSlotProps } from '../types';
3
+ /***********************属性与事件*********************/
2
4
  type __VLS_Props = {
3
5
  group?: string;
4
6
  pageSize?: number;
@@ -6,11 +8,15 @@ type __VLS_Props = {
6
8
  showLabels?: boolean;
7
9
  storageKey?: string;
8
10
  };
11
+ type __VLS_Slots = {
12
+ 'group-select'?: (props: LumalIconPickerGroupSelectSlotProps) => unknown;
13
+ };
9
14
  type __VLS_ModelProps = {
15
+ /***********************筛选与分页*********************/
10
16
  modelValue?: string;
11
17
  };
12
18
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
13
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
20
  select: (icon: IconDefinition<unknown>) => any;
15
21
  "update:modelValue": (value: string | undefined) => any;
16
22
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
@@ -23,6 +29,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
23
29
  showLabels: boolean;
24
30
  storageKey: string;
25
31
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
32
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
26
33
  declare const _default: typeof __VLS_export;
27
34
  export default _default;
35
+ type __VLS_WithSlots<T, S> = T & {
36
+ new (): {
37
+ $slots: S;
38
+ };
39
+ };
28
40
  //# sourceMappingURL=LumalIconPicker.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LumalIconPicker.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPicker.vue"],"names":[],"mappings":"AA4PA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAKlD,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC;AA2EF,KAAK,gBAAgB,GAAG;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAYF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AA6LxD,QAAA,MAAM,YAAY;;;;;;;WA3RR,MAAM;cACH,MAAM;gBACJ,OAAO;gBACP,OAAO;gBACP,MAAM;6EA2RnB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"LumalIconPicker.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPicker.vue"],"names":[],"mappings":"AAmSA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,UAAU,CAAA;AAKnE,mDAAmD;AACnD,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC;AAcF,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,mCAAmC,KAAK,OAAO,CAAA;CACzE,CAAC;AAsEF,KAAK,gBAAgB,GAAG;IACxB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAYF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AA+MxD,QAAA,MAAM,UAAU;;;;;;;WAzTN,MAAM;cACH,MAAM;gBACJ,OAAO;gBACP,OAAO;gBACP,MAAM;6EAyTnB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -1,15 +1,19 @@
1
+ import type { LumalIconPickerGroupSelectSlotProps } from '../types';
1
2
  /***********************属性与事件*********************/
2
3
  type __VLS_Props = {
3
4
  cancelText?: string;
4
5
  confirmText?: string;
5
6
  title?: string;
6
7
  };
8
+ type __VLS_Slots = {
9
+ 'group-select'?: (props: LumalIconPickerGroupSelectSlotProps) => unknown;
10
+ };
7
11
  type __VLS_ModelProps = {
8
12
  'visible'?: boolean;
9
13
  modelValue?: string;
10
14
  };
11
15
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
12
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
17
  "update:modelValue": (value: string | undefined) => any;
14
18
  cancel: () => any;
15
19
  confirm: (icon: string) => any;
@@ -24,6 +28,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
24
28
  cancelText: string;
25
29
  confirmText: string;
26
30
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
27
32
  declare const _default: typeof __VLS_export;
28
33
  export default _default;
34
+ type __VLS_WithSlots<T, S> = T & {
35
+ new (): {
36
+ $slots: S;
37
+ };
38
+ };
29
39
  //# sourceMappingURL=LumalIconPickerDialog.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LumalIconPickerDialog.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPickerDialog.vue"],"names":[],"mappings":"AAkLA,mDAAmD;AACnD,KAAK,WAAW,GAAG;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAC;AA+CF,KAAK,gBAAgB,GAAG;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAWF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAqGxD,QAAA,MAAM,YAAY;;;;;;;;;;;WAnKR,MAAM;gBAFD,MAAM;iBACL,MAAM;6EAwKpB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"LumalIconPickerDialog.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPickerDialog.vue"],"names":[],"mappings":"AAyPA,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,UAAU,CAAA;AAKnE,mDAAmD;AACnD,KAAK,WAAW,GAAG;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAC;AAaF,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,mCAAmC,KAAK,OAAO,CAAA;CACzE,CAAC;AAgFF,KAAK,gBAAgB,GAAG;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAWF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAoJxD,QAAA,MAAM,UAAU;;;;;;;;;;;WAlQN,MAAM;gBAFD,MAAM;iBACL,MAAM;6EAuQpB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { PreparedIconMorph } from '@lumal/icons/morph';
2
+ import type { MaybeRefOrGetter } from 'vue';
3
+ import type { MorphRuntime } from '../runtime/morph';
4
+ export declare function useIconMorph(svgText: MaybeRefOrGetter<string>, enabled: MaybeRefOrGetter<boolean>): {
5
+ state: import("vue").ShallowRef<(PreparedIconMorph & {
6
+ component: MorphRuntime["MorphIcon"];
7
+ }) | undefined, (PreparedIconMorph & {
8
+ component: MorphRuntime["MorphIcon"];
9
+ }) | undefined>;
10
+ reset: () => void;
11
+ };
12
+ //# sourceMappingURL=useIconMorph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIconMorph.d.ts","sourceRoot":"","sources":["../../../src/composables/useIconMorph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAKpD,wBAAgB,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;;mBAIrC,YAAY,CAAC,WAAW,CAAC;;mBAAzB,YAAY,CAAC,WAAW,CAAC;;;EA6ErF"}
@@ -4,4 +4,5 @@ import LumalIconPickerDialog from './components/LumalIconPickerDialog.vue';
4
4
  export { LumalIcon, LumalIconPicker, LumalIconPickerDialog, };
5
5
  export { useIconRegistry } from './composables/useIconRegistry';
6
6
  export type { UseIconRegistryReturn } from './composables/useIconRegistry';
7
+ export type { LumalIconMorphSpring, LumalIconPickerGroupSelectSlotProps } from './types';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,eAAe,MAAM,kCAAkC,CAAA;AAC9D,OAAO,qBAAqB,MAAM,wCAAwC,CAAA;AAE1E,OAAO,EACL,SAAS,EACT,eAAe,EACf,qBAAqB,GACtB,CAAA;AACD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,eAAe,MAAM,kCAAkC,CAAA;AAC9D,OAAO,qBAAqB,MAAM,wCAAwC,CAAA;AAE1E,OAAO,EACL,SAAS,EACT,eAAe,EACf,qBAAqB,GACtB,CAAA;AACD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,YAAY,EAAE,oBAAoB,EAAE,mCAAmC,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,6 @@
1
+ export interface MorphRuntime {
2
+ MorphIcon: typeof import('morphicons/vue')['MorphIcon'];
3
+ }
4
+ /** 通用转换由 @lumal/icons/morph 负责,此处只按需加载官方 Vue 绑定。 */
5
+ export declare function loadMorphRuntime(): Promise<MorphRuntime>;
6
+ //# sourceMappingURL=morph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morph.d.ts","sourceRoot":"","sources":["../../../src/runtime/morph.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,cAAc,gBAAgB,CAAC,CAAC,WAAW,CAAC,CAAA;CACxD;AAID,oDAAoD;AACpD,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC,CAMxD"}
@@ -0,0 +1,9 @@
1
+ import type { IconGroupDefinition } from '@lumal/icons';
2
+ export type { LumalIconMorphSpring } from '@lumal/icons/morph';
3
+ /***********************选择器插槽类型*********************/
4
+ export interface LumalIconPickerGroupSelectSlotProps {
5
+ modelValue: string;
6
+ groups: IconGroupDefinition[];
7
+ setGroup: (group: string) => void;
8
+ }
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAEvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAE9D,qDAAqD;AACrD,MAAM,WAAW,mCAAmC;IAClD,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,mBAAmB,EAAE,CAAA;IAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lumal/icons-vue",
3
3
  "type": "module",
4
- "version": "0.0.2-beta",
4
+ "version": "0.0.4-beta",
5
5
  "description": "Vue components and reactive adapters for @lumal/icons.",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -29,6 +29,7 @@
29
29
  "module": "./dist/index.js",
30
30
  "types": "./dist/src/index.d.ts",
31
31
  "files": [
32
+ "CHANGELOG.md",
32
33
  "README.md",
33
34
  "dist"
34
35
  ],
@@ -37,7 +38,8 @@
37
38
  "vue": "^3.5.0"
38
39
  },
39
40
  "dependencies": {
40
- "@lumal/icons": "0.0.2-beta"
41
+ "@lumal/icons": "0.0.4-beta",
42
+ "morphicons": "2.0.0"
41
43
  },
42
44
  "scripts": {
43
45
  "build": "vite build --config vite.config.ts && vue-tsc -p tsconfig.json --emitDeclarationOnly --outDir dist && node ../../scripts/clean-package-dist.mjs dist",