@hankchen/canvas-editor-vue 0.2.0 → 0.3.0

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.
@@ -1,9 +1,9 @@
1
1
  import { t as e } from "./createLucideIcon-SCvtEGVf.js";
2
2
  import { c as t, d as n, f as r, l as i, o as a, p as o, s, u as c } from "./dist-DGtNmLwo.js";
3
3
  import { i as l, n as u, o as d } from "./layerPath-uy2ywyld.js";
4
- import { i as f, r as p } from "./completionAnchor-CDR5YZhu.js";
4
+ import { i as f, r as p } from "./completionAnchor-Da8VhzMQ.js";
5
5
  import { c as m, n as h, r as g, s as _, t as v, u as y } from "./useTransientFeedback-CTjmMmFF.js";
6
- import { i as b, n as x, r as S, t as C } from "./uploadFile-BOfv8aLG.js";
6
+ import { i as b, n as x, r as S, t as C } from "./uploadFile-DXAEX9kG.js";
7
7
  import { n as w, t as T } from "./useViewport-D9Ipevzs.js";
8
8
  import { Fragment as E, computed as D, createBlock as O, createCommentVNode as k, createElementBlock as A, createElementVNode as j, createVNode as M, defineComponent as N, mergeProps as P, nextTick as F, normalizeClass as I, normalizeStyle as L, onBeforeUnmount as R, onMounted as z, onScopeDispose as B, openBlock as V, ref as H, renderList as U, shallowRef as W, toDisplayString as G, unref as K, vModelText as ee, vShow as q, watch as J, withDirectives as Y, withKeys as X, withModifiers as Z } from "vue";
9
9
  var Q = e({
package/dist/canvas.js CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g } from "./canvas-C70NSsoF.js";
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g } from "./canvas-ZMyaouKe.js";
2
2
  export { e as AlignFloatBar, n as CanvasSurface, f as ContentTypePill, a as ContextMenu, l as FindBar, m as GuidesOverlay, d as Ruler, c as TextEditingOverlay, u as createGizmoOverlayPainter, h as createRafScheduler, t as drawCreateRubberBand, s as drawFindMatches, p as drawSelectionGizmo, r as useDpr, o as useFindSession, g as useTextEditing, i as watchDprChanges };
