@hankchen/canvas-editor-vue 0.1.0 → 0.1.2

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.
@@ -0,0 +1,1667 @@
1
+ import { a as e, i as t, n, r, t as i } from "./dist-B6-i-hhY.js";
2
+ import { a, r as o } from "./layerPath-uy2ywyld.js";
3
+ import { i as s, r as c } from "./completionAnchor-CDR5YZhu.js";
4
+ import { i as l, n as u, r as d, t as f } from "./uploadFile-BOfv8aLG.js";
5
+ import { n as p, r as m, t as h } from "./usePathCompletion-uJ5c_gQ0.js";
6
+ import { Fragment as g, computed as _, createBlock as v, createCommentVNode as y, createElementBlock as b, createElementVNode as x, createTextVNode as S, createVNode as C, defineComponent as w, inject as T, markRaw as E, nextTick as D, normalizeClass as O, onScopeDispose as ee, openBlock as k, provide as te, ref as A, renderList as j, resolveDynamicComponent as ne, shallowRef as M, toDisplayString as N, unref as P, vModelText as F, watch as I, watchEffect as re, withCtx as ie, withDirectives as ae, withModifiers as L } from "vue";
7
+ import { AlignCenterHorizontal as oe, AlignCenterVertical as se, AlignEndHorizontal as ce, AlignEndVertical as le, AlignStartHorizontal as ue, AlignStartVertical as de, ChevronDown as fe, Grid2x2 as pe, Square as me, SquareSplitVertical as he } from "@lucide/vue";
8
+ //#region ../canvas-editor/src/shared/resourceStatus.ts
9
+ function ge(n, r) {
10
+ if (n.type !== "ImageLayer") return !1;
11
+ if (n.expression !== null || n.src === null || e(n) <= 0 || t(n) <= 0) return !0;
12
+ if (r !== void 0) {
13
+ let e = r[n.src];
14
+ if (e !== void 0 && e !== "done") return !0;
15
+ }
16
+ return !1;
17
+ }
18
+ //#endregion
19
+ //#region src/property-panel/fieldSchema.ts
20
+ var _e = "当前层内容未绘制,padding 不影响预览", R = {
21
+ title: "位置与尺寸",
22
+ fields: [
23
+ {
24
+ key: ["position"],
25
+ label: "位置",
26
+ control: "pair",
27
+ items: [{
28
+ key: ["x"],
29
+ label: "X",
30
+ control: "number",
31
+ integer: !0
32
+ }, {
33
+ key: ["y"],
34
+ label: "Y",
35
+ control: "number",
36
+ integer: !0
37
+ }]
38
+ },
39
+ {
40
+ key: ["shape"],
41
+ label: "尺寸",
42
+ control: "pair",
43
+ items: [{
44
+ key: ["width"],
45
+ label: "宽",
46
+ control: "number",
47
+ integer: !0,
48
+ min: 0,
49
+ auto: {
50
+ key: ["autoWidth"],
51
+ placeholder: "自动"
52
+ }
53
+ }, {
54
+ key: ["height"],
55
+ label: "高",
56
+ control: "number",
57
+ integer: !0,
58
+ min: 0,
59
+ auto: { key: ["autoHeight"] }
60
+ }]
61
+ },
62
+ {
63
+ key: ["angle"],
64
+ label: "旋转角",
65
+ control: "number",
66
+ integer: !0,
67
+ visibleWhen: (e) => e.type === "TextLayer"
68
+ },
69
+ {
70
+ key: ["position", "anchor"],
71
+ label: "锚点",
72
+ control: "anchor"
73
+ }
74
+ ]
75
+ }, z = {
76
+ title: "对齐",
77
+ fields: [{
78
+ key: ["align", "horizontal"],
79
+ label: "水平",
80
+ control: "align",
81
+ domain: n
82
+ }, {
83
+ key: ["align", "vertical"],
84
+ label: "垂直",
85
+ control: "align",
86
+ domain: r
87
+ }]
88
+ }, B = {
89
+ title: "形状",
90
+ fields: [
91
+ {
92
+ key: ["shape", "backgroundColor"],
93
+ label: "背景色",
94
+ control: "color",
95
+ nullable: !0
96
+ },
97
+ {
98
+ key: ["shape", "lineHeight"],
99
+ label: "行高倍数",
100
+ control: "number",
101
+ step: .1,
102
+ min: 0,
103
+ visibleWhen: (e) => e.type === "TextLayer"
104
+ },
105
+ {
106
+ key: ["shape", "padding"],
107
+ label: "内边距",
108
+ control: "padding",
109
+ title: "内边距作用于内容盒,不改变图层尺寸",
110
+ hint: (e, t) => ge(e, t) ? _e : null
111
+ },
112
+ {
113
+ key: ["shape", "border"],
114
+ label: "边框",
115
+ control: "border"
116
+ }
117
+ ]
118
+ }, V = {
119
+ ImageLayer: [
120
+ R,
121
+ z,
122
+ B,
123
+ {
124
+ title: "图片",
125
+ fields: [{
126
+ key: ["src"],
127
+ label: "资源地址",
128
+ control: "imageSrc",
129
+ data: !0
130
+ }]
131
+ }
132
+ ],
133
+ TextLayer: [
134
+ R,
135
+ z,
136
+ B,
137
+ {
138
+ title: "文本",
139
+ fields: [
140
+ {
141
+ key: ["text"],
142
+ label: "内容",
143
+ control: "textarea",
144
+ data: !0
145
+ },
146
+ {
147
+ key: ["font"],
148
+ label: "字体",
149
+ control: "font"
150
+ },
151
+ {
152
+ key: ["fontSize"],
153
+ label: "字号",
154
+ control: "number",
155
+ integer: !0,
156
+ min: 1
157
+ },
158
+ {
159
+ key: ["fontColor"],
160
+ label: "字色",
161
+ control: "color"
162
+ },
163
+ {
164
+ key: ["autowrap"],
165
+ label: "自动换行",
166
+ control: "boolean"
167
+ }
168
+ ]
169
+ }
170
+ ],
171
+ QrCodeLayer: [
172
+ R,
173
+ z,
174
+ B,
175
+ {
176
+ title: "二维码",
177
+ fields: [{
178
+ key: ["value"],
179
+ label: "内容",
180
+ control: "text",
181
+ data: !0
182
+ }]
183
+ }
184
+ ],
185
+ TableLayer: [
186
+ R,
187
+ z,
188
+ B,
189
+ {
190
+ title: "数据",
191
+ fields: [{
192
+ key: ["rowsPath"],
193
+ label: "数据行路径",
194
+ control: "text",
195
+ placeholder: "如 order.items",
196
+ nonEmpty: !0,
197
+ completion: "rowsPath",
198
+ visibleWhen: (e) => e.type === "TableLayer" && e.template !== null
199
+ }]
200
+ }
201
+ ],
202
+ TableRowLayer: [
203
+ R,
204
+ z,
205
+ B
206
+ ],
207
+ TableCellLayer: [
208
+ R,
209
+ z,
210
+ B
211
+ ],
212
+ TableRowTemplate: [{
213
+ title: "行模板(行宽由表宽同步)",
214
+ fields: [{
215
+ key: ["shape", "height"],
216
+ label: "高",
217
+ control: "number",
218
+ integer: !0,
219
+ min: 0
220
+ }, {
221
+ key: ["shape", "autoHeight"],
222
+ label: "高自适应",
223
+ control: "boolean"
224
+ }]
225
+ }]
226
+ };
227
+ function H(e) {
228
+ return V[e] ?? [];
229
+ }
230
+ function U(e) {
231
+ if (e[e.length - 1] === "content") return o(e) ? "templateContent" : "content";
232
+ let t = e[e.length - 2];
233
+ return t === "rows" ? "row" : t === "cells" ? "cell" : "root";
234
+ }
235
+ var ve = {
236
+ root: [],
237
+ cell: [],
238
+ row: ["shape.width", "shape.autoWidth"],
239
+ content: [
240
+ "shape.width",
241
+ "shape.autoWidth",
242
+ "shape.height",
243
+ "shape.autoHeight"
244
+ ],
245
+ templateContent: ["shape.width", "shape.autoWidth"]
246
+ };
247
+ function W(e, t) {
248
+ return [...e.key, ...t.key];
249
+ }
250
+ function ye(e, t) {
251
+ let n = new Set(ve[U(e)]), r = [];
252
+ for (let e of H(t.type)) {
253
+ let i = [];
254
+ for (let r of e.fields) {
255
+ if (r.items) {
256
+ let e = r.items.filter((e) => !n.has(W(r, e).join(".")) && (!e.visibleWhen || e.visibleWhen(t)));
257
+ e.length > 0 && i.push({
258
+ ...r,
259
+ items: e
260
+ });
261
+ continue;
262
+ }
263
+ n.has(r.key.join(".")) || (!r.visibleWhen || r.visibleWhen(t)) && i.push(r);
264
+ }
265
+ i.length > 0 && r.push({
266
+ title: e.title,
267
+ fields: i
268
+ });
269
+ }
270
+ return r;
271
+ }
272
+ var be = [{
273
+ title: "画布",
274
+ fields: [{
275
+ key: ["width"],
276
+ label: "宽",
277
+ control: "number",
278
+ integer: !0,
279
+ min: 1
280
+ }, {
281
+ key: ["height"],
282
+ label: "高",
283
+ control: "number",
284
+ integer: !0,
285
+ min: 1
286
+ }]
287
+ }];
288
+ function G(e, t) {
289
+ let n = e;
290
+ for (let e = 0; e < t.length; e += 1) {
291
+ if (typeof n != "object" || !n) return { ok: !1 };
292
+ n = n[t[e]];
293
+ }
294
+ return n === void 0 ? { ok: !1 } : {
295
+ ok: !0,
296
+ value: n
297
+ };
298
+ }
299
+ //#endregion
300
+ //#region src/property-panel/fields/AlignField.vue?vue&type=script&setup=true&lang.ts
301
+ var xe = ["aria-label"], Se = [
302
+ "aria-pressed",
303
+ "title",
304
+ "onClick"
305
+ ], Ce = {
306
+ key: 1,
307
+ class: "truncate px-1 text-[10px] leading-none"
308
+ }, we = /* @__PURE__ */ w({
309
+ __name: "AlignField",
310
+ props: {
311
+ field: {},
312
+ modelValue: {}
313
+ },
314
+ emits: ["change"],
315
+ setup(e, { emit: t }) {
316
+ let i = e, a = t, o = {
317
+ [n.join(".")]: {
318
+ left: {
319
+ icon: de,
320
+ title: "左对齐"
321
+ },
322
+ center: {
323
+ icon: se,
324
+ title: "居中对齐"
325
+ },
326
+ right: {
327
+ icon: le,
328
+ title: "右对齐"
329
+ }
330
+ },
331
+ [r.join(".")]: {
332
+ top: {
333
+ icon: ue,
334
+ title: "顶对齐"
335
+ },
336
+ center: {
337
+ icon: oe,
338
+ title: "居中对齐"
339
+ },
340
+ bottom: {
341
+ icon: ce,
342
+ title: "底对齐"
343
+ }
344
+ }
345
+ }, c = _(() => {
346
+ let e = i.field.domain ?? [], t = o[e.join(".")];
347
+ return e.map((e) => ({
348
+ value: e,
349
+ icon: t?.[e]?.icon,
350
+ title: t?.[e] ? `${i.field.label}:${t[e].title}` : `${i.field.label}:${e}`
351
+ }));
352
+ });
353
+ function l(e) {
354
+ e !== i.modelValue && a("change", e);
355
+ }
356
+ return (t, n) => (k(), b("span", {
357
+ class: "cn-align flex h-7 min-w-0 flex-1 overflow-hidden rounded-md border border-cn-field-line bg-cn-field",
358
+ role: "group",
359
+ "aria-label": e.field.label
360
+ }, [(k(!0), b(g, null, j(c.value, (t, n) => (k(), b("button", {
361
+ key: t.value,
362
+ type: "button",
363
+ class: O(["cn-align__option flex min-w-0 flex-1 items-center justify-center p-0 transition-colors duration-100 focus-visible:z-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cn-accent/40", [n > 0 ? "border-l border-cn-field-line" : "", t.value === e.modelValue ? "cn-align__option--active bg-cn-accent-soft text-cn-accent" : "text-cn-muted hover:text-cn-fg"]]),
364
+ "aria-pressed": t.value === e.modelValue,
365
+ title: t.title,
366
+ onClick: L((e) => l(t.value), ["prevent"])
367
+ }, [t.icon ? (k(), v(s, {
368
+ key: 0,
369
+ icon: t.icon
370
+ }, null, 8, ["icon"])) : (k(), b("span", Ce, N(t.value), 1))], 10, Se))), 128))], 8, xe));
371
+ }
372
+ }), Te = { class: "block" }, Ee = ["aria-expanded", "title"], De = { class: "cn-prop-field__label shrink-0 select-none truncate text-[11px] leading-none text-cn-muted" }, Oe = { class: "flex shrink-0 items-center gap-1.5" }, ke = {
373
+ viewBox: "0 0 24 24",
374
+ class: "size-3.5",
375
+ "aria-hidden": "true"
376
+ }, Ae = [
377
+ "cx",
378
+ "cy",
379
+ "r"
380
+ ], je = {
381
+ key: 0,
382
+ class: "mt-2 flex justify-end"
383
+ }, Me = {
384
+ class: "cn-anchor grid w-[66px] shrink-0 grid-cols-3 gap-[3px]",
385
+ role: "group",
386
+ "aria-label": "九宫锚点"
387
+ }, Ne = [
388
+ "aria-pressed",
389
+ "title",
390
+ "onClick"
391
+ ], K = /* @__PURE__ */ w({
392
+ __name: "AnchorDisclosureField",
393
+ props: {
394
+ field: {},
395
+ modelValue: {},
396
+ expanded: { type: Boolean }
397
+ },
398
+ emits: ["change", "toggle"],
399
+ setup(e, { emit: t }) {
400
+ let n = e, r = t, a = E(i), o = Array.from({ length: 9 }, (e, t) => ({
401
+ index: t,
402
+ cx: 4 + t % 3 * 8,
403
+ cy: 4 + Math.floor(t / 3) * 8
404
+ })), c = _(() => {
405
+ let e = n.modelValue.includes("top") ? 0 : n.modelValue.includes("bottom") ? 2 : 1, t = n.modelValue.includes("left") ? 0 : n.modelValue.includes("right") ? 2 : 1;
406
+ return e * 3 + t;
407
+ });
408
+ function l(e) {
409
+ r("change", e);
410
+ }
411
+ return (t, n) => (k(), b("span", Te, [x("button", {
412
+ type: "button",
413
+ class: "cn-anchor-disclosure__header flex w-full items-center justify-between gap-2",
414
+ "aria-expanded": e.expanded,
415
+ title: e.expanded ? "收起锚点" : `锚点:${e.modelValue}(点击展开调整)`,
416
+ onClick: n[0] ||= (e) => r("toggle")
417
+ }, [x("span", De, N(e.field.label), 1), x("span", Oe, [(k(), b("svg", ke, [(k(!0), b(g, null, j(P(o), (e) => (k(), b("circle", {
418
+ key: e.index,
419
+ cx: e.cx,
420
+ cy: e.cy,
421
+ r: e.index === c.value ? 3.2 : 2.2,
422
+ class: O(e.index === c.value ? "fill-cn-accent" : "fill-cn-muted/35")
423
+ }, null, 10, Ae))), 128))])), C(s, {
424
+ icon: P(fe),
425
+ class: O(["text-cn-muted transition-transform duration-150", { "rotate-180": e.expanded }])
426
+ }, null, 8, ["icon", "class"])])], 8, Ee), e.expanded ? (k(), b("span", je, [x("span", Me, [(k(!0), b(g, null, j(P(a), (t) => (k(), b("button", {
427
+ key: t,
428
+ type: "button",
429
+ class: O(["cn-anchor__cell relative aspect-square min-w-0 rounded-[4px] border p-0 transition-colors duration-100", t === e.modelValue ? "cn-anchor__cell--active border-cn-accent bg-cn-accent shadow-[0_0_8px_rgba(56,189,248,0.35)]" : "border-cn-field-line bg-cn-field hover:border-cn-muted/50"]),
430
+ "aria-pressed": t === e.modelValue,
431
+ title: t,
432
+ onClick: (e) => l(t)
433
+ }, null, 10, Ne))), 128))])])) : y("", !0)]));
434
+ }
435
+ }), Pe = { class: "cn-bool relative inline-flex h-4 w-7 shrink-0 cursor-pointer items-center" }, Fe = ["checked"], Ie = /* @__PURE__ */ w({
436
+ __name: "BooleanField",
437
+ props: {
438
+ field: {},
439
+ modelValue: { type: Boolean }
440
+ },
441
+ emits: ["change"],
442
+ setup(e, { emit: t }) {
443
+ let n = e, r = t, i = A(null);
444
+ async function a(e) {
445
+ r("change", e.target.checked), await D(), i.value && (i.value.checked = n.modelValue);
446
+ }
447
+ return re(() => {
448
+ i.value && (i.value.checked = n.modelValue);
449
+ }), (t, n) => (k(), b("label", Pe, [
450
+ x("input", {
451
+ ref_key: "inputRef",
452
+ ref: i,
453
+ class: "cn-bool__input peer sr-only",
454
+ type: "checkbox",
455
+ checked: e.modelValue,
456
+ onChange: a
457
+ }, null, 40, Fe),
458
+ n[0] ||= x("span", { class: "absolute inset-0 rounded-full border border-cn-field-line bg-cn-field transition-colors duration-150 peer-checked:border-cn-accent/60 peer-checked:bg-cn-accent/30 peer-focus-visible:ring-[3px] peer-focus-visible:ring-cn-accent/20" }, null, -1),
459
+ n[1] ||= x("span", { class: "relative mx-0.5 size-3 rounded-full bg-cn-muted shadow-sm transition-transform duration-150 peer-checked:translate-x-3 peer-checked:bg-cn-accent" }, null, -1)
460
+ ]));
461
+ }
462
+ }), Le = {
463
+ 1: [{
464
+ label: "四边",
465
+ rep: "top",
466
+ sides: [
467
+ "top",
468
+ "bottom",
469
+ "left",
470
+ "right"
471
+ ]
472
+ }],
473
+ 2: [{
474
+ label: "上下",
475
+ rep: "top",
476
+ sides: ["top", "bottom"]
477
+ }, {
478
+ label: "左右",
479
+ rep: "left",
480
+ sides: ["left", "right"]
481
+ }],
482
+ 4: [
483
+ {
484
+ label: "上",
485
+ rep: "top",
486
+ sides: ["top"]
487
+ },
488
+ {
489
+ label: "下",
490
+ rep: "bottom",
491
+ sides: ["bottom"]
492
+ },
493
+ {
494
+ label: "左",
495
+ rep: "left",
496
+ sides: ["left"]
497
+ },
498
+ {
499
+ label: "右",
500
+ rep: "right",
501
+ sides: ["right"]
502
+ }
503
+ ]
504
+ };
505
+ function Re(e) {
506
+ return e === 1 ? 2 : e === 2 ? 4 : 1;
507
+ }
508
+ function ze(e) {
509
+ return e.top === e.bottom && e.bottom === e.left && e.left === e.right ? 1 : e.top === e.bottom && e.left === e.right ? 2 : 4;
510
+ }
511
+ function Be(e, t) {
512
+ if (t === 1) {
513
+ let { top: t } = e;
514
+ return {
515
+ top: t,
516
+ bottom: t,
517
+ left: t,
518
+ right: t
519
+ };
520
+ }
521
+ if (t === 2) {
522
+ let { top: t, left: n } = e;
523
+ return {
524
+ top: t,
525
+ bottom: t,
526
+ left: n,
527
+ right: n
528
+ };
529
+ }
530
+ return e;
531
+ }
532
+ function Ve(e, t) {
533
+ return e.top === t.top && e.bottom === t.bottom && e.left === t.left && e.right === t.right;
534
+ }
535
+ function q(e, t) {
536
+ return e === null || t === null ? e === t : e.width === t.width && e.color === t.color;
537
+ }
538
+ function He(e) {
539
+ let { top: t, bottom: n, left: r, right: i } = e;
540
+ return t === null && n === null && r === null && i === null || t !== null && q(t, n) && q(t, r) && q(t, i) ? 1 : q(t, n) && q(r, i) ? 2 : 4;
541
+ }
542
+ function Ue(e, t) {
543
+ let n = (e) => e === null ? null : { ...e };
544
+ if (t === 1) {
545
+ let t = n(e.top);
546
+ return {
547
+ top: t,
548
+ bottom: n(t),
549
+ left: n(t),
550
+ right: n(t)
551
+ };
552
+ }
553
+ if (t === 2) {
554
+ let t = n(e.top), r = n(e.left);
555
+ return {
556
+ top: t,
557
+ bottom: n(t),
558
+ left: r,
559
+ right: n(r)
560
+ };
561
+ }
562
+ return e;
563
+ }
564
+ function We(e, t) {
565
+ return q(e.top, t.top) && q(e.bottom, t.bottom) && q(e.left, t.left) && q(e.right, t.right);
566
+ }
567
+ //#endregion
568
+ //#region src/property-panel/useShorthandMode.ts
569
+ function Ge(e, t) {
570
+ let n = _(() => t(e())), r = A(null), i = _(() => r.value ?? n.value);
571
+ I(e, () => {
572
+ r.value = null;
573
+ });
574
+ function a() {
575
+ let e = i.value, t = Re(e);
576
+ return r.value = t, {
577
+ from: e,
578
+ to: t
579
+ };
580
+ }
581
+ return {
582
+ mode: i,
583
+ cycle: a
584
+ };
585
+ }
586
+ //#endregion
587
+ //#region src/property-panel/controlStyles.ts
588
+ var J = "h-7 flex-1 w-full min-w-0 rounded-md border border-cn-field-line bg-cn-field text-[11.5px] leading-none text-cn-fg outline-none transition-[border-color,box-shadow,background-color] duration-100 placeholder:text-cn-muted/60 hover:border-cn-muted/40 focus:border-cn-accent/70 focus:ring-[3px] focus:ring-cn-accent/15 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-cn-field-line", Y = `${J} text-right font-mono tabular-nums`, Ke = J, qe = "w-full flex-1 min-w-0 resize-y rounded-md border border-cn-field-line bg-cn-field px-2 py-1.5 text-[11.5px] leading-5 text-cn-fg outline-none transition-[border-color,box-shadow] duration-100 placeholder:text-cn-muted/60 hover:border-cn-muted/40 focus:border-cn-accent/70 focus:ring-[3px] focus:ring-cn-accent/15 disabled:cursor-not-allowed disabled:opacity-40", Je = "size-7 shrink-0 cursor-pointer self-center rounded-md border border-cn-field-line bg-cn-field p-0.5 transition-colors hover:border-cn-muted/40 disabled:cursor-not-allowed disabled:opacity-40", Ye = ["aria-label"], Xe = /* @__PURE__ */ w({
589
+ __name: "BorderWidthInput",
590
+ props: {
591
+ value: {},
592
+ label: {}
593
+ },
594
+ emits: ["input", "change"],
595
+ setup(e, { emit: t }) {
596
+ let n = e, r = t, i = A(n.value === null ? "" : String(n.value)), a = A(!1);
597
+ I(() => n.value, (e) => {
598
+ a.value || (i.value = e === null ? "" : String(e));
599
+ });
600
+ function o(e) {
601
+ return Math.max(0, Math.trunc(e));
602
+ }
603
+ function s(e) {
604
+ if (e.value.trim() === "") return null;
605
+ let t = Number(e.value);
606
+ return Number.isFinite(t) ? t : null;
607
+ }
608
+ function c(e) {
609
+ return e === null ? "" : String(e);
610
+ }
611
+ function l(e) {
612
+ let t = e.target;
613
+ i.value = t.value;
614
+ let n = s(t);
615
+ n !== null && r("input", o(n));
616
+ }
617
+ function u(e) {
618
+ let t = s(e.target);
619
+ if (t === null) {
620
+ i.value = c(n.value);
621
+ return;
622
+ }
623
+ let a = o(t);
624
+ i.value = a === 0 ? "" : String(a), r("change", a);
625
+ }
626
+ return (t, n) => ae((k(), b("input", {
627
+ "onUpdate:modelValue": n[0] ||= (e) => i.value = e,
628
+ class: O(["cn-field cn-field--number min-w-0 flex-1", P(Y)]),
629
+ type: "number",
630
+ "aria-label": e.label,
631
+ min: 0,
632
+ step: "1",
633
+ placeholder: "无边框",
634
+ title: "宽度归 0 即关闭该边",
635
+ onInput: l,
636
+ onFocus: n[1] ||= (e) => a.value = !0,
637
+ onBlur: u,
638
+ onChange: u
639
+ }, null, 42, Ye)), [[F, i.value]]);
640
+ }
641
+ }), Ze = ["aria-label", "title"], Qe = /* @__PURE__ */ w({
642
+ __name: "ShorthandModeButton",
643
+ props: {
644
+ mode: {},
645
+ label: {}
646
+ },
647
+ emits: ["cycle"],
648
+ setup(e, { emit: t }) {
649
+ let n = e, r = t, i = {
650
+ 1: {
651
+ icon: me,
652
+ title: "统一值"
653
+ },
654
+ 2: {
655
+ icon: he,
656
+ title: "上下/左右"
657
+ },
658
+ 4: {
659
+ icon: pe,
660
+ title: "四边独立"
661
+ }
662
+ }, a = _(() => i[n.mode]), o = _(() => `${n.label}:${a.value.title}(点击切换值模式)`);
663
+ return (e, t) => (k(), b("button", {
664
+ type: "button",
665
+ class: "cn-props__mode-toggle shrink-0",
666
+ "aria-label": o.value,
667
+ title: o.value,
668
+ onClick: t[0] ||= L((e) => r("cycle"), ["prevent"])
669
+ }, [C(s, {
670
+ icon: a.value.icon,
671
+ size: 12
672
+ }, null, 8, ["icon"])], 8, Ze));
673
+ }
674
+ }), $e = { class: "cn-border flex w-full min-w-0 items-center gap-1" }, et = { class: "grid min-w-0 flex-1 gap-1 grid-cols-1" }, tt = { class: "w-5 shrink-0 select-none text-[10px] leading-none text-cn-muted" }, nt = [
675
+ "value",
676
+ "disabled",
677
+ "onInput",
678
+ "onChange"
679
+ ], rt = "#000000", it = /* @__PURE__ */ w({
680
+ __name: "BorderField",
681
+ props: {
682
+ field: {},
683
+ modelValue: {}
684
+ },
685
+ emits: ["input", "change"],
686
+ setup(e, { emit: t }) {
687
+ let n = e, r = t, { mode: i, cycle: a } = Ge(() => n.modelValue, He), o = _(() => Le[i.value]);
688
+ function s(e) {
689
+ return n.modelValue[e.rep]?.width ?? null;
690
+ }
691
+ function c(e) {
692
+ return n.modelValue[e.rep]?.color ?? rt;
693
+ }
694
+ function l(e, t, i) {
695
+ let a = { ...n.modelValue };
696
+ for (let n of e.sides) a[n] = t === null ? null : { ...t };
697
+ r(i ? "change" : "input", a);
698
+ }
699
+ function u(e, t, r) {
700
+ let i = n.modelValue[e.rep]?.color ?? rt;
701
+ l(e, t <= 0 ? null : {
702
+ width: t,
703
+ color: i
704
+ }, r);
705
+ }
706
+ function d(e, t, r) {
707
+ let i = n.modelValue[e.rep];
708
+ if (!i) return;
709
+ let a = t.target.value.trim();
710
+ a !== "" && l(e, {
711
+ width: i.width,
712
+ color: a
713
+ }, r);
714
+ }
715
+ function f() {
716
+ let { from: e, to: t } = a();
717
+ if (t < e) {
718
+ let e = Ue(n.modelValue, t);
719
+ We(e, n.modelValue) || r("change", e);
720
+ }
721
+ }
722
+ return (t, n) => (k(), b("span", $e, [C(Qe, {
723
+ mode: P(i),
724
+ label: "边框",
725
+ onCycle: f
726
+ }, null, 8, ["mode"]), x("span", et, [(k(!0), b(g, null, j(o.value, (t) => (k(), b("label", {
727
+ key: t.rep,
728
+ class: "flex items-center gap-1.5"
729
+ }, [
730
+ x("span", tt, N(t.label), 1),
731
+ C(Xe, {
732
+ class: "cn-border__width",
733
+ value: s(t),
734
+ label: t.label,
735
+ onInput: (e) => u(t, e, !1),
736
+ onChange: (e) => u(t, e, !0)
737
+ }, null, 8, [
738
+ "value",
739
+ "label",
740
+ "onInput",
741
+ "onChange"
742
+ ]),
743
+ x("input", {
744
+ class: "cn-border__color size-6 shrink-0 cursor-pointer self-center rounded-md border border-cn-field-line bg-cn-field p-0.5 transition-colors hover:border-cn-muted/40 disabled:cursor-not-allowed disabled:opacity-40",
745
+ type: "color",
746
+ title: "边框颜色",
747
+ value: c(t),
748
+ disabled: e.modelValue[t.rep] === null,
749
+ onInput: (e) => d(t, e, !1),
750
+ onChange: (e) => d(t, e, !0)
751
+ }, null, 40, nt)
752
+ ]))), 128))])]));
753
+ }
754
+ }), at = Symbol("canvas-font-picker");
755
+ function ot() {
756
+ return T(at, null);
757
+ }
758
+ //#endregion
759
+ //#region src/property-panel/fields/FontField.vue?vue&type=script&setup=true&lang.ts
760
+ var st = ["value"], ct = {
761
+ key: 1,
762
+ class: "flex flex-1 items-center gap-1.5"
763
+ }, lt = ["value"], ut = ["value"], dt = [
764
+ "disabled",
765
+ "title",
766
+ "data-upload-error"
767
+ ], ft = /* @__PURE__ */ w({
768
+ __name: "FontField",
769
+ props: {
770
+ field: {},
771
+ modelValue: {}
772
+ },
773
+ emits: ["input", "change"],
774
+ setup(e, { emit: t }) {
775
+ let n = e, r = t, i = ot(), a = _(() => {
776
+ if (i === null) return [];
777
+ let e = [{
778
+ label: "内置默认字体",
779
+ value: ""
780
+ }];
781
+ for (let t of i.entries.value) t.ref !== "" && e.push({
782
+ label: t.label,
783
+ value: t.ref
784
+ });
785
+ let t = n.modelValue;
786
+ return t !== "" && !e.some((e) => e.value === t) && e.push({
787
+ label: `${o(t)}(清单外引用)`,
788
+ value: t
789
+ }), e;
790
+ });
791
+ function o(e) {
792
+ return e.startsWith("data:") ? "自定义字体(内联)" : e.split("/").pop() || e;
793
+ }
794
+ function s(e) {
795
+ r("change", e.target.value);
796
+ }
797
+ let c = !1;
798
+ function l(e) {
799
+ c || e.isComposing || r("input", e.target.value);
800
+ }
801
+ function u() {
802
+ c = !0;
803
+ }
804
+ function d(e) {
805
+ c = !1, r("input", e.target.value);
806
+ }
807
+ function p(e) {
808
+ c = !1, r("change", e.target.value);
809
+ }
810
+ let m = A(!1), h = A(null), v = A(null);
811
+ function S() {
812
+ h.value = null, v.value?.click();
813
+ }
814
+ async function C(e) {
815
+ let t = e.target, n = t.files?.[0];
816
+ if (t.value = "", i !== null && n && !m.value) {
817
+ m.value = !0;
818
+ try {
819
+ let e = await i.uploadFont(await f(n));
820
+ r("change", e);
821
+ } catch (e) {
822
+ h.value = e instanceof Error ? e.message : String(e);
823
+ } finally {
824
+ m.value = !1;
825
+ }
826
+ }
827
+ }
828
+ return (t, n) => P(i) === null ? (k(), b("input", {
829
+ key: 0,
830
+ class: O(["cn-field", P(Ke)]),
831
+ type: "text",
832
+ value: e.modelValue,
833
+ onInput: l,
834
+ onCompositionstart: u,
835
+ onCompositionend: d,
836
+ onChange: p
837
+ }, null, 42, st)) : (k(), b("div", ct, [
838
+ x("select", {
839
+ class: O(["cn-field cn-select", P(J)]),
840
+ value: e.modelValue,
841
+ onChange: s
842
+ }, [(k(!0), b(g, null, j(a.value, (e) => (k(), b("option", {
843
+ key: e.value,
844
+ value: e.value
845
+ }, N(e.label), 9, ut))), 128))], 42, lt),
846
+ x("input", {
847
+ ref_key: "fileInput",
848
+ ref: v,
849
+ type: "file",
850
+ class: "hidden",
851
+ accept: ".ttf,.otf,.woff,.woff2,font/ttf,font/otf,font/woff,font/woff2",
852
+ onChange: C
853
+ }, null, 544),
854
+ P(i).canUpload ? (k(), b("button", {
855
+ key: 0,
856
+ type: "button",
857
+ class: "h-7 shrink-0 rounded-md border border-cn-field-line bg-cn-field px-2 text-[11px] leading-none text-cn-fg transition-colors duration-100 hover:border-cn-muted/40 disabled:cursor-not-allowed disabled:opacity-40",
858
+ disabled: m.value,
859
+ title: h.value ?? "上传本机字体(加入清单后可选)",
860
+ "data-upload-error": h.value ?? void 0,
861
+ onClick: S
862
+ }, N(m.value ? "…" : h.value ? "!" : "上传"), 9, dt)) : y("", !0)
863
+ ]));
864
+ }
865
+ }), pt = { class: "cn-color flex min-w-0 flex-1 items-center gap-1.5" }, mt = ["checked"], ht = ["value", "disabled"], gt = ["value", "disabled"], _t = "#000000", vt = /* @__PURE__ */ w({
866
+ __name: "ColorField",
867
+ props: {
868
+ field: {},
869
+ modelValue: {}
870
+ },
871
+ emits: ["input", "change"],
872
+ setup(e, { emit: t }) {
873
+ let n = e, r = t, i = A(n.modelValue !== null), a = A(o(n.modelValue));
874
+ I(() => n.modelValue, (e) => {
875
+ i.value = e !== null, i.value && (a.value = o(e));
876
+ });
877
+ function o(e) {
878
+ return e !== null && /^#[0-9a-fA-F]{6}$/.test(e) ? e : _t;
879
+ }
880
+ function s(e) {
881
+ let t = e.target.checked;
882
+ if (i.value = t, !t) {
883
+ r("change", null);
884
+ return;
885
+ }
886
+ let n = a.value;
887
+ r("change", n);
888
+ }
889
+ function c(e) {
890
+ let t = e.target.value;
891
+ a.value = t, r("input", t);
892
+ }
893
+ function l(e) {
894
+ let t = e.target.value;
895
+ a.value = t, r("change", t);
896
+ }
897
+ function u(e) {
898
+ let t = e.target.value.trim();
899
+ if (t === "") {
900
+ n.field.nullable && r("change", null);
901
+ return;
902
+ }
903
+ a.value = o(t), r("change", t);
904
+ }
905
+ return (t, n) => (k(), b("span", pt, [
906
+ e.field.nullable ? (k(), b("input", {
907
+ key: 0,
908
+ class: "cn-color__toggle size-3.5 shrink-0 cursor-pointer accent-cn-accent",
909
+ type: "checkbox",
910
+ title: "启用颜色",
911
+ checked: i.value,
912
+ onChange: s
913
+ }, null, 40, mt)) : y("", !0),
914
+ x("input", {
915
+ class: O(["cn-color__swatch", P(Je)]),
916
+ type: "color",
917
+ value: a.value,
918
+ disabled: !i.value,
919
+ onInput: c,
920
+ onChange: l
921
+ }, null, 42, ht),
922
+ x("input", {
923
+ class: O(["cn-color__text min-w-0 flex-1", P(J)]),
924
+ type: "text",
925
+ value: e.modelValue ?? "",
926
+ disabled: !i.value,
927
+ placeholder: "无",
928
+ onChange: u
929
+ }, null, 42, gt)
930
+ ]));
931
+ }
932
+ }), X = Symbol("canvas-image-upload");
933
+ function yt() {
934
+ return T(X, null);
935
+ }
936
+ //#endregion
937
+ //#region src/property-panel/fields/TextField.vue?vue&type=script&setup=true&lang.ts
938
+ var bt = ["value", "placeholder"], Z = /* @__PURE__ */ w({
939
+ __name: "TextField",
940
+ props: {
941
+ field: {},
942
+ modelValue: {}
943
+ },
944
+ emits: ["input", "change"],
945
+ setup(e, { emit: t }) {
946
+ let n = e, r = t, i = !1, a = A(!1);
947
+ function o(e) {
948
+ return n.field.nonEmpty === !0 ? e.trim() === "" ? (a.value = !0, !0) : (a.value = !1, !1) : !1;
949
+ }
950
+ function s(e) {
951
+ let t = e.target.value;
952
+ i || e.isComposing || o(t) || r("input", t);
953
+ }
954
+ function c() {
955
+ i = !0;
956
+ }
957
+ function l(e) {
958
+ i = !1;
959
+ let t = e.target.value;
960
+ o(t) || r("input", t);
961
+ }
962
+ function u(e) {
963
+ i = !1;
964
+ let t = e.target.value;
965
+ o(t) || r("change", t);
966
+ }
967
+ return (t, n) => (k(), b("input", {
968
+ class: O(["cn-field", [P(Ke), a.value ? "cn-field--invalid" : ""]]),
969
+ type: "text",
970
+ value: e.modelValue,
971
+ placeholder: e.field.placeholder,
972
+ onInput: s,
973
+ onCompositionstart: c,
974
+ onCompositionend: l,
975
+ onChange: u
976
+ }, null, 42, bt));
977
+ }
978
+ }), xt = {
979
+ key: 0,
980
+ class: "flex flex-col gap-1.5"
981
+ }, St = [
982
+ "disabled",
983
+ "title",
984
+ "data-upload-error"
985
+ ], Ct = ["src"], wt = {
986
+ key: 2,
987
+ class: "relative"
988
+ }, Tt = { class: "flex items-center gap-1.5" }, Et = /* @__PURE__ */ w({
989
+ __name: "ImageSrcField",
990
+ props: {
991
+ field: {},
992
+ modelValue: {},
993
+ dataMode: {},
994
+ resourceStatus: {}
995
+ },
996
+ emits: ["input", "change"],
997
+ setup(e, { emit: t }) {
998
+ let n = e, r = t, i = yt(), a = _(() => i !== null && i.canUpload && n.dataMode !== "expression"), o = _(() => typeof n.modelValue == "string" && n.modelValue !== ""), s = _(() => n.resourceStatus === "pending" ? "装载中" : n.resourceStatus === "failed" ? "失败" : null), c = A(!1), l = A(null), u = A(null);
999
+ function d() {
1000
+ l.value = null, u.value?.click();
1001
+ }
1002
+ async function p(e) {
1003
+ let t = e.target, n = t.files?.[0];
1004
+ if (t.value = "", i !== null && n && !c.value) {
1005
+ c.value = !0;
1006
+ try {
1007
+ let e = await i.uploadImage(await f(n));
1008
+ e !== null && r("change", e);
1009
+ } catch (e) {
1010
+ l.value = e instanceof Error ? e.message : String(e);
1011
+ } finally {
1012
+ c.value = !1;
1013
+ }
1014
+ }
1015
+ }
1016
+ return (t, n) => a.value ? (k(), b("div", xt, [
1017
+ x("button", {
1018
+ type: "button",
1019
+ class: "cn-imagesrc__thumb relative flex h-16 w-full items-center justify-center overflow-hidden rounded-md border border-dashed border-cn-field-line bg-cn-field/40 text-[11px] leading-none text-cn-muted transition-colors duration-100 hover:border-cn-muted/40 disabled:cursor-not-allowed disabled:opacity-40",
1020
+ disabled: c.value,
1021
+ title: l.value ?? (o.value ? "点击替换图片" : "点击上传图片"),
1022
+ "data-upload-error": l.value ?? void 0,
1023
+ onClick: d
1024
+ }, [
1025
+ o.value ? (k(), b("img", {
1026
+ key: 0,
1027
+ src: e.modelValue ?? void 0,
1028
+ class: "absolute inset-0 size-full object-cover",
1029
+ alt: ""
1030
+ }, null, 8, Ct)) : y("", !0),
1031
+ s.value ? (k(), b("span", {
1032
+ key: 1,
1033
+ class: O(["cn-imagesrc__status absolute right-1 top-1 rounded bg-cn-bg-elevated/90 px-1 py-0.5 text-[10px] leading-none", e.resourceStatus === "failed" ? "text-red-400" : "text-cn-muted"])
1034
+ }, N(s.value), 3)) : y("", !0),
1035
+ o.value ? y("", !0) : (k(), b("span", wt, N(c.value ? "…" : l.value ? "!" : "点击上传图片"), 1))
1036
+ ], 8, St),
1037
+ x("input", {
1038
+ ref_key: "fileInput",
1039
+ ref: u,
1040
+ type: "file",
1041
+ class: "hidden",
1042
+ accept: "image/*",
1043
+ onChange: p
1044
+ }, null, 544),
1045
+ x("div", Tt, [C(Z, {
1046
+ class: "flex-1",
1047
+ field: e.field,
1048
+ "model-value": e.modelValue ?? "",
1049
+ "aria-label": e.field.label,
1050
+ onInput: n[0] ||= (e) => r("input", e),
1051
+ onChange: n[1] ||= (e) => r("change", e)
1052
+ }, null, 8, [
1053
+ "field",
1054
+ "model-value",
1055
+ "aria-label"
1056
+ ]), o.value ? (k(), b("button", {
1057
+ key: 0,
1058
+ type: "button",
1059
+ class: "cn-imagesrc__clear h-7 shrink-0 rounded-md border border-cn-field-line bg-cn-field px-2 text-[11px] leading-none text-cn-fg transition-colors duration-100 hover:border-cn-muted/40",
1060
+ title: "清除图片(资源地址置空)",
1061
+ onClick: n[2] ||= (e) => r("change", "")
1062
+ }, "清除")) : y("", !0)])
1063
+ ])) : (k(), v(Z, {
1064
+ key: 1,
1065
+ field: e.field,
1066
+ "model-value": e.modelValue ?? "",
1067
+ "aria-label": e.field.label,
1068
+ onInput: n[3] ||= (e) => r("input", e),
1069
+ onChange: n[4] ||= (e) => r("change", e)
1070
+ }, null, 8, [
1071
+ "field",
1072
+ "model-value",
1073
+ "aria-label"
1074
+ ]));
1075
+ }
1076
+ }), Dt = [
1077
+ "aria-label",
1078
+ "min",
1079
+ "max",
1080
+ "step"
1081
+ ], Q = /* @__PURE__ */ w({
1082
+ __name: "NumberField",
1083
+ props: {
1084
+ field: {},
1085
+ modelValue: {}
1086
+ },
1087
+ emits: ["input", "change"],
1088
+ setup(e, { emit: t }) {
1089
+ let n = e, r = t, i = A(String(n.modelValue)), a = A(!1);
1090
+ I(() => n.modelValue, (e) => {
1091
+ a.value || (i.value = String(e));
1092
+ });
1093
+ function o(e) {
1094
+ let t = n.field.integer ? Math.trunc(e) : e;
1095
+ return n.field.min !== void 0 && (t = Math.max(n.field.min, t)), n.field.max !== void 0 && (t = Math.min(n.field.max, t)), t;
1096
+ }
1097
+ function s(e) {
1098
+ if (e.value.trim() === "") return null;
1099
+ let t = Number(e.value);
1100
+ return Number.isFinite(t) ? t : null;
1101
+ }
1102
+ function c(e) {
1103
+ let t = e.target;
1104
+ i.value = t.value;
1105
+ let n = s(t);
1106
+ n !== null && r("input", o(n));
1107
+ }
1108
+ function l(e) {
1109
+ let t = s(e.target);
1110
+ if (t === null) {
1111
+ i.value = String(n.modelValue);
1112
+ return;
1113
+ }
1114
+ let a = o(t);
1115
+ i.value = String(a), r("change", a);
1116
+ }
1117
+ return (t, n) => ae((k(), b("input", {
1118
+ "onUpdate:modelValue": n[0] ||= (e) => i.value = e,
1119
+ class: O(["cn-field cn-field--number", P(Y)]),
1120
+ type: "number",
1121
+ "aria-label": e.field.label,
1122
+ min: e.field.min,
1123
+ max: e.field.max,
1124
+ step: e.field.step ?? (e.field.integer ? 1 : .1),
1125
+ onInput: c,
1126
+ onFocus: n[1] ||= (e) => a.value = !0,
1127
+ onBlur: l,
1128
+ onChange: l
1129
+ }, null, 42, Dt)), [[F, i.value]]);
1130
+ }
1131
+ }), Ot = { class: "cn-padding flex w-full min-w-0 items-center gap-1.5" }, kt = { class: "w-5 shrink-0 select-none text-[10px] leading-none text-cn-muted" }, At = /* @__PURE__ */ w({
1132
+ __name: "PaddingField",
1133
+ props: {
1134
+ field: {},
1135
+ modelValue: {}
1136
+ },
1137
+ emits: ["input", "change"],
1138
+ setup(e, { emit: t }) {
1139
+ let n = e, r = t, { mode: i, cycle: a } = Ge(() => n.modelValue, ze), o = _(() => Le[i.value]);
1140
+ function s(e) {
1141
+ return {
1142
+ key: ["padding", e.rep],
1143
+ label: e.label,
1144
+ control: "number"
1145
+ };
1146
+ }
1147
+ function c(e, t, i) {
1148
+ let a = { ...n.modelValue };
1149
+ for (let n of e.sides) a[n] = t;
1150
+ r(i ? "change" : "input", a);
1151
+ }
1152
+ function l() {
1153
+ let { from: e, to: t } = a();
1154
+ if (t < e) {
1155
+ let e = Be(n.modelValue, t);
1156
+ Ve(e, n.modelValue) || r("change", e);
1157
+ }
1158
+ }
1159
+ return (t, n) => (k(), b("span", Ot, [C(Qe, {
1160
+ mode: P(i),
1161
+ label: "内边距",
1162
+ onCycle: l
1163
+ }, null, 8, ["mode"]), x("span", { class: O(["grid min-w-0 flex-1 gap-1.5", P(i) === 1 ? "grid-cols-1" : "grid-cols-2"]) }, [(k(!0), b(g, null, j(o.value, (t) => (k(), b("label", {
1164
+ key: t.rep,
1165
+ class: "flex min-w-0 items-center gap-1.5"
1166
+ }, [x("span", kt, N(t.label), 1), C(Q, {
1167
+ class: "min-w-0 flex-1",
1168
+ field: s(t),
1169
+ "model-value": e.modelValue[t.rep],
1170
+ onInput: (e) => c(t, e, !1),
1171
+ onChange: (e) => c(t, e, !0)
1172
+ }, null, 8, [
1173
+ "field",
1174
+ "model-value",
1175
+ "onInput",
1176
+ "onChange"
1177
+ ])]))), 128))], 2)]));
1178
+ }
1179
+ }), jt = { class: "grid w-full min-w-0 grid-cols-2 gap-1" }, Mt = ["title"], Nt = { class: "w-3.5 shrink-0 select-none text-[10px] leading-none text-cn-muted" }, Pt = [
1180
+ "aria-pressed",
1181
+ "title",
1182
+ "onClick"
1183
+ ], Ft = [
1184
+ "aria-label",
1185
+ "value",
1186
+ "placeholder",
1187
+ "title"
1188
+ ], It = /* @__PURE__ */ w({
1189
+ __name: "PairField",
1190
+ props: {
1191
+ field: {},
1192
+ modelValue: {},
1193
+ displays: {}
1194
+ },
1195
+ emits: [
1196
+ "input",
1197
+ "change",
1198
+ "sub-commit"
1199
+ ],
1200
+ setup(e, { emit: t }) {
1201
+ let n = e, r = t, i = _(() => n.field.items ?? []);
1202
+ function a(e) {
1203
+ if (!e.auto) return !1;
1204
+ let t = G(n.modelValue, e.auto.key);
1205
+ return t.ok && t.value === !0;
1206
+ }
1207
+ function o(e) {
1208
+ return {
1209
+ ...e,
1210
+ key: W(n.field, e)
1211
+ };
1212
+ }
1213
+ function s(e) {
1214
+ return {
1215
+ key: [...n.field.key, ...e.auto?.key ?? []],
1216
+ label: `${e.label}自适应`,
1217
+ control: "boolean"
1218
+ };
1219
+ }
1220
+ function c(e, t, n) {
1221
+ r("sub-commit", o(e), t, n);
1222
+ }
1223
+ function l(e) {
1224
+ r("sub-commit", s(e), !a(e), !0);
1225
+ }
1226
+ function u(e) {
1227
+ let t = G(n.modelValue, e.key);
1228
+ return t.ok && typeof t.value == "number" ? t.value : 0;
1229
+ }
1230
+ function d(e) {
1231
+ return n.displays?.[W(n.field, e).join(".")];
1232
+ }
1233
+ function f(e) {
1234
+ let t = d(e);
1235
+ return t === void 0 ? "" : String(t.value);
1236
+ }
1237
+ function p(e) {
1238
+ return a(e) ? `${e.label}自适应:已开启(输入框禁用)` : `${e.label}自适应:开启后由内容决定,输入框禁用`;
1239
+ }
1240
+ function m(e) {
1241
+ let t = d(e);
1242
+ return t?.preview ? "模板子树:预览盒尺寸(随行实例变化,非文档声明值)" : t === void 0 ? `${e.label}自适应:已开启` : `${e.label}自适应:布局解析值(与画布选择框同源)`;
1243
+ }
1244
+ return (e, t) => (k(), b("span", jt, [(k(!0), b(g, null, j(i.value, (e) => (k(), b("label", {
1245
+ key: e.key.join("."),
1246
+ class: "flex min-w-0 items-center gap-1",
1247
+ title: e.auto ? void 0 : e.label
1248
+ }, [
1249
+ x("span", Nt, N(e.label), 1),
1250
+ e.auto ? (k(), b("button", {
1251
+ key: 0,
1252
+ type: "button",
1253
+ class: O(["cn-props__auto-toggle shrink-0", { "cn-props__auto-toggle--active": a(e) }]),
1254
+ "aria-pressed": a(e),
1255
+ title: p(e),
1256
+ onClick: L((t) => l(e), ["prevent"])
1257
+ }, "自", 10, Pt)) : y("", !0),
1258
+ a(e) ? (k(), b("input", {
1259
+ key: 2,
1260
+ class: O(["cn-field cn-field--number min-w-0 flex-1", [P(Y), d(e)?.preview ? "cn-field--preview" : ""]]),
1261
+ type: "number",
1262
+ disabled: "",
1263
+ "aria-label": e.label,
1264
+ value: f(e),
1265
+ placeholder: e.auto?.placeholder ?? "",
1266
+ title: m(e)
1267
+ }, null, 10, Ft)) : (k(), v(Q, {
1268
+ key: 1,
1269
+ class: "min-w-0 flex-1",
1270
+ field: e,
1271
+ "model-value": u(e),
1272
+ onInput: (t) => c(e, t, !1),
1273
+ onChange: (t) => c(e, t, !0)
1274
+ }, null, 8, [
1275
+ "field",
1276
+ "model-value",
1277
+ "onInput",
1278
+ "onChange"
1279
+ ]))
1280
+ ], 8, Mt))), 128))]));
1281
+ }
1282
+ }), Lt = ["value"], Rt = ["value"], zt = /* @__PURE__ */ w({
1283
+ __name: "SelectField",
1284
+ props: {
1285
+ field: {},
1286
+ modelValue: {}
1287
+ },
1288
+ emits: ["change"],
1289
+ setup(e, { emit: t }) {
1290
+ let n = t;
1291
+ function r(e) {
1292
+ n("change", e.target.value);
1293
+ }
1294
+ return (t, n) => (k(), b("select", {
1295
+ class: "cn-select h-7 w-full min-w-0 flex-1 cursor-pointer appearance-none rounded-md border border-cn-field-line bg-cn-field py-0 pl-2 pr-6 text-[11px] leading-none text-cn-fg outline-none transition-[border-color,box-shadow] duration-100 hover:border-cn-muted/40 focus:border-cn-accent/70 focus:ring-[3px] focus:ring-cn-accent/15 disabled:cursor-not-allowed disabled:opacity-40",
1296
+ value: e.modelValue,
1297
+ onChange: r
1298
+ }, [(k(!0), b(g, null, j(e.field.domain ?? [], (e) => (k(), b("option", {
1299
+ key: e,
1300
+ value: e
1301
+ }, N(e), 9, Rt))), 128))], 40, Lt));
1302
+ }
1303
+ }), Bt = ["value"], Vt = /* @__PURE__ */ w({
1304
+ __name: "TextareaField",
1305
+ props: {
1306
+ field: {},
1307
+ modelValue: {}
1308
+ },
1309
+ emits: ["input", "change"],
1310
+ setup(e, { emit: t }) {
1311
+ let n = t, r = !1;
1312
+ function i(e) {
1313
+ let t = e.target.value;
1314
+ r || e.isComposing || n("input", t);
1315
+ }
1316
+ function a() {
1317
+ r = !0;
1318
+ }
1319
+ function o(e) {
1320
+ r = !1, n("input", e.target.value);
1321
+ }
1322
+ function s(e) {
1323
+ r = !1, n("change", e.target.value);
1324
+ }
1325
+ return (t, n) => (k(), b("textarea", {
1326
+ class: O(["cn-field", P(qe)]),
1327
+ rows: "3",
1328
+ value: e.modelValue,
1329
+ onInput: i,
1330
+ onCompositionstart: a,
1331
+ onCompositionend: o,
1332
+ onChange: s
1333
+ }, null, 42, Bt));
1334
+ }
1335
+ }), Ht = {
1336
+ number: E(Q),
1337
+ text: E(Z),
1338
+ textarea: E(Vt),
1339
+ color: E(vt),
1340
+ select: E(zt),
1341
+ boolean: E(Ie),
1342
+ pair: E(It),
1343
+ anchor: E(K),
1344
+ align: E(we),
1345
+ padding: E(At),
1346
+ border: E(it),
1347
+ font: E(ft),
1348
+ imageSrc: E(Et)
1349
+ };
1350
+ //#endregion
1351
+ //#region src/property-panel/usePropertyPanel.ts
1352
+ function Ut(e) {
1353
+ let t = M(e.store.doc), n = M(e.store.ui.selection), r = M(e.store.ui.anchorExpanded), i = M(e.store.ui.dataSourceSchema), o = M(e.store.ui.resourceStatuses), s = e.subscribe((a) => {
1354
+ a.scope === "doc" ? (t.value = e.store.doc, n.value = e.store.ui.selection, o.value = e.store.ui.resourceStatuses) : a.scope === "ui" && (a.branch === "selection" ? (n.value = e.store.ui.selection, e.store.closeMerge()) : a.branch === "anchorExpanded" ? r.value = e.store.ui.anchorExpanded : a.branch === "dataSourceSchema" ? i.value = e.store.ui.dataSourceSchema : a.branch === "resourceStatuses" && (o.value = e.store.ui.resourceStatuses));
1355
+ });
1356
+ ee(s, !0);
1357
+ let c = _(() => {
1358
+ let e = t.value, r = n.value;
1359
+ return e && r ? a(e, r) : null;
1360
+ }), u = _(() => t.value), f = _(() => {
1361
+ let e = c.value, r = n.value;
1362
+ return e && r ? ye(r, e) : t.value ? be : [];
1363
+ }), h = _(() => {
1364
+ let r = n.value;
1365
+ return r && t.value ? e.layerBoxAt(r) : null;
1366
+ }), g = _(() => {
1367
+ let e = i.value;
1368
+ return e === null ? null : d(e, l(e, t.value, n.value));
1369
+ }), v = _(() => p(m(t.value, n.value, i.value))), y = _(() => n.value?.includes("template") ?? !1);
1370
+ function b(t) {
1371
+ e.store.setAnchorExpanded(t);
1372
+ }
1373
+ function x(e) {
1374
+ if (!e.data) return !1;
1375
+ let t = c.value;
1376
+ return t !== null && "expression" in t && t.expression !== null;
1377
+ }
1378
+ function S(r, i, a) {
1379
+ if (!t.value) return;
1380
+ let o = n.value;
1381
+ if (!o) {
1382
+ w(r, i, a);
1383
+ return;
1384
+ }
1385
+ let s = `sel:${o.join(".")}:${r.key.join(".")}`;
1386
+ if (r.data) {
1387
+ if (x(r)) {
1388
+ let t = `sel:${o.join(".")}:data.expression`;
1389
+ e.updateDataExpression(o, i, { mergeKey: t }), a && e.store.closeMerge(t);
1390
+ return;
1391
+ }
1392
+ e.updateData(o, i, { mergeKey: s }), a && e.store.closeMerge(s);
1393
+ return;
1394
+ }
1395
+ e.updateSpec(o, r.key, i, { mergeKey: s }), a && e.store.closeMerge(s);
1396
+ }
1397
+ function C(t) {
1398
+ let r = c.value, i = n.value;
1399
+ if (!r || !i || !t.data) return;
1400
+ let a = G(r, t.key);
1401
+ if (!a.ok) return;
1402
+ let o = typeof a.value == "string" ? a.value : "";
1403
+ x(t) ? e.updateData(i, o) : e.updateDataExpression(i, o);
1404
+ }
1405
+ function w(t, n, r) {
1406
+ let i = t.key[0];
1407
+ if (i !== "width" && i !== "height" || typeof n != "number") return;
1408
+ let a = `canvas:${i}`;
1409
+ e.updateCanvasProp(i, n, { mergeKey: a }), r && e.store.closeMerge(a);
1410
+ }
1411
+ return {
1412
+ selection: _(() => n.value),
1413
+ layer: c,
1414
+ canvas: u,
1415
+ sections: f,
1416
+ layerBox: h,
1417
+ isPreviewBox: y,
1418
+ completionSource: g,
1419
+ rowsPathSource: v,
1420
+ resourceStatuses: _(() => o.value),
1421
+ anchorExpanded: _(() => r.value),
1422
+ commit: S,
1423
+ toggleDataMode: C,
1424
+ setAnchorExpanded: b
1425
+ };
1426
+ }
1427
+ //#endregion
1428
+ //#region src/property-panel/fields/ValueTypeSegmented.vue?vue&type=script&setup=true&lang.ts
1429
+ var Wt = {
1430
+ class: "cn-valuetype flex h-7 shrink-0 items-stretch overflow-hidden rounded-md border border-cn-field-line bg-cn-field",
1431
+ role: "group",
1432
+ "aria-label": "取值方式"
1433
+ }, Gt = [
1434
+ "aria-pressed",
1435
+ "title",
1436
+ "onClick"
1437
+ ], Kt = /* @__PURE__ */ w({
1438
+ __name: "ValueTypeSegmented",
1439
+ props: { mode: {} },
1440
+ emits: ["change"],
1441
+ setup(e, { emit: t }) {
1442
+ let n = e, r = t, i = [{
1443
+ value: "static",
1444
+ label: "静态",
1445
+ title: "静态值:输入的字面内容直接显示在画布上"
1446
+ }, {
1447
+ value: "expression",
1448
+ label: "表达式",
1449
+ title: "表达式值:内容为插值原文,画布显示解析镜像({{路径}} / {{$index}} / {{$root.*}})"
1450
+ }];
1451
+ function a(e) {
1452
+ e !== n.mode && r("change", e);
1453
+ }
1454
+ return (t, n) => (k(), b("span", Wt, [(k(), b(g, null, j(i, (t, n) => x("button", {
1455
+ key: t.value,
1456
+ type: "button",
1457
+ class: O(["cn-valuetype__option flex items-center justify-center p-0 px-1.5 text-[10px] leading-none transition-colors duration-100 focus-visible:z-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cn-accent/40", [n > 0 ? "border-l border-cn-field-line" : "", t.value === e.mode ? "cn-valuetype__option--active bg-cn-accent-soft text-cn-accent" : "text-cn-muted hover:text-cn-fg"]]),
1458
+ "aria-pressed": t.value === e.mode,
1459
+ title: t.value === e.mode ? t.title : `${t.title};点击切换`,
1460
+ onClick: L((e) => a(t.value), ["prevent"])
1461
+ }, N(t.label), 11, Gt)), 64))]));
1462
+ }
1463
+ }), qt = ["title"], Jt = {
1464
+ key: 2,
1465
+ class: "cn-prop-field__hint col-span-2 block text-[11px] leading-4 text-cn-muted"
1466
+ }, $ = /* @__PURE__ */ w({
1467
+ __name: "PropertyField",
1468
+ props: {
1469
+ field: {},
1470
+ value: {},
1471
+ dataMode: {},
1472
+ completion: { type: [Function, null] },
1473
+ displays: {},
1474
+ hint: {},
1475
+ resourceStatus: {}
1476
+ },
1477
+ emits: [
1478
+ "input",
1479
+ "change",
1480
+ "toggle-mode",
1481
+ "sub-commit"
1482
+ ],
1483
+ setup(e, { emit: t }) {
1484
+ let n = e, r = t, i = _(() => Ht[n.field.control]), a = _(() => n.dataMode === "expression"), o = _(() => n.field.control === "pair" ? "cn-prop-field block" : "cn-prop-field grid grid-cols-[60px_minmax(0,1fr)] items-center gap-x-2 gap-y-1.5"), s = _(() => n.field.data === !0 ? "col-span-2" : ""), l = _(() => n.field.data === !0 && (n.field.control === "textarea" || n.field.control === "text" || n.field.control === "imageSrc")), d = _(() => n.field.completion === "rowsPath"), f = _(() => l.value || d.value), p = A(null), m = _(() => {
1485
+ if (!f.value) return null;
1486
+ let e = p.value?.$el;
1487
+ return e instanceof HTMLTextAreaElement || e instanceof HTMLInputElement ? e : null;
1488
+ }), x = A(null), S = _(() => x.value?.rootEl ?? null), { popup: C, accept: w } = u({
1489
+ target: m,
1490
+ enabled: () => l.value && a.value && n.completion != null,
1491
+ pairing: () => l.value && a.value,
1492
+ resolve: (e) => n.completion?.(e) ?? null,
1493
+ popupEl: S
1494
+ }), { popup: T, accept: E } = h({
1495
+ target: m,
1496
+ enabled: () => d.value && n.completion != null,
1497
+ resolve: (e) => n.completion?.(e) ?? null,
1498
+ popupEl: S
1499
+ });
1500
+ function D(e, t, n) {
1501
+ r("sub-commit", e, t, n);
1502
+ }
1503
+ return (t, n) => (k(), b(g, null, [(k(), v(ne(e.field.control === "pair" || e.field.control === "imageSrc" ? "div" : "label"), { class: O(o.value) }, {
1504
+ default: ie(() => [
1505
+ e.field.control === "pair" ? y("", !0) : (k(), b("span", {
1506
+ key: 0,
1507
+ class: "cn-prop-field__label shrink-0 select-none truncate text-[11px] leading-none text-cn-muted",
1508
+ title: e.field.title
1509
+ }, N(e.field.label), 9, qt)),
1510
+ e.field.data ? (k(), v(Kt, {
1511
+ key: 1,
1512
+ class: "justify-self-end",
1513
+ mode: e.dataMode ?? "static",
1514
+ onChange: n[0] ||= (e) => r("toggle-mode")
1515
+ }, null, 8, ["mode"])) : y("", !0),
1516
+ (k(), v(ne(i.value), {
1517
+ ref_key: "controlRef",
1518
+ ref: p,
1519
+ class: O(["cn-prop-field__control", [s.value, { "cn-field--expression": a.value }]]),
1520
+ field: e.field,
1521
+ "model-value": e.value,
1522
+ displays: e.field.control === "pair" ? e.displays : void 0,
1523
+ "data-mode": e.field.control === "imageSrc" ? e.dataMode : void 0,
1524
+ "resource-status": e.field.control === "imageSrc" ? e.resourceStatus : void 0,
1525
+ onInput: n[1] ||= (e) => r("input", e),
1526
+ onChange: n[2] ||= (e) => r("change", e),
1527
+ onSubCommit: D
1528
+ }, null, 40, [
1529
+ "class",
1530
+ "field",
1531
+ "model-value",
1532
+ "displays",
1533
+ "data-mode",
1534
+ "resource-status"
1535
+ ])),
1536
+ e.hint ? (k(), b("span", Jt, N(e.hint), 1)) : y("", !0)
1537
+ ]),
1538
+ _: 1
1539
+ }, 8, ["class"])), l.value ? (k(), v(c, {
1540
+ key: 0,
1541
+ ref_key: "popupRef",
1542
+ ref: x,
1543
+ state: P(C),
1544
+ onSelect: P(w)
1545
+ }, null, 8, ["state", "onSelect"])) : d.value ? (k(), v(c, {
1546
+ key: 1,
1547
+ ref_key: "popupRef",
1548
+ ref: x,
1549
+ state: P(T),
1550
+ onSelect: P(E)
1551
+ }, null, 8, ["state", "onSelect"])) : y("", !0)], 64));
1552
+ }
1553
+ }), Yt = { class: "cn-props flex w-[288px] shrink-0 flex-col overflow-y-auto rounded-xl border border-cn-line bg-cn-bg text-cn-fg shadow-[0_16px_40px_-12px_rgba(2,6,23,0.55)]" }, Xt = { class: "sticky top-0 z-10 border-b border-cn-line bg-cn-bg-elevated/95 px-3.5 py-2.5 backdrop-blur-sm" }, Zt = { class: "flex items-center gap-2" }, Qt = { class: "inline-flex items-center gap-1.5 rounded border border-cn-accent/25 bg-cn-accent-soft px-1.5 py-0.5 font-mono text-[10px] leading-4 text-cn-accent" }, $t = { class: "text-[12px] font-medium tracking-wide text-cn-fg/90" }, en = {
1554
+ key: 0,
1555
+ class: "mx-3.5 my-4 rounded-lg border border-dashed border-cn-line px-3 py-6 text-center text-[11px] leading-5 text-cn-muted"
1556
+ }, tn = { class: "cn-props__section-title mb-2 text-[10px] font-semibold uppercase tracking-[0.16em] text-cn-muted" }, nn = { class: "flex flex-col gap-2" }, rn = /* @__PURE__ */ w({
1557
+ __name: "PropertyPanel",
1558
+ props: { editor: {} },
1559
+ setup(e) {
1560
+ let t = e, n = Ut(t.editor);
1561
+ te(X, {
1562
+ canUpload: t.editor.canUpload,
1563
+ uploadImage: (e) => t.editor.uploadImage(e)
1564
+ });
1565
+ function r(e) {
1566
+ return e.completion === "rowsPath" ? n.rowsPathSource.value : n.completionSource.value;
1567
+ }
1568
+ let i = _(() => n.layer.value !== null), a = _(() => {
1569
+ let e = n.layer.value;
1570
+ return e ? e.type : n.canvas.value ? "Canvas" : "—";
1571
+ });
1572
+ function o(e) {
1573
+ let t = G(e, ["expression"]);
1574
+ return t.ok && t.value !== null ? "expression" : "static";
1575
+ }
1576
+ let s = _(() => {
1577
+ let e = n.layer.value ?? (n.selection.value ? null : n.canvas.value);
1578
+ if (!e) return [];
1579
+ let t = n.selection.value?.join(".") ?? "canvas", r = n.layer.value, i = n.resourceStatuses.value, a = [];
1580
+ for (let s of n.sections.value) {
1581
+ let n = [];
1582
+ for (let a of s.fields) {
1583
+ let s = G(e, a.key);
1584
+ s.ok && n.push({
1585
+ key: `${t}:${a.key.join(".")}`,
1586
+ field: a,
1587
+ value: s.value,
1588
+ dataMode: a.data ? o(e) : void 0,
1589
+ hint: a.hint && r ? a.hint(r, i) ?? void 0 : void 0,
1590
+ resourceStatus: a.control === "imageSrc" && typeof s.value == "string" && s.value !== "" ? i[s.value] : void 0
1591
+ });
1592
+ }
1593
+ n.length > 0 && a.push({
1594
+ title: s.title,
1595
+ fields: n
1596
+ });
1597
+ }
1598
+ return a;
1599
+ }), c = _(() => {
1600
+ let e = {}, t = n.layerBox.value, r = n.layer.value;
1601
+ if (!t || !r) return e;
1602
+ let i = /* @__PURE__ */ new Map();
1603
+ if (r.shape.autoWidth && i.set("autoWidth", Math.round(t.width * 100) / 100), r.shape.autoHeight && i.set("autoHeight", Math.round(t.height * 100) / 100), i.size === 0) return e;
1604
+ for (let t of n.sections.value) for (let r of t.fields) for (let t of r.items ?? []) {
1605
+ let a = t.auto ? i.get(t.auto.key.join(".")) : void 0;
1606
+ a !== void 0 && (e[W(r, t).join(".")] = {
1607
+ value: a,
1608
+ preview: n.isPreviewBox.value
1609
+ });
1610
+ }
1611
+ return e;
1612
+ });
1613
+ function l() {
1614
+ n.setAnchorExpanded(!n.anchorExpanded.value);
1615
+ }
1616
+ return (e, t) => (k(), b("aside", Yt, [
1617
+ x("header", Xt, [x("div", Zt, [x("span", Qt, [t[0] ||= x("i", {
1618
+ class: "size-1.5 rounded-full bg-cn-accent",
1619
+ "aria-hidden": "true"
1620
+ }, null, -1), S(" " + N(a.value), 1)]), x("span", $t, N(i.value ? "图层属性" : "画布属性"), 1)])]),
1621
+ s.value.length === 0 ? (k(), b("p", en, " 打开文档后可编辑属性 ")) : y("", !0),
1622
+ (k(!0), b(g, null, j(s.value, (e) => (k(), b("section", {
1623
+ key: e.title,
1624
+ class: "cn-props__section border-b border-cn-line/70 px-3.5 py-3 last:border-b-0"
1625
+ }, [x("h3", tn, N(e.title), 1), x("div", nn, [(k(!0), b(g, null, j(e.fields, (e) => (k(), b(g, { key: e.key }, [e.field.control === "anchor" ? (k(), v(K, {
1626
+ key: 0,
1627
+ field: e.field,
1628
+ "model-value": e.value,
1629
+ expanded: P(n).anchorExpanded.value,
1630
+ onChange: (t) => P(n).commit(e.field, t, !0),
1631
+ onToggle: l
1632
+ }, null, 8, [
1633
+ "field",
1634
+ "model-value",
1635
+ "expanded",
1636
+ "onChange"
1637
+ ])) : (k(), v($, {
1638
+ key: 1,
1639
+ field: e.field,
1640
+ value: e.value,
1641
+ "data-mode": e.dataMode,
1642
+ hint: e.hint,
1643
+ completion: r(e.field),
1644
+ displays: c.value,
1645
+ "resource-status": e.resourceStatus,
1646
+ onInput: (t) => P(n).commit(e.field, t, !1),
1647
+ onChange: (t) => P(n).commit(e.field, t, !0),
1648
+ onToggleMode: (t) => P(n).toggleDataMode(e.field),
1649
+ onSubCommit: P(n).commit
1650
+ }, null, 8, [
1651
+ "field",
1652
+ "value",
1653
+ "data-mode",
1654
+ "hint",
1655
+ "completion",
1656
+ "displays",
1657
+ "resource-status",
1658
+ "onInput",
1659
+ "onChange",
1660
+ "onToggleMode",
1661
+ "onSubCommit"
1662
+ ]))], 64))), 128))])]))), 128))
1663
+ ]));
1664
+ }
1665
+ });
1666
+ //#endregion
1667
+ export { X as a, ot as c, ye as d, H as f, Ht as i, be as l, G as m, $ as n, yt as o, U as p, Ut as r, at as s, rn as t, V as u };