@lumal/icons-vue 0.0.2-beta → 0.0.3-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 +13 -0
- package/README.md +2 -0
- package/dist/icons-vue.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +139 -121
- package/dist/src/components/LumalIcon.vue.d.ts.map +1 -1
- package/dist/src/components/LumalIconPickerDialog.vue.d.ts.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @lumal/icons-vue
|
|
2
|
+
|
|
3
|
+
## 0.0.3-beta (2026-10-16)
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 修复直接传入 component、Iconify 和 local-svg 图标定义时的分支解析。
|
|
8
|
+
- 图标选择弹窗增加 Teleport、键盘焦点约束与焦点恢复,并使用 useTemplateRef。
|
|
9
|
+
- 明确 SVG 仅接受可信静态资源,格式校验不等于安全净化。
|
|
10
|
+
|
|
11
|
+
## 0.0.2-beta (2026-08-01)
|
|
12
|
+
|
|
13
|
+
- Version bump only, to stay in lockstep with the other @lumal packages.
|
package/README.md
CHANGED
|
@@ -14,3 +14,5 @@ import '@lumal/icons-vue/style.css'
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
SVG 改色、渐变、合成、Data URI 和注册表等纯 TypeScript 能力由 `@lumal/icons` 提供。
|
|
17
|
+
|
|
18
|
+
`LumalIcon` 接受注册名或直接 `IconDefinition`(component / iconify / local-svg)。SVG 使用 HTML 渲染,仅接受可信静态资源;注册和渲染不自动净化,单色格式校验不是完整 sanitizer。图标选择弹窗通过 Teleport 挂载到 body,约束 Tab、支持 Escape,并在关闭/卸载时恢复焦点。
|
package/dist/icons-vue.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.lumal-icon[data-v-
|
|
1
|
+
.lumal-icon[data-v-f5cc1719]{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-f5cc1719],.lumal-icon__component[data-v-f5cc1719]{width:100%;height:100%}.lumal-icon__svg[data-v-f5cc1719] 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-a6a04d17]{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-a6a04d17]{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-a6a04d17],.lumal-icon-picker-dialog__footer[data-v-a6a04d17]{justify-content:space-between;align-items:center;gap:12px;min-height:56px;padding:12px 20px;display:flex}.lumal-icon-picker-dialog__header[data-v-a6a04d17]{border-bottom:1px solid var(--el-border-color-lighter,currentColor)}.lumal-icon-picker-dialog__header h3[data-v-a6a04d17]{margin:0;font-size:17px}.lumal-icon-picker-dialog__content[data-v-a6a04d17]{min-height:0;padding:20px;overflow:auto}.lumal-icon-picker-dialog__footer[data-v-a6a04d17]{border-top:1px solid var(--el-border-color-lighter,currentColor);justify-content:flex-end}.lumal-icon-picker-dialog button[data-v-a6a04d17]{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-a6a04d17]{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-a6a04d17]:disabled{cursor:not-allowed;opacity:.5}@media (width<=640px){.lumal-icon-picker-dialog[data-v-a6a04d17]{align-items:flex-end;padding:0}.lumal-icon-picker-dialog__body[data-v-a6a04d17]{border-radius:var(--lumal-radius-large,12px) var(--lumal-radius-large,12px) 0 0;max-height:92dvh}}
|
|
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)(()=>{
|
|
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)(()=>{let e=s.name?l.resolve(s.name):void 0;if(e)return e;let t=s.icon;return t&&typeof t==`object`&&`source`in t&&`key`in t?t:void 0}),d=(0,e.computed)(()=>{let e=s.icon,t=u.value?.svgText??(typeof e==`string`&&e.trim().startsWith(`<svg`)?e:``);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)(()=>{if(u.value){let t=u.value.source===`component`?u.value.component:void 0;return typeof t==`function`||typeof t==`object`&&t?(0,e.toRaw)(t):void 0}return typeof s.icon==`function`||typeof s.icon==`object`?(0,e.toRaw)(s.icon):void 0}),p=(0,e.computed)(()=>{if(u.value?.source===`iconify`)return u.value.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-f5cc1719`]]),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.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 f(){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`,w,[(0,e.createElementVNode)(`h3`,null,(0,e.toDisplayString)(t.title),1),(0,e.createElementVNode)(`button`,{type:`button`,"aria-label":`关闭图标选择器`,onClick:d},` × `)]),(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:d},(0,e.toDisplayString)(t.cancelText),1),(0,e.createElementVNode)(`button`,{type:`button`,class:`is-primary`,disabled:!o.value,onClick:f},(0,e.toDisplayString)(t.confirmText),9,D)])],40,C)],32)):(0,e.createCommentVNode)(``,!0)]))}}),[[`__scopeId`,`data-v-a6a04d17`]]);exports.LumalIcon=c,exports.LumalIconPicker=S,exports.LumalIconPickerDialog=O,exports.useIconRegistry=r;
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import { Fragment as e,
|
|
2
|
-
import { Icon as
|
|
3
|
-
import { applySvgGradient as
|
|
1
|
+
import { Fragment as e, Teleport as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createVNode as s, defineComponent as c, mergeModels as l, nextTick as u, normalizeClass as d, normalizeStyle as f, onBeforeUnmount as p, onScopeDispose as m, openBlock as h, ref as g, renderList as _, resolveDynamicComponent as v, shallowRef as y, toDisplayString as b, toRaw as x, unref as S, useId as C, useModel as w, useTemplateRef as T, vModelSelect as E, vModelText as D, watch as O, withDirectives as k, withModifiers as A } from "vue";
|
|
2
|
+
import { Icon as j } from "@iconify/vue";
|
|
3
|
+
import { applySvgGradient as M, getRegisteredIconDefinitions as ee, getRegisteredIconGroups as te, recolorSvgString as N, resolveIconDefinition as P, subscribeIconRegistry as F } from "@lumal/icons";
|
|
4
4
|
//#region src/composables/useIconRegistry.ts
|
|
5
|
-
function
|
|
6
|
-
let e =
|
|
7
|
-
|
|
5
|
+
function I() {
|
|
6
|
+
let e = y(0);
|
|
7
|
+
m(F(() => {
|
|
8
8
|
e.value += 1;
|
|
9
9
|
}));
|
|
10
|
-
let
|
|
10
|
+
let t = n(() => (e.value, ee())), r = n(() => (e.value, te()));
|
|
11
11
|
function i(t) {
|
|
12
|
-
return e.value,
|
|
12
|
+
return e.value, P(t);
|
|
13
13
|
}
|
|
14
14
|
return {
|
|
15
15
|
groups: r,
|
|
16
|
-
icons:
|
|
16
|
+
icons: t,
|
|
17
17
|
resolve: i
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/components/LumalIcon.vue?vue&type=script&setup=true&lang.ts
|
|
22
|
-
var
|
|
22
|
+
var L = ["title"], R = ["innerHTML"], z = /*@__PURE__*/ c({
|
|
23
23
|
__name: "LumalIcon",
|
|
24
24
|
props: {
|
|
25
25
|
name: {},
|
|
@@ -30,80 +30,80 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
|
|
|
30
30
|
title: {}
|
|
31
31
|
},
|
|
32
32
|
setup(e) {
|
|
33
|
-
let
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
let t = e, o = `lumal-icon-gradient-${C()}`, s = I(), c = n(() => {
|
|
34
|
+
let e = t.name ? s.resolve(t.name) : void 0;
|
|
35
|
+
if (e) return e;
|
|
36
|
+
let n = t.icon;
|
|
37
|
+
return n && typeof n == "object" && "source" in n && "key" in n ? n : void 0;
|
|
38
|
+
}), l = n(() => {
|
|
39
|
+
let e = t.icon, n = c.value?.svgText ?? (typeof e == "string" && e.trim().startsWith("<svg") ? e : "");
|
|
40
|
+
return n ? t.gradient ? M(n, {
|
|
41
|
+
...t.gradient,
|
|
42
|
+
id: t.gradient.id ?? o
|
|
43
|
+
}) : N(n, t.color) : "";
|
|
44
|
+
}), u = n(() => {
|
|
45
|
+
if (c.value) {
|
|
46
|
+
let e = c.value.source === "component" ? c.value.component : void 0;
|
|
47
|
+
return typeof e == "function" || typeof e == "object" && e ? x(e) : void 0;
|
|
47
48
|
}
|
|
48
|
-
return typeof
|
|
49
|
-
}),
|
|
49
|
+
return typeof t.icon == "function" || typeof t.icon == "object" ? x(t.icon) : void 0;
|
|
50
|
+
}), d = n(() => {
|
|
50
51
|
if (c.value?.source === "iconify") return c.value.icon;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return (e, t) => h.value ? (p(), i("span", {
|
|
52
|
+
}), p = n(() => ({
|
|
53
|
+
"--lumal-icon-size": typeof t.size == "number" ? `${t.size}px` : t.size ?? "1em",
|
|
54
|
+
color: t.color
|
|
55
|
+
})), m = n(() => !!(l.value || u.value || d.value)), g = n(() => t.title ?? c.value?.label);
|
|
56
|
+
return (e, t) => m.value ? (h(), a("span", {
|
|
57
57
|
key: 0,
|
|
58
58
|
class: "lumal-icon",
|
|
59
|
-
style:
|
|
60
|
-
title:
|
|
59
|
+
style: f(p.value),
|
|
60
|
+
title: g.value,
|
|
61
61
|
"aria-hidden": "true"
|
|
62
|
-
}, [u.value ? (
|
|
62
|
+
}, [u.value ? (h(), r(v(u.value), {
|
|
63
63
|
key: 0,
|
|
64
64
|
class: "lumal-icon__component"
|
|
65
|
-
})) :
|
|
65
|
+
})) : d.value ? (h(), r(S(j), {
|
|
66
66
|
key: 1,
|
|
67
67
|
class: "lumal-icon__component",
|
|
68
|
-
icon:
|
|
69
|
-
}, null, 8, ["icon"])) : (
|
|
68
|
+
icon: d.value
|
|
69
|
+
}, null, 8, ["icon"])) : (h(), a("span", {
|
|
70
70
|
key: 2,
|
|
71
71
|
class: "lumal-icon__svg",
|
|
72
72
|
innerHTML: l.value
|
|
73
|
-
}, null, 8,
|
|
73
|
+
}, null, 8, R))], 12, L)) : i("", !0);
|
|
74
74
|
}
|
|
75
|
-
}),
|
|
75
|
+
}), B = (e, t) => {
|
|
76
76
|
let n = e.__vccOpts || e;
|
|
77
77
|
for (let [e, r] of t) n[e] = r;
|
|
78
78
|
return n;
|
|
79
|
-
},
|
|
79
|
+
}, V = /*#__PURE__*/ B(z, [["__scopeId", "data-v-f5cc1719"]]), H = { class: "lumal-icon-picker" }, U = { class: "lumal-icon-picker__toolbar" }, W = {
|
|
80
80
|
key: 0,
|
|
81
81
|
class: "lumal-icon-picker__field"
|
|
82
|
-
},
|
|
82
|
+
}, G = {
|
|
83
83
|
key: 1,
|
|
84
84
|
class: "lumal-icon-picker__field"
|
|
85
|
-
},
|
|
85
|
+
}, K = ["value"], q = {
|
|
86
86
|
class: "lumal-icon-picker__summary",
|
|
87
87
|
role: "status"
|
|
88
|
-
},
|
|
88
|
+
}, J = {
|
|
89
89
|
key: 0,
|
|
90
90
|
class: "lumal-icon-picker__grid",
|
|
91
91
|
role: "listbox",
|
|
92
92
|
"aria-label": "图标列表"
|
|
93
|
-
},
|
|
93
|
+
}, Y = [
|
|
94
94
|
"aria-label",
|
|
95
95
|
"aria-selected",
|
|
96
96
|
"title",
|
|
97
97
|
"onClick"
|
|
98
|
-
],
|
|
98
|
+
], X = { key: 0 }, Z = {
|
|
99
99
|
key: 1,
|
|
100
100
|
class: "lumal-icon-picker__empty"
|
|
101
|
-
},
|
|
101
|
+
}, ne = {
|
|
102
102
|
key: 2,
|
|
103
103
|
class: "lumal-icon-picker__pagination"
|
|
104
|
-
},
|
|
104
|
+
}, re = ["disabled"], ie = ["disabled"], Q = /*#__PURE__*/ B(/* @__PURE__ */ c({
|
|
105
105
|
__name: "LumalIconPicker",
|
|
106
|
-
props: /*@__PURE__*/
|
|
106
|
+
props: /*@__PURE__*/ l({
|
|
107
107
|
group: { default: "" },
|
|
108
108
|
pageSize: { default: 48 },
|
|
109
109
|
searchable: {
|
|
@@ -119,76 +119,76 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
|
|
|
119
119
|
modelValue: {},
|
|
120
120
|
modelModifiers: {}
|
|
121
121
|
}),
|
|
122
|
-
emits: /*@__PURE__*/
|
|
123
|
-
setup(
|
|
124
|
-
let c =
|
|
125
|
-
let e =
|
|
122
|
+
emits: /*@__PURE__*/ l(["select"], ["update:modelValue"]),
|
|
123
|
+
setup(t, { emit: r }) {
|
|
124
|
+
let c = t, l = r, u = w(t, "modelValue"), f = g(""), p = g(c.group), m = g(1), v = n(() => Math.max(1, c.pageSize)), y = I(), x = y.icons, S = n(() => {
|
|
125
|
+
let e = y.groups.value, t = new Set(e.map((e) => e.key)), n = x.value.map((e) => e.group).filter((e) => typeof e == "string" && !t.has(e)).filter((e, t, n) => n.indexOf(e) === t).map((e) => ({
|
|
126
126
|
key: e,
|
|
127
127
|
label: e
|
|
128
128
|
}));
|
|
129
129
|
return [...e, ...n];
|
|
130
|
-
}),
|
|
130
|
+
}), C = n(() => {
|
|
131
131
|
let e = f.value.trim().toLocaleLowerCase();
|
|
132
|
-
return
|
|
133
|
-
let n = !
|
|
132
|
+
return x.value.filter((t) => {
|
|
133
|
+
let n = !p.value || t.group === p.value, r = !e || t.key.toLocaleLowerCase().includes(e) || t.label?.toLocaleLowerCase().includes(e);
|
|
134
134
|
return n && r;
|
|
135
135
|
});
|
|
136
|
-
}),
|
|
137
|
-
let e = (
|
|
138
|
-
return
|
|
136
|
+
}), T = n(() => Math.max(1, Math.ceil(C.value.length / v.value))), A = n(() => {
|
|
137
|
+
let e = (m.value - 1) * v.value;
|
|
138
|
+
return C.value.slice(e, e + v.value);
|
|
139
139
|
});
|
|
140
|
-
|
|
140
|
+
O([
|
|
141
141
|
f,
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
p,
|
|
143
|
+
v
|
|
144
144
|
], () => {
|
|
145
|
-
|
|
146
|
-
}),
|
|
147
|
-
|
|
148
|
-
}),
|
|
149
|
-
|
|
150
|
-
}), c.storageKey && typeof localStorage < "u" && !
|
|
145
|
+
m.value = 1;
|
|
146
|
+
}), O(() => c.group, (e) => {
|
|
147
|
+
p.value = e;
|
|
148
|
+
}), O(T, (e) => {
|
|
149
|
+
m.value = Math.min(m.value, e);
|
|
150
|
+
}), c.storageKey && typeof localStorage < "u" && !u.value && (u.value = localStorage.getItem(c.storageKey) ?? void 0);
|
|
151
151
|
function j(e) {
|
|
152
|
-
|
|
152
|
+
u.value = e.key, c.storageKey && typeof localStorage < "u" && localStorage.setItem(c.storageKey, e.key), l("select", e);
|
|
153
153
|
}
|
|
154
|
-
return (
|
|
155
|
-
|
|
156
|
-
"onUpdate:modelValue":
|
|
154
|
+
return (n, r) => (h(), a("div", H, [
|
|
155
|
+
o("div", U, [t.searchable ? (h(), a("label", W, [r[4] ||= o("span", { class: "lumal-icon-picker__field-label" }, "搜索图标", -1), k(o("input", {
|
|
156
|
+
"onUpdate:modelValue": r[0] ||= (e) => f.value = e,
|
|
157
157
|
type: "search",
|
|
158
158
|
placeholder: "输入名称或 key"
|
|
159
|
-
}, null, 512), [[
|
|
159
|
+
}, null, 512), [[D, f.value]])])) : i("", !0), S.value.length ? (h(), a("label", G, [r[6] ||= o("span", { class: "lumal-icon-picker__field-label" }, "图标分组", -1), k(o("select", { "onUpdate:modelValue": r[1] ||= (e) => p.value = e }, [r[5] ||= o("option", { value: "" }, "全部分组", -1), (h(!0), a(e, null, _(S.value, (e) => (h(), a("option", {
|
|
160
160
|
key: e.key,
|
|
161
161
|
value: e.key
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
A.value.length ? (
|
|
162
|
+
}, b(e.label), 9, K))), 128))], 512), [[E, p.value]])])) : i("", !0)]),
|
|
163
|
+
o("p", q, " 共 " + b(C.value.length) + " 个图标 ", 1),
|
|
164
|
+
A.value.length ? (h(), a("div", J, [(h(!0), a(e, null, _(A.value, (e) => (h(), a("button", {
|
|
165
165
|
key: e.key,
|
|
166
|
-
class:
|
|
166
|
+
class: d(["lumal-icon-picker__item", { "is-selected": u.value === e.key }]),
|
|
167
167
|
type: "button",
|
|
168
168
|
role: "option",
|
|
169
169
|
"aria-label": e.label || e.key,
|
|
170
|
-
"aria-selected":
|
|
170
|
+
"aria-selected": u.value === e.key,
|
|
171
171
|
title: e.label || e.key,
|
|
172
172
|
onClick: (t) => j(e)
|
|
173
|
-
}, [
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
}, [s(V, { name: e.key }, null, 8, ["name"]), t.showLabels ? (h(), a("span", X, b(e.label || e.key), 1)) : i("", !0)], 10, Y))), 128))])) : (h(), a("p", Z, " 未找到匹配图标 ")),
|
|
174
|
+
T.value > 1 ? (h(), a("footer", ne, [
|
|
175
|
+
o("button", {
|
|
176
176
|
type: "button",
|
|
177
|
-
disabled:
|
|
178
|
-
onClick:
|
|
179
|
-
}, " 上一页 ", 8,
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
disabled: m.value <= 1,
|
|
178
|
+
onClick: r[2] ||= (e) => --m.value
|
|
179
|
+
}, " 上一页 ", 8, re),
|
|
180
|
+
o("span", null, "第 " + b(m.value) + " / " + b(T.value) + " 页", 1),
|
|
181
|
+
o("button", {
|
|
182
182
|
type: "button",
|
|
183
|
-
disabled:
|
|
184
|
-
onClick:
|
|
185
|
-
}, " 下一页 ", 8,
|
|
186
|
-
])) :
|
|
183
|
+
disabled: m.value >= T.value,
|
|
184
|
+
onClick: r[3] ||= (e) => m.value += 1
|
|
185
|
+
}, " 下一页 ", 8, ie)
|
|
186
|
+
])) : i("", !0)
|
|
187
187
|
]));
|
|
188
188
|
}
|
|
189
|
-
}), [["__scopeId", "data-v-937c0d9c"]]),
|
|
189
|
+
}), [["__scopeId", "data-v-937c0d9c"]]), ae = ["aria-label"], oe = { class: "lumal-icon-picker-dialog__header" }, $ = { class: "lumal-icon-picker-dialog__content" }, se = { class: "lumal-icon-picker-dialog__footer" }, ce = ["disabled"], le = /*#__PURE__*/ B(/* @__PURE__ */ c({
|
|
190
190
|
__name: "LumalIconPickerDialog",
|
|
191
|
-
props: /*@__PURE__*/
|
|
191
|
+
props: /*@__PURE__*/ l({
|
|
192
192
|
cancelText: { default: "取消" },
|
|
193
193
|
confirmText: { default: "确认选择" },
|
|
194
194
|
title: { default: "选择图标" }
|
|
@@ -201,53 +201,71 @@ var F = ["title"], I = ["innerHTML"], L = /*@__PURE__*/ s({
|
|
|
201
201
|
modelValue: {},
|
|
202
202
|
modelModifiers: {}
|
|
203
203
|
}),
|
|
204
|
-
emits: /*@__PURE__*/
|
|
205
|
-
setup(e, { emit:
|
|
206
|
-
let
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}, { immediate: !0 });
|
|
210
|
-
function f() {
|
|
211
|
-
s.value = !1, n("cancel");
|
|
204
|
+
emits: /*@__PURE__*/ l(["cancel", "confirm"], ["update:visible", "update:modelValue"]),
|
|
205
|
+
setup(e, { emit: n }) {
|
|
206
|
+
let c = n, l = w(e, "visible"), d = w(e, "modelValue"), f = y(""), m = T("dialogRef"), g;
|
|
207
|
+
function _(e) {
|
|
208
|
+
l.value && m.value && !m.value.contains(e.target) && m.value.focus();
|
|
212
209
|
}
|
|
213
|
-
function
|
|
214
|
-
|
|
210
|
+
function v(e) {
|
|
211
|
+
if (e.key === "Escape" && (e.preventDefault(), e.stopPropagation(), x()), e.key !== "Tab") return;
|
|
212
|
+
let t = [...m.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);
|
|
213
|
+
(!n || (e.shiftKey ? document.activeElement === n || document.activeElement === m.value : document.activeElement === r || document.activeElement === m.value)) && (e.preventDefault(), (e.shiftKey ? r : n)?.focus());
|
|
215
214
|
}
|
|
216
|
-
|
|
215
|
+
O(l, async (e) => {
|
|
216
|
+
if (!(typeof document > "u")) {
|
|
217
|
+
if (!e) {
|
|
218
|
+
document.removeEventListener("focusin", _);
|
|
219
|
+
let e = g;
|
|
220
|
+
await u(), !l.value && e?.isConnected && e.focus();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
g = document.activeElement instanceof HTMLElement ? document.activeElement : void 0, f.value = d.value ?? "", await u(), l.value && (m.value?.focus(), document.addEventListener("focusin", _));
|
|
224
|
+
}
|
|
225
|
+
}, { immediate: !0 }), p(() => {
|
|
226
|
+
document.removeEventListener("focusin", _), g?.isConnected && g.focus();
|
|
227
|
+
});
|
|
228
|
+
function x() {
|
|
229
|
+
l.value = !1, c("cancel");
|
|
230
|
+
}
|
|
231
|
+
function S() {
|
|
232
|
+
f.value && (d.value = f.value, l.value = !1, c("confirm", f.value));
|
|
233
|
+
}
|
|
234
|
+
return (n, c) => (h(), r(t, { to: "body" }, [l.value ? (h(), a("div", {
|
|
217
235
|
key: 0,
|
|
218
236
|
class: "lumal-icon-picker-dialog",
|
|
219
237
|
role: "presentation",
|
|
220
|
-
onMousedown:
|
|
221
|
-
}, [
|
|
238
|
+
onMousedown: A(x, ["self"])
|
|
239
|
+
}, [o("section", {
|
|
222
240
|
ref_key: "dialogRef",
|
|
223
|
-
ref:
|
|
241
|
+
ref: m,
|
|
224
242
|
class: "lumal-icon-picker-dialog__body",
|
|
225
243
|
role: "dialog",
|
|
226
244
|
"aria-modal": "true",
|
|
227
245
|
"aria-label": e.title,
|
|
228
246
|
tabindex: "-1",
|
|
229
|
-
onKeydown:
|
|
247
|
+
onKeydown: v
|
|
230
248
|
}, [
|
|
231
|
-
|
|
249
|
+
o("header", oe, [o("h3", null, b(e.title), 1), o("button", {
|
|
232
250
|
type: "button",
|
|
233
251
|
"aria-label": "关闭图标选择器",
|
|
234
|
-
onClick:
|
|
252
|
+
onClick: x
|
|
235
253
|
}, " × ")]),
|
|
236
|
-
|
|
237
|
-
modelValue:
|
|
238
|
-
"onUpdate:modelValue":
|
|
254
|
+
o("div", $, [s(Q, {
|
|
255
|
+
modelValue: f.value,
|
|
256
|
+
"onUpdate:modelValue": c[0] ||= (e) => f.value = e
|
|
239
257
|
}, null, 8, ["modelValue"])]),
|
|
240
|
-
|
|
258
|
+
o("footer", se, [o("button", {
|
|
241
259
|
type: "button",
|
|
242
|
-
onClick:
|
|
243
|
-
},
|
|
260
|
+
onClick: x
|
|
261
|
+
}, b(e.cancelText), 1), o("button", {
|
|
244
262
|
type: "button",
|
|
245
263
|
class: "is-primary",
|
|
246
|
-
disabled: !
|
|
247
|
-
onClick:
|
|
248
|
-
},
|
|
249
|
-
], 40,
|
|
264
|
+
disabled: !f.value,
|
|
265
|
+
onClick: S
|
|
266
|
+
}, b(e.confirmText), 9, ce)])
|
|
267
|
+
], 40, ae)], 32)) : i("", !0)]));
|
|
250
268
|
}
|
|
251
|
-
}), [["__scopeId", "data-v-
|
|
269
|
+
}), [["__scopeId", "data-v-a6a04d17"]]);
|
|
252
270
|
//#endregion
|
|
253
|
-
export {
|
|
271
|
+
export { V as LumalIcon, Q as LumalIconPicker, le as LumalIconPickerDialog, I as useIconRegistry };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LumalIcon.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIcon.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LumalIcon.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIcon.vue"],"names":[],"mappings":"AA+HA,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;AAiJF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LumalIconPickerDialog.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPickerDialog.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LumalIconPickerDialog.vue.d.ts","sourceRoot":"","sources":["../../../src/components/LumalIconPickerDialog.vue"],"names":[],"mappings":"AA+NA,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;AA0FF,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;AAoHxD,QAAA,MAAM,YAAY;;;;;;;;;;;WA7NR,MAAM;gBAFD,MAAM;iBACL,MAAM;6EAkOpB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumal/icons-vue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3-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,7 @@
|
|
|
37
38
|
"vue": "^3.5.0"
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
|
-
"@lumal/icons": "0.0.
|
|
41
|
+
"@lumal/icons": "0.0.3-beta"
|
|
41
42
|
},
|
|
42
43
|
"scripts": {
|
|
43
44
|
"build": "vite build --config vite.config.ts && vue-tsc -p tsconfig.json --emitDeclarationOnly --outDir dist && node ../../scripts/clean-package-dist.mjs dist",
|