@@ -0,0 +1,470 @@
1
+ import { Fragment as e, Teleport as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, defineComponent as o, mergeProps as s, nextTick as c, normalizeClass as l, normalizeStyle as u, openBlock as d, ref as f, renderList as p, resolveDynamicComponent as m, toDisplayString as h, watch as g, withModifiers as _ } from "vue";
2
+ //#region ../canvas-editor/src/shared/expressionSchema.ts
3
+ function v(e) {
4
+ let t = e;
5
+ for (; t !== void 0;) {
6
+ if (t.properties !== void 0) return t.properties;
7
+ t = t.items;
8
+ }
9
+ return null;
10
+ }
11
+ function y(e, t) {
12
+ let n = e;
13
+ for (let e of t) {
14
+ let t = v(n)?.get(e);
15
+ if (t === void 0) return null;
16
+ n = t;
17
+ }
18
+ return n;
19
+ }
20
+ function b(e) {
21
+ if (e.type === "array" || e.items !== void 0) return { entries: [] };
22
+ let t = e.properties === void 0 ? [] : [...e.properties].map(([e, t]) => ({
23
+ key: e,
24
+ node: t
25
+ }));
26
+ return e.open === !0 ? {
27
+ entries: t,
28
+ open: !0
29
+ } : { entries: t };
30
+ }
31
+ function x(e, t) {
32
+ let n = t.split(".");
33
+ return t === "" || n.includes("") ? null : y(e, n)?.items ?? null;
34
+ }
35
+ //#endregion
36
+ //#region ../canvas-editor/src/shared/expressionPath.ts
37
+ function S(e) {
38
+ if (e === "") return {
39
+ ok: !1,
40
+ error: "expression_syntax_error"
41
+ };
42
+ let t = e.split(".");
43
+ if (t.includes("")) return {
44
+ ok: !1,
45
+ error: "expression_syntax_error"
46
+ };
47
+ let n = t[0], r = t.slice(1);
48
+ return n === "row" ? {
49
+ ok: !0,
50
+ head: { kind: "row" },
51
+ rest: r
52
+ } : n === "$root" ? {
53
+ ok: !0,
54
+ head: { kind: "root" },
55
+ rest: r
56
+ } : {
57
+ ok: !0,
58
+ head: {
59
+ kind: "bare",
60
+ name: n
61
+ },
62
+ rest: r
63
+ };
64
+ }
65
+ //#endregion
66
+ //#region ../canvas-editor/src/shared/expressionCall.ts
67
+ var C = " \n\r\0\v", w = " \n\r", T = `()',.${C}`;
68
+ function E(e) {
69
+ let t = 0, n = e.length;
70
+ for (; t < n && C.includes(e[t]);) t += 1;
71
+ for (; n > t && C.includes(e[n - 1]);) --n;
72
+ return e.slice(t, n);
73
+ }
74
+ function D(e, t) {
75
+ for (; t < e.length && w.includes(e[t]);) t += 1;
76
+ return t;
77
+ }
78
+ function O(e) {
79
+ let t = 0;
80
+ for (; t < e.length && !T.includes(e[t]);) t += 1;
81
+ if (t === 0) return !1;
82
+ let n = t;
83
+ for (; n < e.length && C.includes(e[n]);) n += 1;
84
+ return e[n] === "(";
85
+ }
86
+ function k(e) {
87
+ let t = 0;
88
+ for (; t < e.length && !T.includes(e[t]);) t += 1;
89
+ if (t === 0) return {
90
+ ok: !1,
91
+ error: "expression_syntax_error"
92
+ };
93
+ let n = e.slice(0, t), r = D(e, t);
94
+ if (r >= e.length || e[r] !== "(") return {
95
+ ok: !1,
96
+ error: "expression_syntax_error"
97
+ };
98
+ r = D(e, r + 1);
99
+ let i = [];
100
+ if (r < e.length && e[r] === ")") r += 1;
101
+ else for (;;) {
102
+ if (r >= e.length) return {
103
+ ok: !1,
104
+ error: "expression_syntax_error"
105
+ };
106
+ let t = A(e, r);
107
+ if (!t.ok) return t;
108
+ if (i.push(t.value), r = D(e, t.end), r >= e.length) return {
109
+ ok: !1,
110
+ error: "expression_syntax_error"
111
+ };
112
+ if (e[r] === ",") {
113
+ if (r = D(e, r + 1), r < e.length && e[r] === ")") return {
114
+ ok: !1,
115
+ error: "expression_syntax_error"
116
+ };
117
+ continue;
118
+ }
119
+ if (e[r] === ")") {
120
+ r += 1;
121
+ break;
122
+ }
123
+ return {
124
+ ok: !1,
125
+ error: "expression_syntax_error"
126
+ };
127
+ }
128
+ if (D(e, r) !== e.length || i[0] !== void 0 && i[0].type !== "path") return {
129
+ ok: !1,
130
+ error: "expression_syntax_error"
131
+ };
132
+ for (let e of i) if (e.type === "path" && !S(e.value).ok) return {
133
+ ok: !1,
134
+ error: "expression_syntax_error"
135
+ };
136
+ return {
137
+ ok: !0,
138
+ name: n,
139
+ args: i
140
+ };
141
+ }
142
+ function A(e, t) {
143
+ let n = e.length, r = e[t];
144
+ if (r === "'") {
145
+ let r = t + 1, i = "";
146
+ for (;;) {
147
+ if (r >= n) return {
148
+ ok: !1,
149
+ error: "expression_syntax_error"
150
+ };
151
+ if (e[r] === "'") {
152
+ if (r + 1 < n && e[r + 1] === "'") {
153
+ i += "'", r += 2;
154
+ continue;
155
+ }
156
+ r += 1;
157
+ break;
158
+ }
159
+ i += e[r], r += 1;
160
+ }
161
+ return {
162
+ ok: !0,
163
+ value: {
164
+ type: "string",
165
+ value: i
166
+ },
167
+ end: r
168
+ };
169
+ }
170
+ if (r >= "0" && r <= "9") {
171
+ let r = t, i = (t) => {
172
+ let n = e[t];
173
+ return n !== void 0 && n >= "0" && n <= "9";
174
+ };
175
+ for (; i(t);) t += 1;
176
+ if (t < n && e[t] === "." && i(t + 1)) for (t += 1; i(t);) t += 1;
177
+ return {
178
+ ok: !0,
179
+ value: {
180
+ type: "number",
181
+ value: e.slice(r, t)
182
+ },
183
+ end: t
184
+ };
185
+ }
186
+ let i = t;
187
+ for (; t < n && e[t] !== "," && e[t] !== ")";) t += 1;
188
+ let a = E(e.slice(i, t));
189
+ return a === "" ? {
190
+ ok: !1,
191
+ error: "expression_syntax_error"
192
+ } : {
193
+ ok: !0,
194
+ value: {
195
+ type: "path",
196
+ value: a
197
+ },
198
+ end: t
199
+ };
200
+ }
201
+ function j(e) {
202
+ let t = 0;
203
+ for (; t < e.length && !T.includes(e[t]);) t += 1;
204
+ if (t === 0) return null;
205
+ let n = D(e, t);
206
+ if (n >= e.length || e[n] !== "(") return null;
207
+ n = D(e, n + 1);
208
+ let r = 0;
209
+ for (;;) {
210
+ if (n >= e.length) return {
211
+ name: e.slice(0, t),
212
+ index: r,
213
+ text: "",
214
+ stringSlot: !1
215
+ };
216
+ let i = e[n];
217
+ if (i === "'") {
218
+ let i = n + 1;
219
+ for (;;) {
220
+ if (i >= e.length) return {
221
+ name: e.slice(0, t),
222
+ index: r,
223
+ text: e.slice(n + 1),
224
+ stringSlot: !0
225
+ };
226
+ if (e[i] === "'") {
227
+ if (i + 1 < e.length && e[i + 1] === "'") {
228
+ i += 2;
229
+ continue;
230
+ }
231
+ i += 1;
232
+ break;
233
+ }
234
+ i += 1;
235
+ }
236
+ n = i;
237
+ } else if (i !== "," && i !== ")") {
238
+ let i = n;
239
+ for (; n < e.length && e[n] !== "," && e[n] !== ")";) n += 1;
240
+ if (n >= e.length) return {
241
+ name: e.slice(0, t),
242
+ index: r,
243
+ text: E(e.slice(i)),
244
+ stringSlot: !1
245
+ };
246
+ }
247
+ if (n >= e.length) return {
248
+ name: e.slice(0, t),
249
+ index: r + 1,
250
+ text: "",
251
+ stringSlot: !1
252
+ };
253
+ if (e[n] === ")") return null;
254
+ r += 1, n = D(e, n + 1);
255
+ }
256
+ }
257
+ function M(e) {
258
+ let t = 0, n = e.length;
259
+ for (; t < n && " \n\r\0\v".includes(e[t]);) t += 1;
260
+ for (; n > t && " \n\r\0\v".includes(e[n - 1]);) --n;
261
+ return e.slice(t, n);
262
+ }
263
+ function N(e) {
264
+ return e === "" ? "expression_syntax_error" : O(e) ? k(e).ok ? null : "expression_syntax_error" : S(e).ok ? null : "expression_syntax_error";
265
+ }
266
+ function P(e) {
267
+ let t = [], n = 0, r = e.indexOf("{{");
268
+ for (; r !== -1;) {
269
+ let i = e.indexOf("}}", r + 2);
270
+ if (i === -1) {
271
+ r > n && t.push({
272
+ kind: "literal",
273
+ start: n,
274
+ end: r,
275
+ text: e.slice(n, r)
276
+ });
277
+ let i = e.slice(r);
278
+ return t.push({
279
+ kind: "open",
280
+ start: r,
281
+ end: e.length,
282
+ text: i,
283
+ expr: M(i.slice(2))
284
+ }), {
285
+ template: e,
286
+ parts: t
287
+ };
288
+ }
289
+ r > n && t.push({
290
+ kind: "literal",
291
+ start: n,
292
+ end: r,
293
+ text: e.slice(n, r)
294
+ });
295
+ let a = e.slice(r + 2, i), o = M(a), s = N(o);
296
+ t.push({
297
+ kind: "fragment",
298
+ start: r,
299
+ end: i + 2,
300
+ raw: a,
301
+ expr: o,
302
+ error: s
303
+ }), n = i + 2, r = e.indexOf("{{", n);
304
+ }
305
+ return n < e.length && t.push({
306
+ kind: "literal",
307
+ start: n,
308
+ end: e.length,
309
+ text: e.slice(n)
310
+ }), {
311
+ template: e,
312
+ parts: t
313
+ };
314
+ }
315
+ function F(e, t) {
316
+ for (let n of e.parts) if (n.kind !== "literal" && (n.kind === "open" ? t > n.start && t <= n.end : t > n.start && t < n.end)) return n;
317
+ return null;
318
+ }
319
+ //#endregion
320
+ //#region src/shared/PanelIcon.vue
321
+ var I = /* @__PURE__ */ o({
322
+ inheritAttrs: !1,
323
+ __name: "PanelIcon",
324
+ props: {
325
+ icon: {},
326
+ size: { default: 14 },
327
+ strokeWidth: { default: 2 }
328
+ },
329
+ setup(e) {
330
+ return (t, r) => (d(), n(m(e.icon), s({
331
+ size: e.size,
332
+ "stroke-width": e.strokeWidth
333
+ }, t.$attrs), null, 16, ["size", "stroke-width"]));
334
+ }
335
+ }), L = {
336
+ role: "listbox",
337
+ "aria-label": "表达式路径候选"
338
+ }, R = [
339
+ "aria-selected",
340
+ "title",
341
+ "onClick"
342
+ ], z = { class: "cn-completion__segment font-mono text-cn-fg" }, B = {
343
+ key: 0,
344
+ class: "shrink-0 rounded-sm bg-cn-field px-1 py-0.5 text-[9px] leading-none text-cn-muted"
345
+ }, V = {
346
+ key: 1,
347
+ class: "truncate text-[10px] leading-none text-cn-muted"
348
+ }, H = {
349
+ key: 0,
350
+ class: "cn-completion__hint px-2 py-1.5 text-[10px] leading-none text-cn-muted"
351
+ }, U = /* @__PURE__ */ o({
352
+ __name: "ExpressionCompletionPopup",
353
+ props: { state: {} },
354
+ emits: ["select"],
355
+ setup(o, { expose: s, emit: m }) {
356
+ let v = o, y = m, b = f(null);
357
+ return s({ rootEl: b }), g(() => v.state.activeIndex, async () => {
358
+ await c(), b.value?.querySelector(".cn-completion__option--active")?.scrollIntoView?.({ block: "nearest" });
359
+ }), (s, c) => (d(), n(t, { to: "body" }, [o.state.open ? (d(), i("div", {
360
+ key: 0,
361
+ ref_key: "rootRef",
362
+ ref: b,
363
+ class: "cn-props cn-completion fixed z-50 max-h-[200px] min-w-[140px] max-w-[280px] overflow-y-auto rounded-md border border-cn-field-line py-1 text-[11px] leading-none",
364
+ style: u({
365
+ top: `${o.state.top}px`,
366
+ left: `${o.state.left}px`
367
+ }),
368
+ onMousedown: c[0] ||= _(() => {}, ["prevent", "stop"]),
369
+ onPointerdown: c[1] ||= _(() => {}, ["stop"])
370
+ }, [a("div", L, [(d(!0), i(e, null, p(o.state.items, (e, t) => (d(), i("button", {
371
+ key: `${t}:${e.segment}`,
372
+ type: "button",
373
+ role: "option",
374
+ class: l(["cn-completion__option flex w-full items-center gap-1.5 px-2 py-1.5 text-left", t === o.state.activeIndex ? "cn-completion__option--active" : ""]),
375
+ "aria-selected": t === o.state.activeIndex,
376
+ title: e.path ?? e.segment,
377
+ onClick: (e) => y("select", t)
378
+ }, [
379
+ a("span", z, h(e.segment), 1),
380
+ e.type ? (d(), i("span", B, h(e.type), 1)) : r("", !0),
381
+ e.description ?? e.title ? (d(), i("span", V, h(e.description ?? e.title), 1)) : r("", !0)
382
+ ], 10, R))), 128))]), o.state.openMapping ? (d(), i("div", H, " 动态字段,键由模板定义 ")) : r("", !0)], 36)) : r("", !0)]));
383
+ }
384
+ });
385
+ //#endregion
386
+ //#region src/shared/completion.ts
387
+ function W(e, t, n, r, i) {
388
+ let a = t.start + 2, o = t.kind === "open" ? t.end : t.end - 2, s = Math.min(n, o), c = 0;
389
+ for (; s - c > a && " \n\r\0\v".includes(e[s - 1 - c]);) c += 1;
390
+ let l = s - c, u = l - (i.replaceLen ?? r.length);
391
+ if (u < a || i.replaceLen === void 0 && e.slice(u, l) !== r) return null;
392
+ let d = i.cursorBack ?? 0;
393
+ return d > i.segment.length ? null : {
394
+ value: e.slice(0, u) + i.segment + e.slice(l),
395
+ cursor: u + i.segment.length - d
396
+ };
397
+ }
398
+ //#endregion
399
+ //#region src/shared/completionAnchor.ts
400
+ function G(e, t) {
401
+ return parseFloat(e.getPropertyValue(t)) || 0;
402
+ }
403
+ function K(e, t, n) {
404
+ for (let r of n) {
405
+ let n = e.getPropertyValue(r);
406
+ n && t.setProperty(r, n);
407
+ }
408
+ }
409
+ var q = [
410
+ "font-family",
411
+ "font-size",
412
+ "font-weight",
413
+ "font-style",
414
+ "font-stretch",
415
+ "letter-spacing",
416
+ "word-spacing",
417
+ "line-height",
418
+ "text-transform",
419
+ "text-indent",
420
+ "tab-size"
421
+ ];
422
+ function J(e) {
423
+ return G(e, "line-height") || G(e, "font-size") * 1.4;
424
+ }
425
+ function Y(e) {
426
+ let t = document.createElement("div"), n = t.style;
427
+ return n.position = "fixed", n.top = "0", n.left = "0", n.visibility = "hidden", e(t, n), document.body.appendChild(t), t;
428
+ }
429
+ function X(e, t) {
430
+ let n = e.selectionStart ?? e.value.length, r = e.getBoundingClientRect(), i = getComputedStyle(e), a = G(i, "padding-left"), o = G(i, "padding-top"), s = null, c = Y((t, r) => {
431
+ r.whiteSpace = i.whiteSpace || "pre-wrap", r.boxSizing = "content-box", r.width = `${Math.max(0, e.clientWidth - a - G(i, "padding-right"))}px`, K(i, r, [
432
+ "padding-left",
433
+ "padding-right",
434
+ "padding-top",
435
+ "padding-bottom",
436
+ "word-break",
437
+ "overflow-wrap"
438
+ ]), K(i, r, q), s = document.createElement("span"), s.textContent = "​", t.append(document.createTextNode(e.value.slice(0, n)), s);
439
+ });
440
+ try {
441
+ let n = r.left + G(i, "border-left-width") + a + s.offsetLeft * t - e.scrollLeft, c = r.top + G(i, "border-top-width") + o + s.offsetTop * t - e.scrollTop;
442
+ return {
443
+ left: n,
444
+ top: c,
445
+ bottom: c + J(i) * t
446
+ };
447
+ } finally {
448
+ c.remove();
449
+ }
450
+ }
451
+ function Z(e, t) {
452
+ let n = e.selectionStart ?? e.value.length, r = e.getBoundingClientRect(), i = getComputedStyle(e), a = Y((t, r) => {
453
+ r.display = "inline-block", r.whiteSpace = "pre", K(i, r, q), t.textContent = e.value.slice(0, n);
454
+ });
455
+ try {
456
+ let n = a.getBoundingClientRect().width || a.offsetWidth;
457
+ return {
458
+ left: r.left + G(i, "border-left-width") + G(i, "padding-left") + n * t - e.scrollLeft,
459
+ top: r.top + G(i, "border-top-width"),
460
+ bottom: r.bottom - G(i, "border-bottom-width")
461
+ };
462
+ } finally {
463
+ a.remove();
464
+ }
465
+ }
466
+ function Q(e, t = 1) {
467
+ return e instanceof HTMLTextAreaElement ? X(e, t) : Z(e, t);
468
+ }
469
+ //#endregion
470
+ export { F as a, j as c, x as d, b as f, I as i, O as l, W as n, M as o, y as p, U as r, P as s, Q as t, S as u };
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g } from "./canvas-C70NSsoF.js";
2
- import { a as _, i as v, n as y, o as b, r as x, s as S, t as C } from "./layer-panel-BEcT9HhJ.js";
3
- import { a as w, c as T, d as E, f as D, i as O, l as k, m as A, n as j, o as M, p as N, r as P, s as F, t as I, u as L } from "./property-panel-C2etsIhF.js";
4
- import { i as R, n as z, r as B, t as V } from "./completionAnchor-CDR5YZhu.js";
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g } from "./canvas-ZMyaouKe.js";
2
+ import { a as _, i as v, n as y, o as b, r as x, s as S, t as C } from "./layer-panel-CEyB57XM.js";
3
+ import { a as w, c as T, d as E, f as D, i as O, l as k, m as A, n as j, o as M, p as N, r as P, s as F, t as I, u as L } from "./property-panel-DmSf_GPu.js";
4
+ import { i as R, n as z, r as B, t as V } from "./completionAnchor-Da8VhzMQ.js";
5
5
  import { c as H, i as U, n as W, s as G, t as K } from "./useTransientFeedback-CTjmMmFF.js";
