vome-core 0.1.24 → 0.1.26
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/dist/admin/components/vm-icon-picker.vue +44 -15
- package/dist/admin/config/plugin-dev.js +1 -1
- package/dist/admin/crud/components/vm-color-picker.vue +355 -15
- package/dist/admin/crud/config.js +1 -1
- package/dist/admin/crud/confirm.js +1 -1
- package/dist/admin/crud/dict.js +1 -1
- package/dist/admin/crud/key.js +1 -1
- package/dist/admin/crud/mitt.js +1 -1
- package/dist/admin/crud/plugins.js +1 -1
- package/dist/admin/crud/span.js +1 -1
- package/dist/admin/crud/style.js +1 -1
- package/dist/admin/crud/validate.js +1 -1
- package/dist/admin/directives/perm.js +1 -1
- package/dist/admin/hooks/useUpload.js +1 -1
- package/dist/admin/lib/browser.js +1 -1
- package/dist/admin/lib/cn.js +1 -1
- package/dist/admin/lib/dialog-float.js +1 -1
- package/dist/admin/lib/export-excel.js +1 -1
- package/dist/admin/lib/import-excel.js +1 -1
- package/dist/admin/lib/json.js +1 -1
- package/dist/admin/lib/menu.js +1 -1
- package/dist/admin/lib/tree.js +1 -1
- package/dist/admin/lib/upload.js +1 -1
- package/dist/admin/lib/video-frame.js +1 -1
- package/dist/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/shared/excel.js +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/locale-json.js +1 -1
- package/dist/shared/tree.js +1 -1
- package/package.json +1 -1
|
@@ -91,12 +91,26 @@
|
|
|
91
91
|
<i :class="name" />
|
|
92
92
|
</button>
|
|
93
93
|
<button
|
|
94
|
-
v-if="
|
|
94
|
+
v-if="showPager"
|
|
95
95
|
type="button"
|
|
96
|
-
class="vm-icon-
|
|
96
|
+
class="vm-icon-picker__page-btn"
|
|
97
|
+
:disabled="!canPrev"
|
|
98
|
+
title="上一页"
|
|
99
|
+
aria-label="上一页"
|
|
100
|
+
@click.prevent.stop="prevBatch"
|
|
101
|
+
>
|
|
102
|
+
<i class="ri-arrow-left-s-line" />
|
|
103
|
+
</button>
|
|
104
|
+
<button
|
|
105
|
+
v-if="showPager"
|
|
106
|
+
type="button"
|
|
107
|
+
class="vm-icon-picker__page-btn"
|
|
108
|
+
:disabled="!canNext"
|
|
109
|
+
title="下一页"
|
|
110
|
+
aria-label="下一页"
|
|
97
111
|
@click.prevent.stop="nextBatch"
|
|
98
112
|
>
|
|
99
|
-
|
|
113
|
+
<i class="ri-arrow-right-s-line" />
|
|
100
114
|
</button>
|
|
101
115
|
<p v-if="!filtered.length" class="vm-icon-picker__empty">无匹配图标</p>
|
|
102
116
|
</div>
|
|
@@ -138,7 +152,7 @@ const emit = defineEmits<{
|
|
|
138
152
|
'update:modelValue': [v: string]
|
|
139
153
|
}>()
|
|
140
154
|
|
|
141
|
-
/** 10 列 × 5 行 = 50 格,末尾 2
|
|
155
|
+
/** 10 列 × 5 行 = 50 格,末尾 2 格给上一页 / 下一页 */
|
|
142
156
|
const PAGE_SIZE = 48
|
|
143
157
|
const ALL = allIcons as string[]
|
|
144
158
|
|
|
@@ -221,11 +235,15 @@ const pageCount = computed(() =>
|
|
|
221
235
|
)
|
|
222
236
|
|
|
223
237
|
const pageIcons = computed(() => {
|
|
224
|
-
const start =
|
|
238
|
+
const start = page.value * PAGE_SIZE
|
|
225
239
|
return filtered.value.slice(start, start + PAGE_SIZE)
|
|
226
240
|
})
|
|
227
241
|
|
|
228
|
-
const
|
|
242
|
+
const showPager = computed(() => filtered.value.length > PAGE_SIZE)
|
|
243
|
+
const canPrev = computed(() => page.value > 0)
|
|
244
|
+
const canNext = computed(
|
|
245
|
+
() => page.value < pageCount.value - 1 && filtered.value.length > PAGE_SIZE,
|
|
246
|
+
)
|
|
229
247
|
|
|
230
248
|
watch(filtered, () => {
|
|
231
249
|
page.value = 0
|
|
@@ -321,8 +339,14 @@ function pick(name: string) {
|
|
|
321
339
|
closePanel()
|
|
322
340
|
}
|
|
323
341
|
|
|
342
|
+
function prevBatch() {
|
|
343
|
+
if (!canPrev.value) return
|
|
344
|
+
page.value -= 1
|
|
345
|
+
}
|
|
346
|
+
|
|
324
347
|
function nextBatch() {
|
|
325
|
-
|
|
348
|
+
if (!canNext.value) return
|
|
349
|
+
page.value += 1
|
|
326
350
|
}
|
|
327
351
|
|
|
328
352
|
function onDocPointer(e: Event) {
|
|
@@ -586,10 +610,8 @@ onUnmounted(() => {
|
|
|
586
610
|
}
|
|
587
611
|
}
|
|
588
612
|
|
|
589
|
-
.vm-icon-
|
|
590
|
-
|
|
591
|
-
height: 100%;
|
|
592
|
-
min-height: 32px;
|
|
613
|
+
.vm-icon-picker__page-btn {
|
|
614
|
+
aspect-ratio: 1;
|
|
593
615
|
display: inline-flex;
|
|
594
616
|
align-items: center;
|
|
595
617
|
justify-content: center;
|
|
@@ -597,14 +619,21 @@ onUnmounted(() => {
|
|
|
597
619
|
border-radius: 8px;
|
|
598
620
|
background: var(--brand-soft);
|
|
599
621
|
color: var(--brand);
|
|
600
|
-
font-size:
|
|
601
|
-
|
|
622
|
+
font-size: 18px;
|
|
623
|
+
line-height: 1;
|
|
602
624
|
cursor: pointer;
|
|
603
|
-
transition:
|
|
625
|
+
transition:
|
|
626
|
+
background 0.12s,
|
|
627
|
+
opacity 0.12s;
|
|
604
628
|
|
|
605
|
-
&:hover {
|
|
629
|
+
&:hover:not(:disabled) {
|
|
606
630
|
background: color-mix(in srgb, var(--brand) 16%, #fff);
|
|
607
631
|
}
|
|
632
|
+
|
|
633
|
+
&:disabled {
|
|
634
|
+
opacity: 0.35;
|
|
635
|
+
cursor: not-allowed;
|
|
636
|
+
}
|
|
608
637
|
}
|
|
609
638
|
|
|
610
639
|
.vm-icon-picker__empty {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const _0x3c321b=_0x412f;(function(_0x5828f9,_0x1524b3){const _0x44ee95=_0x412f,_0x246a4e=_0x5828f9();while(!![]){try{const _0x42dd1c=parseInt(_0x44ee95(0x1a0))/0x1+parseInt(_0x44ee95(0x19e))/0x2+parseInt(_0x44ee95(0x1a1))/0x3+-parseInt(_0x44ee95(0x197))/0x4*(-parseInt(_0x44ee95(0x1ac))/0x5)+parseInt(_0x44ee95(0x196))/0x6*(parseInt(_0x44ee95(0x1a6))/0x7)+parseInt(_0x44ee95(0x199))/0x8+-parseInt(_0x44ee95(0x18f))/0x9;if(_0x42dd1c===_0x1524b3)break;else _0x246a4e['push'](_0x246a4e['shift']());}catch(_0x300b9e){_0x246a4e['push'](_0x246a4e['shift']());}}}(_0x11f6,0xacacd));const ORG=_0x3c321b(0x19f);export function serviceUrlFromDocs(_0x185a02){const _0x5739f8=_0x3c321b,_0x3671af=new URL(_0x185a02),_0x46bac4=_0x3671af[_0x5739f8(0x190)]['replace'](/^www\./,'')[_0x5739f8(0x1a7)](/^service\./,'');return _0x3671af[_0x5739f8(0x198)]+_0x5739f8(0x19d)+_0x46bac4;}export function seatApiBaseFromDocs(_0x6f0391){const _0x26b314=_0x3c321b;return serviceUrlFromDocs(_0x6f0391)+_0x26b314(0x1ab);}function _0x412f(_0x56722d,_0x21dfed){_0x56722d=_0x56722d-0x18f;const _0x11f6ef=_0x11f6();let _0x412f44=_0x11f6ef[_0x56722d];if(_0x412f['knSTYd']===undefined){var _0xc38e37=function(_0x25f388){const _0x7c1e01='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x185a02='',_0x3671af='';for(let _0x46bac4=0x0,_0x6f0391,_0x29d51e,_0x487c63=0x0;_0x29d51e=_0x25f388['charAt'](_0x487c63++);~_0x29d51e&&(_0x6f0391=_0x46bac4%0x4?_0x6f0391*0x40+_0x29d51e:_0x29d51e,_0x46bac4++%0x4)?_0x185a02+=String['fromCharCode'](0xff&_0x6f0391>>(-0x2*_0x46bac4&0x6)):0x0){_0x29d51e=_0x7c1e01['indexOf'](_0x29d51e);}for(let _0x427ed8=0x0,_0x308e54=_0x185a02['length'];_0x427ed8<_0x308e54;_0x427ed8++){_0x3671af+='%'+('00'+_0x185a02['charCodeAt'](_0x427ed8)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3671af);};_0x412f['gYbhhk']=_0xc38e37,_0x412f['oxBKWP']={},_0x412f['knSTYd']=!![];}const _0x43fcd4=_0x11f6ef[0x0],_0x69870b=_0x56722d+_0x43fcd4,_0x7ebf1e=_0x412f['oxBKWP'][_0x69870b];return!_0x7ebf1e?(_0x412f44=_0x412f['gYbhhk'](_0x412f44),_0x412f['oxBKWP'][_0x69870b]=_0x412f44):_0x412f44=_0x7ebf1e,_0x412f44;}export function licenseIssueUrlFromDocs(_0x29d51e){const _0x9f4c2f=_0x3c321b;return serviceUrlFromDocs(_0x29d51e)+_0x9f4c2f(0x195);}function giteeArchive(_0x487c63){const _0x153b44=_0x3c321b;return _0x153b44(0x19c)+ORG+'/'+_0x487c63+_0x153b44(0x193);}function githubArchive(_0x427ed8){const _0x51b92f=_0x3c321b;return _0x51b92f(0x191)+ORG+'/'+_0x427ed8+'/archive/refs/heads/master.zip';}function giteeRepo(_0x308e54){const _0x53b464=_0x3c321b;return _0x53b464(0x19c)+ORG+'/'+_0x308e54;}function githubRepo(_0x3a7ee1){const _0x54bd7c=_0x3c321b;return _0x54bd7c(0x191)+ORG+'/'+_0x3a7ee1;}const docsUrl=_0x3c321b(0x1ad);export const pluginDev={'docsUrl':docsUrl,'serviceUrl':serviceUrlFromDocs(docsUrl),'uploadUrl':docsUrl+'/plugins/upload','mirrors':{'prefer':'gitee','giteeOrg':_0x3c321b(0x19c)+ORG,'githubOrg':_0x3c321b(0x191)+ORG},'scaffolds':{'full':{'key':_0x3c321b(0x1a9),'title':_0x3c321b(0x1a8),'desc':_0x3c321b(0x192),'repo':_0x3c321b(0x1a3),'repoUrl':giteeRepo('vome-plugin-full'),'githubRepoUrl':githubRepo(_0x3c321b(0x1a3)),'downloadUrl':giteeArchive('vome-plugin-full'),'githubDownloadUrl':githubArchive(_0x3c321b(0x1a3))},'backend':{'key':_0x3c321b(0x194),'title':'纯后端','desc':_0x3c321b(0x1a5),'repo':_0x3c321b(0x1aa),'repoUrl':giteeRepo(_0x3c321b(0x1aa)),'githubRepoUrl':githubRepo(_0x3c321b(0x1aa)),'downloadUrl':giteeArchive('vome-plugin-service'),'githubDownloadUrl':githubArchive(_0x3c321b(0x1aa))},'frontend':{'key':_0x3c321b(0x1a2),'title':_0x3c321b(0x19b),'desc':_0x3c321b(0x1a4),'repo':_0x3c321b(0x19a),'repoUrl':giteeRepo(_0x3c321b(0x19a)),'githubRepoUrl':githubRepo('vome-plugin-front'),'downloadUrl':giteeArchive('vome-plugin-front'),'githubDownloadUrl':githubArchive('vome-plugin-front')}}};function _0x11f6(){const _0x1d4525=['Ahr0Chm6lY92B21LA2OUy29T','ndq4nJa4nZHIuxvUvui','Ag9ZDg5HBwu','Ahr0Chm6lY9NAxrODwiUy29TlW','5A6m5Pw05lIA5yQH5QIH5z2x6isA5OMl5P6277YilNzVBwxVVjRLKkSGC2vYDMvYios4JIb3zwlVViNVViZMNkZLNldLVidLJ5hMIzpLJixLKi7LJ5hLUipJGii','l3jLCg9ZAxrVCNKVyxjJAgL2zs9Tyxn0zxiUEMLW','yMfJA2vUza','l2fWCc9WBhvNAw5tDg9Yzs93ywXSzxqVBgLJzw5Zzs9PC3n1zq','nZHAA3nsDMm','nejlr0jKCq','ChjVDg9JB2W','mZG0ndC1mMXlqvvfAG','DM9Tzs1WBhvNAw4TzNjVBNq','57QV5yMn56UV','Ahr0Chm6lY9NAxrLzs5JB20V','lY9Zzxj2AwnLlG','mJa4nZi4ofHNte1KAq','DM9TzwTQ','mJKWntyXzvbnAvzp','nda3mtmYmvjJrgn6vW','zNjVBNrLBMq','DM9Tzs1WBhvNAw4TzNvSBa','5zco5y+W5B6U5BQu55sO6isA5OMl5P6277YilNzVBwxVVjRLKkSGD2vIl++8IE+8Jos7Psb3DwPPzsdMJilOVB3NI6ZNQ4VLIy3NQ6/POBxPNAlJGii','6zkP5A2qic8G5PYn5yQH56UV5O+s5lU26isA5OMl5P6277YilNzVBwxVVjRKU4uGC2vYDMvY77Yj77Ym6ycc5zci5lIk5lYG44cb55+T5l+H44cb5PsV5lUy562j6io95yQB5OMP5Bgv44cc','nJK4ndG4zMPSrwDm','CMvWBgfJzq','5yMn56UVicSG5zco56UV','zNvSBa','DM9Tzs1WBhvNAw4TC2vYDMLJzq','l2fWCc9WBhvNAw5tDg9Yzs9Zzwf0','nJeXmZyWnwXLrhfutG'];_0x11f6=function(){return _0x1d4525;};return _0x11f6();}
|
|
@@ -21,15 +21,16 @@
|
|
|
21
21
|
<input
|
|
22
22
|
type="text"
|
|
23
23
|
class="vm-color-picker__input"
|
|
24
|
-
:value="
|
|
24
|
+
:value="inlineDisplay"
|
|
25
25
|
:placeholder="placeholderText"
|
|
26
26
|
:disabled="disabled"
|
|
27
27
|
spellcheck="false"
|
|
28
28
|
autocomplete="off"
|
|
29
|
+
:title="isThemeBound ? themeBoundLabel : undefined"
|
|
29
30
|
@input="onInlineInput"
|
|
30
31
|
@focus="openPanel"
|
|
31
32
|
@blur="onInlineBlur"
|
|
32
|
-
@keydown.esc.stop="
|
|
33
|
+
@keydown.esc.stop="onEscEnd"
|
|
33
34
|
/>
|
|
34
35
|
|
|
35
36
|
<Teleport to="body">
|
|
@@ -47,6 +48,69 @@
|
|
|
47
48
|
@pointerdown.stop
|
|
48
49
|
@mousedown.stop
|
|
49
50
|
>
|
|
51
|
+
<div class="vm-color-picker__toolbar">
|
|
52
|
+
<div
|
|
53
|
+
v-if="hasThemeOptions"
|
|
54
|
+
class="vm-color-picker__modes"
|
|
55
|
+
role="tablist"
|
|
56
|
+
>
|
|
57
|
+
<button
|
|
58
|
+
type="button"
|
|
59
|
+
class="vm-color-picker__mode"
|
|
60
|
+
:class="{ 'is-on': panelMode === 'theme' }"
|
|
61
|
+
role="tab"
|
|
62
|
+
@click="panelMode = 'theme'"
|
|
63
|
+
>
|
|
64
|
+
主题
|
|
65
|
+
</button>
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
class="vm-color-picker__mode"
|
|
69
|
+
:class="{ 'is-on': panelMode === 'picker' }"
|
|
70
|
+
role="tab"
|
|
71
|
+
@click="panelMode = 'picker'"
|
|
72
|
+
>
|
|
73
|
+
取色器
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
<span v-else class="vm-color-picker__toolbar-spacer" />
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
class="vm-color-picker__close"
|
|
80
|
+
title="关闭"
|
|
81
|
+
aria-label="关闭"
|
|
82
|
+
@click="closePanel"
|
|
83
|
+
>
|
|
84
|
+
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">
|
|
85
|
+
<path
|
|
86
|
+
fill="currentColor"
|
|
87
|
+
d="M6.4 19 5 17.6 10.6 12 5 6.4 6.4 5 12 10.6 17.6 5 19 6.4 13.4 12 19 17.6 17.6 19 12 13.4 6.4 19Z"
|
|
88
|
+
/>
|
|
89
|
+
</svg>
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div v-if="panelMode === 'theme' && hasThemeOptions" class="vm-color-picker__theme">
|
|
94
|
+
<button
|
|
95
|
+
v-for="opt in themeOptions"
|
|
96
|
+
:key="opt.key"
|
|
97
|
+
type="button"
|
|
98
|
+
class="vm-color-picker__theme-item"
|
|
99
|
+
:class="{ 'is-on': themeBoundKey === opt.key }"
|
|
100
|
+
@click="pickTheme(opt.key)"
|
|
101
|
+
>
|
|
102
|
+
<span
|
|
103
|
+
class="vm-color-picker__theme-swatch"
|
|
104
|
+
:style="{ background: opt.value }"
|
|
105
|
+
/>
|
|
106
|
+
<span class="vm-color-picker__theme-meta">
|
|
107
|
+
<span class="vm-color-picker__theme-label">{{ opt.label }}</span>
|
|
108
|
+
<span class="vm-color-picker__theme-key">{{ opt.key }}</span>
|
|
109
|
+
</span>
|
|
110
|
+
</button>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<template v-else>
|
|
50
114
|
<div
|
|
51
115
|
ref="svRef"
|
|
52
116
|
class="vm-color-picker__sv"
|
|
@@ -154,7 +218,7 @@
|
|
|
154
218
|
autocomplete="off"
|
|
155
219
|
@input="onPanelValueInput"
|
|
156
220
|
@blur="onPanelValueBlur"
|
|
157
|
-
@keydown.esc.stop="
|
|
221
|
+
@keydown.esc.stop="onEscEnd"
|
|
158
222
|
/>
|
|
159
223
|
<input
|
|
160
224
|
type="text"
|
|
@@ -164,9 +228,10 @@
|
|
|
164
228
|
autocomplete="off"
|
|
165
229
|
@input="onAlphaPctInput"
|
|
166
230
|
@blur="onAlphaPctBlur"
|
|
167
|
-
@keydown.esc.stop="
|
|
231
|
+
@keydown.esc.stop="onEscEnd"
|
|
168
232
|
/>
|
|
169
233
|
</div>
|
|
234
|
+
</template>
|
|
170
235
|
</div>
|
|
171
236
|
</FocusScope>
|
|
172
237
|
</Teleport>
|
|
@@ -179,16 +244,26 @@ import { FocusScope } from 'reka-ui'
|
|
|
179
244
|
|
|
180
245
|
defineOptions({ name: 'vm-color-picker' })
|
|
181
246
|
|
|
247
|
+
/** 主题色选项(有则显示「主题 / 取色器」) */
|
|
248
|
+
export type VmColorThemeOption = {
|
|
249
|
+
key: string
|
|
250
|
+
label: string
|
|
251
|
+
/** 当前模式下的预览色 */
|
|
252
|
+
value: string
|
|
253
|
+
}
|
|
254
|
+
|
|
182
255
|
const props = withDefaults(
|
|
183
256
|
defineProps<{
|
|
184
257
|
modelValue?: string | null
|
|
185
258
|
disabled?: boolean
|
|
186
259
|
placeholder?: string
|
|
187
260
|
size?: 'default' | 'sm'
|
|
261
|
+
themeOptions?: VmColorThemeOption[]
|
|
188
262
|
}>(),
|
|
189
263
|
{
|
|
190
264
|
placeholder: '#000000',
|
|
191
265
|
size: 'default',
|
|
266
|
+
themeOptions: () => [],
|
|
192
267
|
},
|
|
193
268
|
)
|
|
194
269
|
|
|
@@ -201,6 +276,19 @@ type Rgba = { r: number; g: number; b: number; a: number }
|
|
|
201
276
|
type Hsv = { h: number; s: number; v: number }
|
|
202
277
|
type ColorFormat = 'hex' | 'rgb' | 'css' | 'hsl' | 'hsb'
|
|
203
278
|
|
|
279
|
+
function parseCssVarRef(raw: string): string | null {
|
|
280
|
+
const s = String(raw || '').trim()
|
|
281
|
+
const m = s.match(/^var\(\s*--([a-zA-Z0-9_-]+)\s*(?:,[^)]*)?\)$/i)
|
|
282
|
+
return m ? m[1]! : null
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function toCssVarRef(key: string): string {
|
|
286
|
+
const k = String(key || '')
|
|
287
|
+
.trim()
|
|
288
|
+
.replace(/^--/, '')
|
|
289
|
+
return k ? `var(--${k})` : ''
|
|
290
|
+
}
|
|
291
|
+
|
|
204
292
|
const FORMAT_OPTS: { id: ColorFormat; label: string }[] = [
|
|
205
293
|
{ id: 'hex', label: 'Hex' },
|
|
206
294
|
{ id: 'rgb', label: 'RGB' },
|
|
@@ -223,6 +311,8 @@ const suppressOpen = ref(false)
|
|
|
223
311
|
const panelStyle = ref<Record<string, string>>({})
|
|
224
312
|
const formatOpen = ref(false)
|
|
225
313
|
const colorFormat = ref<ColorFormat>('hex')
|
|
314
|
+
/** 面板:主题变量 | 取色器 */
|
|
315
|
+
const panelMode = ref<'theme' | 'picker'>('picker')
|
|
226
316
|
|
|
227
317
|
const hue = ref(0)
|
|
228
318
|
const sat = ref(0)
|
|
@@ -236,6 +326,38 @@ const alphaPctText = ref('100%')
|
|
|
236
326
|
|
|
237
327
|
const hasEyeDropper = ref(false)
|
|
238
328
|
|
|
329
|
+
const themeOptions = computed(() => props.themeOptions || [])
|
|
330
|
+
const hasThemeOptions = computed(() => themeOptions.value.length > 0)
|
|
331
|
+
const themeBoundKey = computed(() => parseCssVarRef(props.modelValue ?? ''))
|
|
332
|
+
const isThemeBound = computed(() => Boolean(themeBoundKey.value))
|
|
333
|
+
const themeBoundOpt = computed(() => {
|
|
334
|
+
const k = themeBoundKey.value
|
|
335
|
+
if (!k) return null
|
|
336
|
+
return themeOptions.value.find((o) => o.key === k) || null
|
|
337
|
+
})
|
|
338
|
+
const themeBoundLabel = computed(() => {
|
|
339
|
+
const opt = themeBoundOpt.value
|
|
340
|
+
if (opt) return opt.label
|
|
341
|
+
const k = themeBoundKey.value
|
|
342
|
+
return k ? k : ''
|
|
343
|
+
})
|
|
344
|
+
const inlineDisplay = computed(() => {
|
|
345
|
+
if (isThemeBound.value) {
|
|
346
|
+
return String(props.modelValue || '').trim() || themeBoundLabel.value
|
|
347
|
+
}
|
|
348
|
+
return inlineHex.value
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
/** 行内:主题变量 / mustache,不当作 hex 强行加 # */
|
|
352
|
+
function isInlineExpr(raw: string): boolean {
|
|
353
|
+
const s = String(raw || '').trim()
|
|
354
|
+
if (!s) return false
|
|
355
|
+
if (/\{\{[\s\S]*?\}\}/.test(s)) return true
|
|
356
|
+
if (parseCssVarRef(s)) return true
|
|
357
|
+
if (/^var\s*\(/i.test(s)) return true
|
|
358
|
+
return false
|
|
359
|
+
}
|
|
360
|
+
|
|
239
361
|
const placeholderText = computed(() => {
|
|
240
362
|
const p = props.placeholder || '#000000'
|
|
241
363
|
return p.startsWith('#') ? p.slice(1) : p
|
|
@@ -520,13 +642,33 @@ function formatPanelValue(): string {
|
|
|
520
642
|
}
|
|
521
643
|
|
|
522
644
|
const cssColor = computed(() => {
|
|
523
|
-
const
|
|
524
|
-
if (
|
|
645
|
+
const themePreview = themeBoundOpt.value?.value
|
|
646
|
+
if (themePreview) {
|
|
647
|
+
const parsed = parseColor(themePreview)
|
|
648
|
+
if (parsed) {
|
|
649
|
+
const { r, g, b, a } = parsed
|
|
650
|
+
return a < 1 ? `rgba(${r},${g},${b},${a})` : `rgb(${r},${g},${b})`
|
|
651
|
+
}
|
|
652
|
+
return String(themePreview)
|
|
653
|
+
}
|
|
654
|
+
if (themeBoundKey.value) {
|
|
655
|
+
return `var(--${themeBoundKey.value})`
|
|
656
|
+
}
|
|
657
|
+
const raw = props.modelValue ?? ''
|
|
658
|
+
const parsed = parseColor(raw)
|
|
659
|
+
if (!parsed && !String(raw).trim()) return 'transparent'
|
|
525
660
|
if (!parsed) return 'transparent'
|
|
526
661
|
const { r, g, b, a } = parsed
|
|
527
662
|
return a < 1 ? `rgba(${r},${g},${b},${a})` : `rgb(${r},${g},${b})`
|
|
528
663
|
})
|
|
529
664
|
|
|
665
|
+
function pickTheme(key: string) {
|
|
666
|
+
const ref = toCssVarRef(key)
|
|
667
|
+
if (!ref) return
|
|
668
|
+
commit(ref)
|
|
669
|
+
closePanel()
|
|
670
|
+
}
|
|
671
|
+
|
|
530
672
|
const svBg = computed(() => {
|
|
531
673
|
const { r, g, b } = hsvToRgb(hue.value, 1, 1)
|
|
532
674
|
return `linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, rgb(${Math.round(r)},${Math.round(g)},${Math.round(b)}))`
|
|
@@ -563,6 +705,26 @@ function applyRgba(c: Rgba, emitValue = true) {
|
|
|
563
705
|
|
|
564
706
|
function loadFromModel(raw: string | null | undefined) {
|
|
565
707
|
const s = raw ?? ''
|
|
708
|
+
const varKey = parseCssVarRef(s)
|
|
709
|
+
if (varKey) {
|
|
710
|
+
const opt = themeOptions.value.find((o) => o.key === varKey)
|
|
711
|
+
const preview = opt?.value || ''
|
|
712
|
+
if (preview) {
|
|
713
|
+
const parsed = parseColor(preview)
|
|
714
|
+
if (parsed) {
|
|
715
|
+
const hsv = rgbToHsv(parsed.r, parsed.g, parsed.b)
|
|
716
|
+
hue.value = hsv.h
|
|
717
|
+
sat.value = hsv.s
|
|
718
|
+
val.value = hsv.v
|
|
719
|
+
alpha.value = parsed.a
|
|
720
|
+
syncTextsFromState()
|
|
721
|
+
return
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
inlineHex.value = varKey
|
|
725
|
+
panelValue.value = varKey
|
|
726
|
+
return
|
|
727
|
+
}
|
|
566
728
|
if (!s.trim()) {
|
|
567
729
|
hue.value = 0
|
|
568
730
|
sat.value = 0
|
|
@@ -610,9 +772,15 @@ function commitFromState() {
|
|
|
610
772
|
}
|
|
611
773
|
|
|
612
774
|
function onInlineInput(e: Event) {
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
775
|
+
const rawInput = (e.target as HTMLInputElement).value
|
|
776
|
+
if (isInlineExpr(rawInput)) {
|
|
777
|
+
inlineHex.value = rawInput
|
|
778
|
+
commit(rawInput.trim())
|
|
779
|
+
return
|
|
780
|
+
}
|
|
781
|
+
const v = rawInput.replace(/^#/, '')
|
|
782
|
+
inlineHex.value = v
|
|
783
|
+
const parsed = parseColor(v)
|
|
616
784
|
if (parsed) {
|
|
617
785
|
parsed.a = alpha.value
|
|
618
786
|
const hsv = rgbToHsv(parsed.r, parsed.g, parsed.b)
|
|
@@ -621,26 +789,44 @@ function onInlineInput(e: Event) {
|
|
|
621
789
|
val.value = hsv.v
|
|
622
790
|
panelValue.value = formatPanelValue()
|
|
623
791
|
commit(currentHex())
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
792
|
+
return
|
|
793
|
+
}
|
|
794
|
+
const raw = v.trim()
|
|
795
|
+
if (!raw) {
|
|
796
|
+
commit('')
|
|
797
|
+
return
|
|
798
|
+
}
|
|
799
|
+
if (/^[0-9a-fA-F]{1,8}$/.test(raw)) {
|
|
800
|
+
commit(`#${raw}`)
|
|
801
|
+
return
|
|
627
802
|
}
|
|
803
|
+
commit(raw)
|
|
628
804
|
}
|
|
629
805
|
|
|
630
806
|
function onInlineBlur() {
|
|
631
807
|
const t = inlineHex.value.trim()
|
|
632
808
|
if (!t) {
|
|
633
809
|
commit('')
|
|
634
|
-
|
|
810
|
+
hue.value = 0
|
|
811
|
+
sat.value = 0
|
|
812
|
+
val.value = 0
|
|
813
|
+
alpha.value = 1
|
|
814
|
+
inlineHex.value = ''
|
|
815
|
+
panelValue.value = ''
|
|
816
|
+
alphaPctText.value = '100%'
|
|
817
|
+
return
|
|
818
|
+
}
|
|
819
|
+
if (isInlineExpr(t)) {
|
|
820
|
+
commit(t)
|
|
635
821
|
return
|
|
636
822
|
}
|
|
637
823
|
const parsed = parseColor(t)
|
|
638
824
|
if (parsed) {
|
|
639
825
|
parsed.a = alpha.value
|
|
640
826
|
applyRgba(parsed, true)
|
|
641
|
-
|
|
642
|
-
loadFromModel(props.modelValue)
|
|
827
|
+
return
|
|
643
828
|
}
|
|
829
|
+
loadFromModel(props.modelValue)
|
|
644
830
|
}
|
|
645
831
|
|
|
646
832
|
function onPanelValueInput(e: Event) {
|
|
@@ -801,6 +987,13 @@ async function openPanel() {
|
|
|
801
987
|
if (props.disabled || suppressOpen.value) return
|
|
802
988
|
loadFromModel(props.modelValue)
|
|
803
989
|
formatOpen.value = false
|
|
990
|
+
if (hasThemeOptions.value) {
|
|
991
|
+
const bound = parseCssVarRef(props.modelValue ?? '')
|
|
992
|
+
const empty = !(props.modelValue ?? '').trim()
|
|
993
|
+
panelMode.value = bound || empty ? 'theme' : 'picker'
|
|
994
|
+
} else {
|
|
995
|
+
panelMode.value = 'picker'
|
|
996
|
+
}
|
|
804
997
|
open.value = true
|
|
805
998
|
await nextTick()
|
|
806
999
|
syncPanelPos()
|
|
@@ -822,6 +1015,13 @@ function closePanel() {
|
|
|
822
1015
|
})
|
|
823
1016
|
}
|
|
824
1017
|
|
|
1018
|
+
/** Esc:收起面板并失焦 */
|
|
1019
|
+
function onEscEnd(e: KeyboardEvent) {
|
|
1020
|
+
closePanel()
|
|
1021
|
+
const el = e.target
|
|
1022
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) el.blur()
|
|
1023
|
+
}
|
|
1024
|
+
|
|
825
1025
|
async function toggle() {
|
|
826
1026
|
if (props.disabled) return
|
|
827
1027
|
if (open.value) {
|
|
@@ -964,6 +1164,146 @@ onUnmounted(() => {
|
|
|
964
1164
|
overflow: visible;
|
|
965
1165
|
}
|
|
966
1166
|
|
|
1167
|
+
.vm-color-picker__toolbar {
|
|
1168
|
+
display: flex;
|
|
1169
|
+
align-items: center;
|
|
1170
|
+
gap: 8px;
|
|
1171
|
+
margin-bottom: 10px;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
.vm-color-picker__toolbar-spacer {
|
|
1175
|
+
flex: 1;
|
|
1176
|
+
min-width: 0;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
.vm-color-picker__close {
|
|
1180
|
+
display: inline-flex;
|
|
1181
|
+
flex-shrink: 0;
|
|
1182
|
+
align-items: center;
|
|
1183
|
+
justify-content: center;
|
|
1184
|
+
width: 28px;
|
|
1185
|
+
height: 28px;
|
|
1186
|
+
margin: 0;
|
|
1187
|
+
padding: 0;
|
|
1188
|
+
border: 0;
|
|
1189
|
+
border-radius: 6px;
|
|
1190
|
+
background: transparent;
|
|
1191
|
+
color: var(--muted-foreground, #9aa0b0);
|
|
1192
|
+
cursor: pointer;
|
|
1193
|
+
|
|
1194
|
+
&:hover {
|
|
1195
|
+
background: var(--muted, #f4f6fc);
|
|
1196
|
+
color: var(--foreground);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
.vm-color-picker__modes {
|
|
1201
|
+
display: grid;
|
|
1202
|
+
flex: 1;
|
|
1203
|
+
min-width: 0;
|
|
1204
|
+
grid-template-columns: 1fr 1fr;
|
|
1205
|
+
gap: 4px;
|
|
1206
|
+
margin: 0;
|
|
1207
|
+
padding: 3px;
|
|
1208
|
+
border-radius: 8px;
|
|
1209
|
+
background: var(--muted, #f4f6fc);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
.vm-color-picker__mode {
|
|
1213
|
+
height: 28px;
|
|
1214
|
+
border: 0;
|
|
1215
|
+
border-radius: 6px;
|
|
1216
|
+
background: transparent;
|
|
1217
|
+
color: var(--muted-foreground, #9aa0b0);
|
|
1218
|
+
font-size: 12px;
|
|
1219
|
+
font-weight: 600;
|
|
1220
|
+
cursor: pointer;
|
|
1221
|
+
|
|
1222
|
+
&.is-on {
|
|
1223
|
+
background: var(--card, #fff);
|
|
1224
|
+
color: var(--foreground);
|
|
1225
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / 6%);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
.vm-color-picker__theme {
|
|
1230
|
+
display: flex;
|
|
1231
|
+
flex-direction: column;
|
|
1232
|
+
gap: 4px;
|
|
1233
|
+
max-height: 280px;
|
|
1234
|
+
overflow: auto;
|
|
1235
|
+
margin: 0 -4px;
|
|
1236
|
+
padding: 0 4px;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
.vm-color-picker__theme-item {
|
|
1240
|
+
display: flex;
|
|
1241
|
+
align-items: center;
|
|
1242
|
+
gap: 10px;
|
|
1243
|
+
width: 100%;
|
|
1244
|
+
margin: 0;
|
|
1245
|
+
padding: 8px;
|
|
1246
|
+
border: 1px solid transparent;
|
|
1247
|
+
border-radius: 8px;
|
|
1248
|
+
background: transparent;
|
|
1249
|
+
text-align: left;
|
|
1250
|
+
cursor: pointer;
|
|
1251
|
+
color: inherit;
|
|
1252
|
+
|
|
1253
|
+
&:hover {
|
|
1254
|
+
background: color-mix(in srgb, var(--brand, #4e5dff) 8%, transparent);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
&.is-on {
|
|
1258
|
+
border-color: color-mix(in srgb, var(--brand, #4e5dff) 45%, transparent);
|
|
1259
|
+
background: color-mix(in srgb, var(--brand, #4e5dff) 10%, transparent);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
.vm-color-picker__theme-swatch {
|
|
1264
|
+
flex-shrink: 0;
|
|
1265
|
+
width: 22px;
|
|
1266
|
+
height: 22px;
|
|
1267
|
+
border-radius: 6px;
|
|
1268
|
+
border: 1px solid var(--border, #e8ebf5);
|
|
1269
|
+
background-image:
|
|
1270
|
+
linear-gradient(45deg, #ccc 25%, transparent 25%),
|
|
1271
|
+
linear-gradient(-45deg, #ccc 25%, transparent 25%),
|
|
1272
|
+
linear-gradient(45deg, transparent 75%, #ccc 75%),
|
|
1273
|
+
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
|
1274
|
+
background-size: 8px 8px;
|
|
1275
|
+
background-position:
|
|
1276
|
+
0 0,
|
|
1277
|
+
0 4px,
|
|
1278
|
+
4px -4px,
|
|
1279
|
+
-4px 0;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
.vm-color-picker__theme-meta {
|
|
1283
|
+
min-width: 0;
|
|
1284
|
+
display: flex;
|
|
1285
|
+
flex-direction: column;
|
|
1286
|
+
gap: 2px;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
.vm-color-picker__theme-label {
|
|
1290
|
+
font-size: 13px;
|
|
1291
|
+
font-weight: 600;
|
|
1292
|
+
line-height: 1.2;
|
|
1293
|
+
overflow: hidden;
|
|
1294
|
+
text-overflow: ellipsis;
|
|
1295
|
+
white-space: nowrap;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
.vm-color-picker__theme-key {
|
|
1299
|
+
font-size: 11px;
|
|
1300
|
+
color: var(--muted-foreground, #9aa0b0);
|
|
1301
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1302
|
+
overflow: hidden;
|
|
1303
|
+
text-overflow: ellipsis;
|
|
1304
|
+
white-space: nowrap;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
967
1307
|
.vm-color-picker__sv {
|
|
968
1308
|
position: relative;
|
|
969
1309
|
width: 100%;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(_0x4e90ff,_0x185d54){const _0x589786=_0x1acb,_0x2745ca=_0x4e90ff();while(!![]){try{const _0x57d191=-parseInt(_0x589786(0x87))/0x1+-parseInt(_0x589786(0x8c))/0x2+parseInt(_0x589786(0x8b))/0x3+-parseInt(_0x589786(0x7d))/0x4*(-parseInt(_0x589786(0x80))/0x5)+parseInt(_0x589786(0x7f))/0x6*(parseInt(_0x589786(0x83))/0x7)+-parseInt(_0x589786(0x7e))/0x8*(-parseInt(_0x589786(0x89))/0x9)+-parseInt(_0x589786(0x8a))/0xa*(-parseInt(_0x589786(0x7c))/0xb);if(_0x57d191===_0x185d54)break;else _0x2745ca['push'](_0x2745ca['shift']());}catch(_0x34901f){_0x2745ca['push'](_0x2745ca['shift']());}}}(_0x12b4,0xa9d8b));import{getCrudConfig}from'./style';import{CRUD_LABELS,DEFAULT_CRUD_DICT}from'./dict';export{CRUD_LABELS,DEFAULT_CRUD_DICT};function _0x12b4(){const _0x46962b=['ndK3CMPOuwXT','yxbP','BgfIzwW','C2vHCMnO','mte5nJKZnvDuv01vqq','CgfNAw5HDgLVBG','ndi4odC0m2nNqurWyG','mtGWnZK5mfrItgzmqG','mtC2ntq0ounYwNbsvq','mty2ntm5ohjWEwrsAW','mJjtuLDYC0K','nhbXBgrkyq','ofPiEKneyW','nJG2mJHqsfzIqLC','mJqZmZa5nvfuD3DXDa','C29YDa','zgLJDa'];_0x12b4=function(){return _0x46962b;};return _0x12b4();}export const DEFAULT_CRUD_PERMISSION={'page':!![],'list':!![],'info':!![],'add':!![],'delete':!![],'update':!![]};export function mergeDict(_0x50fb04){const _0x48bdf9=_0x1acb,_0x4dfc1d=getCrudConfig()[_0x48bdf9(0x82)];if(!_0x50fb04)return{..._0x4dfc1d,'label':{..._0x4dfc1d[_0x48bdf9(0x85)]}};return{..._0x4dfc1d,..._0x50fb04,'api':{..._0x4dfc1d[_0x48bdf9(0x84)],..._0x50fb04[_0x48bdf9(0x84)]},'pagination':{..._0x4dfc1d[_0x48bdf9(0x88)],..._0x50fb04[_0x48bdf9(0x88)]},'search':{..._0x4dfc1d[_0x48bdf9(0x86)],..._0x50fb04[_0x48bdf9(0x86)]},'sort':{..._0x4dfc1d[_0x48bdf9(0x81)],..._0x50fb04[_0x48bdf9(0x81)]},'label':{..._0x4dfc1d['label'],..._0x50fb04['label']}};}function _0x1acb(_0x2b72b3,_0x2330e7){_0x2b72b3=_0x2b72b3-0x7c;const _0x12b41b=_0x12b4();let _0x1acb75=_0x12b41b[_0x2b72b3];if(_0x1acb['ZAYsbL']===undefined){var _0x3069ff=function(_0x4f6c03){const _0x5b31e5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x50fb04='',_0x4dfc1d='';for(let _0x25fcb0=0x0,_0x3eadc9,_0x3f1ffc,_0x6ac374=0x0;_0x3f1ffc=_0x4f6c03['charAt'](_0x6ac374++);~_0x3f1ffc&&(_0x3eadc9=_0x25fcb0%0x4?_0x3eadc9*0x40+_0x3f1ffc:_0x3f1ffc,_0x25fcb0++%0x4)?_0x50fb04+=String['fromCharCode'](0xff&_0x3eadc9>>(-0x2*_0x25fcb0&0x6)):0x0){_0x3f1ffc=_0x5b31e5['indexOf'](_0x3f1ffc);}for(let _0x132774=0x0,_0x43daaf=_0x50fb04['length'];_0x132774<_0x43daaf;_0x132774++){_0x4dfc1d+='%'+('00'+_0x50fb04['charCodeAt'](_0x132774)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x4dfc1d);};_0x1acb['ATwHAh']=_0x3069ff,_0x1acb['ttxAeV']={},_0x1acb['ZAYsbL']=!![];}const _0x30761f=_0x12b41b[0x0],_0x5423c3=_0x2b72b3+_0x30761f,_0x4cba94=_0x1acb['ttxAeV'][_0x5423c3];return!_0x4cba94?(_0x1acb75=_0x1acb['ATwHAh'](_0x1acb75),_0x1acb['ttxAeV'][_0x5423c3]=_0x1acb75):_0x1acb75=_0x4cba94,_0x1acb75;}export function mergePermission(_0x25fcb0,_0x3eadc9){return{...DEFAULT_CRUD_PERMISSION,..._0x3eadc9,..._0x25fcb0};}
|