6
- import { i as q, n as J, r as Y, t as X } from "./uploadFile-BOfv8aLG.js";
7
- import { n as Z, t as Q } from "./usePathCompletion-uJ5c_gQ0.js";
6
+ import { i as q, n as J, r as Y, t as X } from "./uploadFile-DXAEX9kG.js";
7
+ import { n as Z, t as Q } from "./usePathCompletion-C52F4phW.js";
8
8
  import { n as $, t as ee } from "./useViewport-D9Ipevzs.js";
9
9
  import { n as te, r as ne, t as re } from "./useDataSourceSchema-CGbldbUj.js";
10
10
  import { n as ie, r as ae, t as oe } from "./status-bar-_PvEXyq8.js";
@@ -1,8 +1,8 @@
1
1
  import { t as e } from "./createLucideIcon-SCvtEGVf.js";
2
2
  import { i as t, r as n, t as r } from "./layerPath-uy2ywyld.js";
3
- import { i, o as a, r as o } from "./completionAnchor-CDR5YZhu.js";
3
+ import { i, r as a, s as o } from "./completionAnchor-Da8VhzMQ.js";
4
4
  import { c as s, i as c, s as l, t as u } from "./useTransientFeedback-CTjmMmFF.js";
5
- import { n as ee, t as te } from "./usePathCompletion-uJ5c_gQ0.js";
5
+ import { n as ee, t as te } from "./usePathCompletion-C52F4phW.js";
6
6
  import { n as ne, t as re } from "./useDataSourceSchema-CGbldbUj.js";
7
7
  import { Fragment as d, computed as f, createBlock as ie, createCommentVNode as p, createElementBlock as m, createElementVNode as h, createVNode as g, defineComponent as _, nextTick as ae, normalizeClass as v, normalizeStyle as oe, onScopeDispose as y, openBlock as b, ref as x, renderList as se, shallowRef as S, toDisplayString as ce, unref as C, vModelText as w, watch as le, withCtx as T, withDirectives as E, withKeys as D, withModifiers as O } from "vue";
8
8
  var ue = e({
@@ -161,7 +161,7 @@ var j = "{{…}}";
161
161
  function M(e) {
162
162
  let t = A(e);
163
163
  if (t === null) return "";
164
- let n = a(t).parts.flatMap((e) => e.kind === "fragment" && e.expr !== "" ? [e.expr] : []);
164
+ let n = o(t).parts.flatMap((e) => e.kind === "fragment" && e.expr !== "" ? [e.expr] : []);
165
165
  return n.length === 0 ? j : n.map((e) => `{{${e}}}`).join(" ");
166
166
  }
167
167
  function N(e, t, n, i) {
@@ -307,7 +307,7 @@ var ge = { class: "cn-props flex w-[232px] shrink-0 flex-col overflow-y-auto rou
307
307
  __name: "LayerPanel",
308
308
  props: { editor: {} },
309
309
  setup(e) {
310
- let r = e, a = `解锁图层(${s("toggleLayerLock", l())})`, _ = `图层已锁定(${s("toggleLayerLock", l())} 解锁后可删除)`, y = V(r.editor), S = x(!1), k = x(""), A = x(!1);
310
+ let r = e, o = `解锁图层(${s("toggleLayerLock", l())})`, _ = `图层已锁定(${s("toggleLayerLock", l())} 解锁后可删除)`, y = V(r.editor), S = x(!1), k = x(""), A = x(!1);
311
311
  function j() {
312
312
  S.value = !1, k.value = "", A.value = !1;
313
313
  }
@@ -546,7 +546,7 @@ var ge = { class: "cn-props flex w-[232px] shrink-0 flex-col overflow-y-auto rou
546
546
  }, " 取消 ", 8, we)])
547
547
  ], 64)) : p("", !0)]),
548
548
  _: 1
549
- }, 8, ["items"]), S.value ? (b(), ie(o, {
549
+ }, 8, ["items"]), S.value ? (b(), ie(a, {
550
550
  key: 0,
551
551
  ref_key: "pathPopupRef",
552
552
  ref: B,
@@ -630,7 +630,7 @@ var ge = { class: "cn-props flex w-[232px] shrink-0 flex-col overflow-y-auto rou
630
630
  type: "button",
631
631
  "data-lock": "",
632
632
  class: v(["cn-layers__lock size-5 shrink-0 items-center justify-center rounded text-cn-muted hover:bg-cn-accent/15 hover:text-cn-accent", e.node.locked ? "flex" : "hidden group-hover:flex"]),
633
- title: e.node.locked ? a : "锁定图层(画布不可点选/拖动/删除,渲染照常)",
633
+ title: e.node.locked ? o : "锁定图层(画布不可点选/拖动/删除,渲染照常)",
634
634
  "aria-pressed": e.node.locked,
635
635
  onClick: O((t) => qe(e), ["stop"])
636
636
  }, [g(i, {
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./layer-panel-BEcT9HhJ.js";
1
+ import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./layer-panel-CEyB57XM.js";
2
2
  export { t as ADD_LAYER_MENU, e as ADD_MENU, r as ADD_TEXT_PRESET_MENU, o as LayerPanel, a as PANEL_ADD_MENU, n as isUpperHalf, i as useLayerPanel };
@@ -1,9 +1,9 @@
1
1
  import { t as e } from "./createLucideIcon-SCvtEGVf.js";
2
2
  import { a as t, c as n, d as r, f as i, i as a, l as o, n as s, p as c, r as l, s as u, t as d, u as f } from "./dist-DGtNmLwo.js";
3
3
  import { a as p, r as m } from "./layerPath-uy2ywyld.js";
4
- import { i as h, r as g } from "./completionAnchor-CDR5YZhu.js";
5
- import { i as _, n as ee, r as te, t as v } from "./uploadFile-BOfv8aLG.js";
6
- import { n as y, r as ne, t as re } from "./usePathCompletion-uJ5c_gQ0.js";
4
+ import { i as h, r as g } from "./completionAnchor-Da8VhzMQ.js";
5
+ import { i as _, n as ee, r as te, t as v } from "./uploadFile-DXAEX9kG.js";
6
+ import { n as y, r as ne, t as re } from "./usePathCompletion-C52F4phW.js";
7
7
  import { Fragment as b, computed as x, createBlock as S, createCommentVNode as C, createElementBlock as w, createElementVNode as T, createTextVNode as ie, createVNode as E, defineComponent as D, inject as ae, markRaw as O, nextTick as oe, normalizeClass as k, onScopeDispose as se, openBlock as A, provide as ce, ref as j, renderList as M, resolveDynamicComponent as le, shallowRef as N, toDisplayString as P, unref as F, vModelText as I, watch as L, watchEffect as ue, withCtx as de, withDirectives as fe, withModifiers as R } from "vue";
8
8
  var pe = e({
9
9
  name: "grid-2x2",
@@ -1,2 +1,2 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./property-panel-C2etsIhF.js";
1
+ import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./property-panel-DmSf_GPu.js";
2
2
  export { a as CANVAS_FIELD_SECTIONS, p as FIELD_SECTIONS_BY_TYPE, d as FONT_PICKER_KEY, e as IMAGE_UPLOAD_KEY, s as PropertyField, f as PropertyPanel, i as controlRegistry, n as fieldSectionsForPath, r as fieldSectionsForType, t as injectFontPicker, c as injectImageUpload, l as layerRoleAt, o as readField, u as usePropertyPanel };
@@ -11,6 +11,22 @@ export interface CompletionItem {
11
11
  title?: string;
12
12
  /** 类型徽标数据(未声明为 undefined) */
13
13
  type?: string;
14
+ /**
15
+ * 插入后光标从插入文本末端回退的码元数(expression-type-methods 工单 12):
16
+ * date() 调用插入 = 2(光标落引号内 format 参数占位)、函数名候选 = 1(落括号
17
+ * 内);缺省 0(落插入末尾)
18
+ */
19
+ cursorBack?: number;
20
+ /**
21
+ * 接受时从光标锚位回退替换的长度(工单 12;缺省 = partial 长度):桶候选携带
22
+ * 整段 expr 长度——调用插入重写「前缀 + 部分段」全量
23
+ */
24
+ replaceLen?: number;
25
+ /**
26
+ * 前缀过滤键(工单 12;缺省 = segment):桶候选 = 字段键名——与同键路径候选
27
+ * 一起按 partial 过滤(segment 是整段调用文本,直接过滤永不匹配)
28
+ */
29
+ filterKey?: string;
14
30
  }
15
31
  /**
16
32
  * 候选源一次求值结果(工单 02 partial/candidates 契约 + 工单 10 open 信号扩展):
@@ -37,13 +53,17 @@ export interface CompletionResult {
37
53
  export type CompletionSource = (expr: string) => CompletionResult | null;
38
54
  /** PHP trim() 默认字符集——内核 expressionScan 导出(单一事实源,勿按值复刻) */
39
55
  /**
40
- * 接受手术:把片段表达式末尾的 partial 换成候选 segment(工单 02 钉定的替换
41
- * 面——非整段重插、不包 `{{}}` 外壳)。part 是扫描产物(start/end 为码元索引,
42
- * end 独占),expr 物理终点 = 片段内容区终点回退 PHP trim 尾空白,partial 恒
43
- * 为其后缀;值与浮层状态漂移(partial 对不上)时拒绝手术返回 null,由调用方
44
- * 安全收口。
56
+ * 接受手术(工单 12 起光标锚定):把**光标锚位前**的替换域换成候选段(工单 02
57
+ * 钉定的替换面——非整段重插、不包 `{{}}` 外壳)。part 是扫描产物(start/end 为
58
+ * 码元索引,end 独占),cursor 是刷新时的光标锚位(片段内容区内);替换域 =
59
+ * [锚位 - 尾随空白 - replaceLen, 锚位 - 尾随空白),replaceLen 缺省 = partial
60
+ * 长度(路径面与旧行为全等——尾随输入位锚定)、桶候选携带整段 expr 长度(调用
61
+ * 插入重写前缀+部分段,工单 12)。默认替换保留漂移检验(锚位文本须等于 partial,
62
+ * 对不上拒绝手术返回 null 由调用方安全收口);replaceLen 面由锚位边界把守
63
+ * (expr 全量来自同一次刷新,漂移即越界拒绝)。返回光标 = 插入末端回退
64
+ * cursorBack(format 参数占位/括号内落点)。
45
65
  */
46
- export declare function applyCompletion(value: string, part: ExpressionScanFragment | ExpressionScanOpen, partial: string, segment: string): {
66
+ export declare function applyCompletion(value: string, part: ExpressionScanFragment | ExpressionScanOpen, cursor: number, partial: string, item: Pick<CompletionItem, 'segment' | 'replaceLen' | 'cursorBack'>): {
47
67
  value: string;
48
68
  cursor: number;
49
69
  } | null;
package/dist/shared.js CHANGED
@@ -1,7 +1,7 @@
1
- import { i as e, n as t, r as n, t as r } from "./completionAnchor-CDR5YZhu.js";
1
+ import { i as e, n as t, r as n, t as r } from "./completionAnchor-Da8VhzMQ.js";
2
2
  import { c as i, i as a, n as o, s, t as c } from "./useTransientFeedback-CTjmMmFF.js";
3
- import { i as l, n as u, r as d, t as f } from "./uploadFile-BOfv8aLG.js";
4
- import { n as p, t as m } from "./usePathCompletion-uJ5c_gQ0.js";
3
+ import { i as l, n as u, r as d, t as f } from "./uploadFile-DXAEX9kG.js";
4
+ import { n as p, t as m } from "./usePathCompletion-C52F4phW.js";
5
5
  import { n as h, t as g } from "./useViewport-D9Ipevzs.js";
6
6
  import { n as _, r as v, t as y } from "./useDataSourceSchema-CGbldbUj.js";
7
7
  import { t as b } from "./useShortcutsHelp-CsyarO2P.js";