@hankchen/canvas-editor-vue 0.3.0 → 0.5.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.
Files changed (45) hide show
  1. package/dist/canvas/CanvasSurface.d.ts +28 -1
  2. package/dist/canvas/{ContentTypePill.d.ts → EditOverlayToolbar.d.ts} +19 -0
  3. package/dist/canvas/TextEditingOverlay.d.ts +31 -3
  4. package/dist/canvas/index.d.ts +1 -1
  5. package/dist/canvas/useTextEditing.d.ts +30 -8
  6. package/dist/{canvas-ZMyaouKe.js → canvas-CX1RdlFC.js} +816 -437
  7. package/dist/canvas.js +2 -2
  8. package/dist/index.js +15 -14
  9. package/dist/layer-panel/LayerPanel.d.ts +1 -27
  10. package/dist/layer-panel/TemplateTableForm.d.ts +38 -0
  11. package/dist/layer-panel/addMenu.d.ts +20 -8
  12. package/dist/layer-panel/index.d.ts +6 -3
  13. package/dist/{layer-panel-CEyB57XM.js → layer-panel-kOceTf8H.js} +329 -243
  14. package/dist/layer-panel.js +2 -2
  15. package/dist/panel-theme.css +24 -0
  16. package/dist/{completionAnchor-Da8VhzMQ.js → popupPosition-Ck5Gsvjy.js} +163 -107
  17. package/dist/property-panel/PropertyField.d.ts +6 -0
  18. package/dist/property-panel/fieldSchema.d.ts +7 -1
  19. package/dist/property-panel/fields/ImageSrcField.d.ts +5 -1
  20. package/dist/property-panel/fields/ResourceValueField.d.ts +19 -0
  21. package/dist/property-panel/fields/TextareaField.d.ts +1 -0
  22. package/dist/property-panel/fields/ValueTypeSegmented.d.ts +3 -1
  23. package/dist/property-panel/index.d.ts +5 -3
  24. package/dist/property-panel/usePropertyPanel.d.ts +16 -4
  25. package/dist/{property-panel-DmSf_GPu.js → property-panel-B32ZBQdf.js} +472 -376
  26. package/dist/property-panel.js +3 -2
  27. package/dist/resourceTemplate-cdcQtp9a.js +246 -0
  28. package/dist/shared/ExpressionPathPicker.d.ts +25 -0
  29. package/dist/shared/completion.d.ts +14 -10
  30. package/dist/shared/expressionContext.d.ts +2 -2
  31. package/dist/shared/index.d.ts +14 -1
  32. package/dist/shared/mergeKey.d.ts +2 -0
  33. package/dist/shared/pathPickerModel.d.ts +11 -0
  34. package/dist/shared/popupPosition.d.ts +41 -0
  35. package/dist/shared/resourceTemplate.d.ts +7 -0
  36. package/dist/shared/useExpressionCompletion.d.ts +0 -7
  37. package/dist/shared/useExpressionDiagnostics.d.ts +15 -0
  38. package/dist/shared.js +10 -9
  39. package/dist/style.css +1 -1
  40. package/dist/uploadFile-D1RY-ji0.js +516 -0
  41. package/dist/usePathCompletion-Do17CQ6l.js +220 -0
  42. package/package.json +2 -2
  43. package/dist/uploadFile-DXAEX9kG.js +0 -455
  44. package/dist/usePathCompletion-C52F4phW.js +0 -229
  45. /package/dist/{property-panel → shared}/fontPicker.d.ts +0 -0
@@ -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-CEyB57XM.js";
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
+ import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./layer-panel-kOceTf8H.js";
2
+ export { e as ADD_LAYER_MENU, a as ADD_MENU, s as ADD_RATIO_PRESET_MENU, t as ADD_TEXT_PRESET_MENU, c as LayerPanel, r as PANEL_ADD_MENU, n as TemplateTableForm, i as isUpperHalf, o as useLayerPanel };
@@ -252,3 +252,27 @@
252
252
  background-color: var(--cn-accent-soft);
253
253
  color: var(--cn-accent);
254
254
  }
255
+
256
+ /* ---- 资源路径选择器浮层(resource-expression-single-ref 工单 05)----
257
+ portal 到 body 后脱离面板 DOM 子树,根元素自带 .cn-props 重建令牌命名空间;
258
+ 抬升底色/投影与高亮态与补全浮层同语言(option 几何以 tailwind utility 留在
259
+ 组件模板)。只读展示框的盒子视觉(bg/border/圆角)同 cn-field 输入框族。 */
260
+ .cn-props.cn-pathpicker__menu {
261
+ background-color: var(--cn-bg-elevated);
262
+ box-shadow: 0 16px 40px -12px rgba(2, 6, 23, 0.55);
263
+ }
264
+
265
+ .cn-props .cn-pathpicker__option--active {
266
+ background-color: var(--cn-accent-soft);
267
+ }
268
+
269
+ /* 选择器的状态描边(工单 05):PropertyField 的状态类(cn-field--expression/
270
+ cn-field--invalid)经 fallthrough 落在选择器根盒(flex 容器无边框),描边经
271
+ 后代选择器落到只读展示框——与 cn-field--invalid 单类规则同值的定向版 */
272
+ .cn-props .cn-field--expression .cn-pathpicker__value {
273
+ border-color: var(--cn-accent);
274
+ }
275
+
276
+ .cn-props .cn-field--invalid .cn-pathpicker__value {
277
+ border-color: var(--cn-danger);
278
+ }
@@ -18,15 +18,10 @@ function y(e, t) {
18
18
  return n;
19
19
  }
20
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]) => ({
21
+ return e.type === "array" || e.items !== void 0 ? { entries: [] } : { entries: e.properties === void 0 ? [] : [...e.properties].map(([e, t]) => ({
23
22
  key: e,
24
23
  node: t
25
- }));
26
- return e.open === !0 ? {
27
- entries: t,
28
- open: !0
29
- } : { entries: t };
24
+ })) };
30
25
  }
31
26
  function x(e, t) {
32
27
  let n = t.split(".");
@@ -75,7 +70,18 @@ function D(e, t) {
75
70
  for (; t < e.length && w.includes(e[t]);) t += 1;
76
71
  return t;
77
72
  }
78
- function O(e) {
73
+ function O(e, t, n) {
74
+ return {
75
+ ok: !1,
76
+ error: "expression_syntax_error",
77
+ kind: e,
78
+ at: {
79
+ start: t,
80
+ end: n
81
+ }
82
+ };
83
+ }
84
+ function k(e) {
79
85
  let t = 0;
80
86
  for (; t < e.length && !T.includes(e[t]);) t += 1;
81
87
  if (t === 0) return !1;
@@ -83,92 +89,86 @@ function O(e) {
83
89
  for (; n < e.length && C.includes(e[n]);) n += 1;
84
90
  return e[n] === "(";
85
91
  }
86
- function k(e) {
92
+ function A(e) {
87
93
  let t = 0;
88
94
  for (; t < e.length && !T.includes(e[t]);) t += 1;
89
- if (t === 0) return {
90
- ok: !1,
91
- error: "expression_syntax_error"
92
- };
95
+ if (t === 0) return O("invalid_path", 0, e.length);
93
96
  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
- };
97
+ if (r >= e.length || e[r] !== "(") return O("missing_open_paren", t, e.length);
98
+ let i = r;
98
99
  r = D(e, r + 1);
99
- let i = [];
100
+ let a = [], o = [];
100
101
  if (r < e.length && e[r] === ")") r += 1;
101
102
  else for (;;) {
102
- if (r >= e.length) return {
103
- ok: !1,
104
- error: "expression_syntax_error"
105
- };
106
- let t = A(e, r);
103
+ if (r >= e.length) return O("unbalanced_paren", i, e.length);
104
+ let t = j(e, r);
107
105
  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
- };
106
+ if (a.push(t.value), o.push({
107
+ start: t.start,
108
+ end: t.end
109
+ }), r = D(e, t.end), r >= e.length) return O("unbalanced_paren", i, e.length);
112
110
  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
- };
111
+ let t = r;
112
+ if (r = D(e, r + 1), r < e.length && e[r] === ")") return O("empty_arg_slot", t + 1, r);
117
113
  continue;
118
114
  }
119
115
  if (e[r] === ")") {
120
116
  r += 1;
121
117
  break;
122
118
  }
123
- return {
124
- ok: !1,
125
- error: "expression_syntax_error"
126
- };
119
+ return O("bad_arg_syntax", r, r + 1);
120
+ }
121
+ if (r = D(e, r), r !== e.length) return O("trailing_after_call", r, e.length);
122
+ if (a[0] !== void 0 && a[0].type !== "path") {
123
+ let e = o[0];
124
+ return O("first_arg_not_path", e.start, e.end);
125
+ }
126
+ for (let e = 0; e < a.length; e += 1) {
127
+ let t = a[e], n = o[e];
128
+ if (t.type === "path" && !S(t.value).ok) return O("invalid_path_arg", n.start, n.end);
127
129
  }
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
130
  return {
137
131
  ok: !0,
138
132
  name: n,
139
- args: i
133
+ args: a
140
134
  };
141
135
  }
142
- function A(e, t) {
143
- let n = e.length, r = e[t];
144
- if (r === "'") {
145
- let r = t + 1, i = "";
136
+ function j(e, t) {
137
+ let n = e.length, r = t, i = e[t];
138
+ if (i === "'") {
139
+ let i = t + 1, a = "";
146
140
  for (;;) {
147
- if (r >= n) return {
141
+ if (i >= n) return {
148
142
  ok: !1,
149
- error: "expression_syntax_error"
143
+ error: "expression_syntax_error",
144
+ kind: "unterminated_string",
145
+ at: {
146
+ start: r,
147
+ end: n
148
+ }
150
149
  };
151
- if (e[r] === "'") {
152
- if (r + 1 < n && e[r + 1] === "'") {
153
- i += "'", r += 2;
150
+ if (e[i] === "'") {
151
+ if (i + 1 < n && e[i + 1] === "'") {
152
+ a += "'", i += 2;
154
153
  continue;
155
154
  }
156
- r += 1;
155
+ i += 1;
157
156
  break;
158
157
  }
159
- i += e[r], r += 1;
158
+ a += e[i], i += 1;
160
159
  }
161
160
  return {
162
161
  ok: !0,
163
162
  value: {
164
163
  type: "string",
165
- value: i
164
+ value: a
166
165
  },
167
- end: r
166
+ start: r,
167
+ end: i
168
168
  };
169
169
  }
170
- if (r >= "0" && r <= "9") {
171
- let r = t, i = (t) => {
170
+ if (i >= "0" && i <= "9") {
171
+ let i = (t) => {
172
172
  let n = e[t];
173
173
  return n !== void 0 && n >= "0" && n <= "9";
174
174
  };
@@ -180,25 +180,31 @@ function A(e, t) {
180
180
  type: "number",
181
181
  value: e.slice(r, t)
182
182
  },
183
+ start: r,
183
184
  end: t
184
185
  };
185
186
  }
186
- let i = t;
187
187
  for (; t < n && e[t] !== "," && e[t] !== ")";) t += 1;
188
- let a = E(e.slice(i, t));
188
+ let a = E(e.slice(r, t));
189
189
  return a === "" ? {
190
190
  ok: !1,
191
- error: "expression_syntax_error"
191
+ error: "expression_syntax_error",
192
+ kind: "empty_arg_slot",
193
+ at: {
194
+ start: r,
195
+ end: t
196
+ }
192
197
  } : {
193
198
  ok: !0,
194
199
  value: {
195
200
  type: "path",
196
201
  value: a
197
202
  },
203
+ start: r,
198
204
  end: t
199
205
  };
200
206
  }
201
- function j(e) {
207
+ function M(e) {
202
208
  let t = 0;
203
209
  for (; t < e.length && !T.includes(e[t]);) t += 1;
204
210
  if (t === 0) return null;
@@ -254,16 +260,41 @@ function j(e) {
254
260
  r += 1, n = D(e, n + 1);
255
261
  }
256
262
  }
257
- function M(e) {
263
+ function N(e) {
258
264
  let t = 0, n = e.length;
259
265
  for (; t < n && " \n\r\0\v".includes(e[t]);) t += 1;
260
266
  for (; n > t && " \n\r\0\v".includes(e[n - 1]);) --n;
261
267
  return e.slice(t, n);
262
268
  }
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
269
  function P(e) {
270
+ if (e === "") return {
271
+ kind: "empty_fragment",
272
+ at: {
273
+ start: 0,
274
+ end: 0
275
+ }
276
+ };
277
+ if (k(e)) {
278
+ let t = A(e);
279
+ return t.ok ? null : {
280
+ kind: t.kind,
281
+ at: t.at
282
+ };
283
+ }
284
+ return S(e).ok ? null : {
285
+ kind: "invalid_path",
286
+ at: {
287
+ start: 0,
288
+ end: e.length
289
+ }
290
+ };
291
+ }
292
+ function F(e) {
293
+ let t = 0;
294
+ for (; t < e.length && " \n\r\0\v".includes(e[t]);) t += 1;
295
+ return t;
296
+ }
297
+ function I(e) {
267
298
  let t = [], n = 0, r = e.indexOf("{{");
268
299
  for (; r !== -1;) {
269
300
  let i = e.indexOf("}}", r + 2);
@@ -280,7 +311,7 @@ function P(e) {
280
311
  start: r,
281
312
  end: e.length,
282
313
  text: i,
283
- expr: M(i.slice(2))
314
+ expr: N(i.slice(2))
284
315
  }), {
285
316
  template: e,
286
317
  parts: t
@@ -292,14 +323,27 @@ function P(e) {
292
323
  end: r,
293
324
  text: e.slice(n, r)
294
325
  });
295
- let a = e.slice(r + 2, i), o = M(a), s = N(o);
326
+ let a = e.slice(r + 2, i), o = N(a), s = null, c = P(o);
327
+ if (c) {
328
+ let e = r + 2 + F(a);
329
+ s = {
330
+ kind: c.kind,
331
+ start: r,
332
+ end: i + 2,
333
+ at: {
334
+ start: e + c.at.start,
335
+ end: e + c.at.end
336
+ }
337
+ };
338
+ }
296
339
  t.push({
297
340
  kind: "fragment",
298
341
  start: r,
299
342
  end: i + 2,
300
343
  raw: a,
301
344
  expr: o,
302
- error: s
345
+ error: s === null ? null : "expression_syntax_error",
346
+ diagnostic: s
303
347
  }), n = i + 2, r = e.indexOf("{{", n);
304
348
  }
305
349
  return n < e.length && t.push({
@@ -312,13 +356,13 @@ function P(e) {
312
356
  parts: t
313
357
  };
314
358
  }
315
- function F(e, t) {
359
+ function L(e, t) {
316
360
  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
361
  return null;
318
362
  }
319
363
  //#endregion
320
364
  //#region src/shared/PanelIcon.vue
321
- var I = /* @__PURE__ */ o({
365
+ var R = /* @__PURE__ */ o({
322
366
  inheritAttrs: !1,
323
367
  __name: "PanelIcon",
324
368
  props: {
@@ -332,23 +376,20 @@ var I = /* @__PURE__ */ o({
332
376
  "stroke-width": e.strokeWidth
333
377
  }, t.$attrs), null, 16, ["size", "stroke-width"]));
334
378
  }
335
- }), L = {
379
+ }), z = {
336
380
  role: "listbox",
337
381
  "aria-label": "表达式路径候选"
338
- }, R = [
382
+ }, B = [
339
383
  "aria-selected",
340
384
  "title",
341
385
  "onClick"
342
- ], z = { class: "cn-completion__segment font-mono text-cn-fg" }, B = {
386
+ ], V = { class: "cn-completion__segment font-mono text-cn-fg" }, H = {
343
387
  key: 0,
344
388
  class: "shrink-0 rounded-sm bg-cn-field px-1 py-0.5 text-[9px] leading-none text-cn-muted"
345
- }, V = {
389
+ }, U = {
346
390
  key: 1,
347
391
  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({
392
+ }, W = /* @__PURE__ */ o({
352
393
  __name: "ExpressionCompletionPopup",
353
394
  props: { state: {} },
354
395
  emits: ["select"],
@@ -367,7 +408,7 @@ var I = /* @__PURE__ */ o({
367
408
  }),
368
409
  onMousedown: c[0] ||= _(() => {}, ["prevent", "stop"]),
369
410
  onPointerdown: c[1] ||= _(() => {}, ["stop"])
370
- }, [a("div", L, [(d(!0), i(e, null, p(o.state.items, (e, t) => (d(), i("button", {
411
+ }, [a("div", z, [(d(!0), i(e, null, p(o.state.items, (e, t) => (d(), i("button", {
371
412
  key: `${t}:${e.segment}`,
372
413
  type: "button",
373
414
  role: "option",
@@ -376,15 +417,15 @@ var I = /* @__PURE__ */ o({
376
417
  title: e.path ?? e.segment,
377
418
  onClick: (e) => y("select", t)
378
419
  }, [
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)]));
420
+ a("span", V, h(e.segment), 1),
421
+ e.type ? (d(), i("span", H, h(e.type), 1)) : r("", !0),
422
+ e.description ?? e.title ? (d(), i("span", U, h(e.description ?? e.title), 1)) : r("", !0)
423
+ ], 10, B))), 128))])], 36)) : r("", !0)]));
383
424
  }
384
425
  });
385
426
  //#endregion
386
427
  //#region src/shared/completion.ts
387
- function W(e, t, n, r, i) {
428
+ function G(e, t, n, r, i) {
388
429
  let a = t.start + 2, o = t.kind === "open" ? t.end : t.end - 2, s = Math.min(n, o), c = 0;
389
430
  for (; s - c > a && " \n\r\0\v".includes(e[s - 1 - c]);) c += 1;
390
431
  let l = s - c, u = l - (i.replaceLen ?? r.length);
@@ -397,16 +438,16 @@ function W(e, t, n, r, i) {
397
438
  }
398
439
  //#endregion
399
440
  //#region src/shared/completionAnchor.ts
400
- function G(e, t) {
441
+ function K(e, t) {
401
442
  return parseFloat(e.getPropertyValue(t)) || 0;
402
443
  }
403
- function K(e, t, n) {
444
+ function q(e, t, n) {
404
445
  for (let r of n) {
405
446
  let n = e.getPropertyValue(r);
406
447
  n && t.setProperty(r, n);
407
448
  }
408
449
  }
409
- var q = [
450
+ var J = [
410
451
  "font-family",
411
452
  "font-size",
412
453
  "font-weight",
@@ -419,52 +460,67 @@ var q = [
419
460
  "text-indent",
420
461
  "tab-size"
421
462
  ];
422
- function J(e) {
423
- return G(e, "line-height") || G(e, "font-size") * 1.4;
424
- }
425
463
  function Y(e) {
464
+ return K(e, "line-height") || K(e, "font-size") * 1.4;
465
+ }
466
+ function X(e) {
426
467
  let t = document.createElement("div"), n = t.style;
427
468
  return n.position = "fixed", n.top = "0", n.left = "0", n.visibility = "hidden", e(t, n), document.body.appendChild(t), t;
428
469
  }
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, [
470
+ function Z(e, t) {
471
+ let n = e.selectionStart ?? e.value.length, r = e.getBoundingClientRect(), i = getComputedStyle(e), a = K(i, "padding-left"), o = K(i, "padding-top"), s = null, c = X((t, r) => {
472
+ r.whiteSpace = i.whiteSpace || "pre-wrap", r.boxSizing = "content-box", r.width = `${Math.max(0, e.clientWidth - a - K(i, "padding-right"))}px`, q(i, r, [
432
473
  "padding-left",
433
474
  "padding-right",
434
475
  "padding-top",
435
476
  "padding-bottom",
436
477
  "word-break",
437
478
  "overflow-wrap"
438
- ]), K(i, r, q), s = document.createElement("span"), s.textContent = "​", t.append(document.createTextNode(e.value.slice(0, n)), s);
479
+ ]), q(i, r, J), s = document.createElement("span"), s.textContent = "​", t.append(document.createTextNode(e.value.slice(0, n)), s);
439
480
  });
440
481
  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;
482
+ let n = r.left + K(i, "border-left-width") + a + s.offsetLeft * t - e.scrollLeft, c = r.top + K(i, "border-top-width") + o + s.offsetTop * t - e.scrollTop;
442
483
  return {
443
484
  left: n,
444
485
  top: c,
445
- bottom: c + J(i) * t
486
+ bottom: c + Y(i) * t
446
487
  };
447
488
  } finally {
448
489
  c.remove();
449
490
  }
450
491
  }
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);
492
+ function Q(e, t) {
493
+ let n = e.selectionStart ?? e.value.length, r = e.getBoundingClientRect(), i = getComputedStyle(e), a = X((t, r) => {
494
+ r.display = "inline-block", r.whiteSpace = "pre", q(i, r, J), t.textContent = e.value.slice(0, n);
454
495
  });
455
496
  try {
456
497
  let n = a.getBoundingClientRect().width || a.offsetWidth;
457
498
  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")
499
+ left: r.left + K(i, "border-left-width") + K(i, "padding-left") + n * t - e.scrollLeft,
500
+ top: r.top + K(i, "border-top-width"),
501
+ bottom: r.bottom - K(i, "border-bottom-width")
461
502
  };
462
503
  } finally {
463
504
  a.remove();
464
505
  }
465
506
  }
466
- function Q(e, t = 1) {
467
- return e instanceof HTMLTextAreaElement ? X(e, t) : Z(e, t);
507
+ function $(e, t = 1) {
508
+ return e instanceof HTMLTextAreaElement ? Z(e, t) : Q(e, t);
509
+ }
510
+ //#endregion
511
+ //#region src/shared/popupPosition.ts
512
+ var ee = 4, te = 4;
513
+ function ne(e) {
514
+ let { anchor: t, popupWidth: n, popupHeight: r, viewportWidth: i, viewportHeight: a } = e, o = e.gap ?? 4, s = e.margin ?? 4, c = t.bottom + o;
515
+ if (r > 0 && c + r > a - s) {
516
+ let e = t.top - o - r;
517
+ c = e >= s ? e : Math.max(s, Math.min(c, a - s - r));
518
+ }
519
+ let l = t.left;
520
+ return n > 0 && (l = Math.max(s, Math.min(l, i - s - n))), {
521
+ top: c,
522
+ left: l
523
+ };
468
524
  }
469
525
  //#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 };
526
+ export { G as a, L as c, M as d, k as f, y as g, b as h, $ as i, N as l, x as m, te as n, W as o, S as p, ne as r, R as s, ee as t, I as u };
@@ -7,6 +7,12 @@ type __VLS_Props = {
7
7
  value: unknown;
8
8
  /** 数据字段取值方式;undefined = 非 data 字段(无切换钮) */
9
9
  dataMode?: 'static' | 'expression';
10
+ /**
11
+ * 会话内容锁定(edit-overlay-toolbar 工单 02,ADR 0019 门面):编辑会话期
12
+ * data 字段的输入控件与模式段 disabled——编辑框草稿是内容唯一写入门,面板
13
+ * 只显示(文档现值 + 随会话活标志的模式段)。undefined/false = 照常可编辑。
14
+ */
15
+ locked?: boolean;
10
16
  /**
11
17
  * 补全候选源(面板按字段分发:data 门字段 = 表达式源,rowsPath 标记字段 =
12
18
  * 行相对源,工单 03);null = 未注入/无接线/降级(浮层恒闭)。
@@ -1,6 +1,6 @@
1
1
  import { Layer, LayerPath, LayerType, ResourceStatusMap } from '@hankchen/canvas-editor';
2
2
  /** 控件种类(与 controls.ts 的组件注册表一一对应) */
3
- export type FieldControl = 'number' | 'text' | 'textarea' | 'color' | 'select' | 'boolean' | 'pair' | 'anchor' | 'align' | 'padding' | 'border' | 'font' | 'imageSrc';
3
+ export type FieldControl = 'number' | 'text' | 'textarea' | 'color' | 'select' | 'boolean' | 'pair' | 'anchor' | 'align' | 'padding' | 'border' | 'font' | 'imageSrc' | 'resourceValue';
4
4
  /**
5
5
  * 自适应 prefix 钮描述(pair 子字段用):key 相对 pair 值对象上的布尔键;
6
6
  * 开启 → 本输入禁用。placeholder 是禁用态兜底占位(盒未解析时;正常路径面板
@@ -33,6 +33,12 @@ export interface FieldDef {
33
33
  readonly auto?: FieldAutoToggle;
34
34
  /** 数据字段:提交走 updateData(按 type 分派到 text/src/value),其余走 updateSpec */
35
35
  readonly data?: boolean;
36
+ /**
37
+ * 资源类内容字段(resource-expression-single-ref 工单 03,ADR 0020):表达式态
38
+ * 诊断走内核资源单值门(resourcePathDiagnostics——恰一闭合片段 + 裸点路径,
39
+ * 禁拼接/函数),不走片段级扫描诊断。图片地址/二维码值两类声明。
40
+ */
41
+ readonly resource?: true;
36
42
  /**
37
43
  * 补全标记门(rows-path-completion 工单 03,D6):'rowsPath' = 裸路径补全
38
44
  * (usePathCompletion,候选源 = 面板 rowsPathSource)——不走 data 门
@@ -1,12 +1,16 @@
1
1
  import { ResourceStatus } from '@hankchen/canvas-editor';
2
+ import { CompletionSource } from '../../shared/completion';
2
3
  import { FieldDef } from '../fieldSchema';
3
4
  type __VLS_Props = {
4
5
  field: FieldDef;
5
6
  modelValue: string | null;
6
- /** 取值方式(面板按 expression 标记派生):表达式态走表达式视觉与退化面 */
7
+ /** 取值方式(面板按 expression 标记派生):表达式态走选择器,静态态走上传形态 */
7
8
  dataMode?: 'static' | 'expression';
8
9
  /** 当前 src 的物化态(面板从 ui.resourceStatuses 切片解析下发):角标与画布失败标识同源 */
9
10
  resourceStatus?: ResourceStatus;
11
+ /** 候选源(面板同款注入缝,PropertyField 经 resource 门下发);null = 未绑声明只读 */
12
+ source?: CompletionSource | null;
13
+ disabled?: boolean;
10
14
  };
11
15
  declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
12
16
  input: (value: string) => any;
@@ -0,0 +1,19 @@
1
+ import { CompletionSource } from '../../shared/completion';
2
+ import { FieldDef } from '../fieldSchema';
3
+ type __VLS_Props = {
4
+ field: FieldDef;
5
+ modelValue: string | null;
6
+ /** 取值方式(面板按 expression 标记派生):表达式态走选择器,静态态走字面输入 */
7
+ dataMode?: 'static' | 'expression';
8
+ /** 候选源(面板同款注入缝);null = 未绑声明,选择器整体只读回显 */
9
+ source?: CompletionSource | null;
10
+ disabled?: boolean;
11
+ };
12
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
13
+ input: (value: string) => any;
14
+ change: (value: string) => any;
15
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
16
+ onInput?: ((value: string) => any) | undefined;
17
+ onChange?: ((value: string) => any) | undefined;
18
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
+ export default _default;
@@ -2,6 +2,7 @@ import { FieldDef } from '../fieldSchema';
2
2
  type __VLS_Props = {
3
3
  field: FieldDef;
4
4
  modelValue: string;
5
+ disabled?: boolean;
5
6
  };
6
7
  declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
7
8
  input: (value: string) => any;
@@ -1,6 +1,8 @@
1
1
  type __VLS_Props = {
2
- /** 当前取值方式(由图层 expression 标记派生:null → static) */
2
+ /** 当前取值方式(锁定期随会话活标志派生:null → static) */
3
3
  mode: 'static' | 'expression';
4
+ /** 会话内容锁定(工单 02):true = 不可点,显示照常随动 */
5
+ disabled?: boolean;
4
6
  };
5
7
  declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
6
8
  change: (value: "expression" | "static") => any;
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * 属性面板域出口:schema 驱动面板——字段描述注册表(fieldSchema)与领域类型、
3
3
  * 面板组件与动态控件分发器、面板订阅切片桥(usePropertyPanel)、动态控件
4
- * 注册表(controls)、Tailwind 类名常量(controlStyles,包内私有)、
5
- * 字体清单注入缝(fontPicker)与图片上传注入缝(imageUpload)。字段控件集见 ./fields。
4
+ * 注册表(controls)、Tailwind 类名常量(controlStyles,包内私有)、图片上传
5
+ * 注入缝(imageUpload)。字段控件集见 ./fields。字体清单注入缝(fontPicker)
6
+ * 已迁 shared 域(edit-overlay-toolbar 工单 04,画布工具条同源消费)——此处
7
+ * 具名转发保持既有出口面不变。
6
8
  */
7
9
  export { CANVAS_FIELD_SECTIONS, FIELD_SECTIONS_BY_TYPE, fieldSectionsForPath, fieldSectionsForType, layerRoleAt, readField, type FieldControl, type FieldDef, type FieldReadResult, type FieldSection, type LayerRole, } from './fieldSchema';
8
10
  export { controlRegistry } from './controls';
9
- export { FONT_PICKER_KEY, injectFontPicker, type FontPickerContext } from './fontPicker';
11
+ export { FONT_PICKER_KEY, injectFontPicker, type FontPickerContext } from '../shared/fontPicker';
10
12
  export { IMAGE_UPLOAD_KEY, injectImageUpload, type ImageUploadContext } from './imageUpload';
11
13
  export { usePropertyPanel, type PropertyPanelBinding } from './usePropertyPanel';
12
14
  export { default as PropertyField } from './PropertyField';
@@ -1,5 +1,5 @@
1
1
  import { ComputedRef } from 'vue';
2
- import { Canvas, EditorSession, Layer, LayerBox, LayerPath, ResourceStatusMap } from '@hankchen/canvas-editor';
2
+ import { Canvas, EditorSession, Layer, LayerBox, LayerPath, ResourceStatusMap, TextEditingSession } from '@hankchen/canvas-editor';
3
3
  import { FieldDef, FieldSection } from './fieldSchema';
4
4
  import { CompletionSource } from '../shared/completion';
5
5
  export type { FieldDef, FieldSection } from './fieldSchema';
@@ -37,12 +37,24 @@ export interface PropertyPanelBinding {
37
37
  * 宿主从渲染端物化状态机桥接注入,padding 行占位态动态提示的物化维度事实源。
38
38
  */
39
39
  readonly resourceStatuses: ComputedRef<ResourceStatusMap>;
40
+ /**
41
+ * 会话内容独占(canvas-web-edit-overlay-toolbar 工单 02,ADR 0019 门面):
42
+ * 编辑会话在场且选中层即编辑层 → 内容面锁定(data 字段与模式段 disabled,
43
+ * 显示随会话活标志/文档现值,退出后随文档通知追平)。会话保持但选择走开
44
+ * (显示别的层)不锁。
45
+ */
46
+ readonly contentLocked: ComputedRef<boolean>;
47
+ /** 锁定时的模式显示源:编辑会话对象(活标志 = expression),非锁定为 null */
48
+ readonly editingSession: ComputedRef<TextEditingSession | null>;
49
+ /** 数据字段当前取值方式(锁定期随会话活标志,否则随层标记态);非 data 字段恒 false */
50
+ isDataMarked(field: FieldDef): boolean;
40
51
  /** 面板唯一提交口:final = 收口提交(change/blur),否则按 mergeKey 合并累积 */
41
52
  commit(field: FieldDef, value: unknown, final: boolean): void;
42
53
  /**
43
- * 数据字段取值方式切换(静态值/表达式,工单 02):静态 → 表达式初值取当前
44
- * 字面原文(不自动包裹/猜变量);表达式 → 静态字面接管(值保持现镜像)。
45
- * 各为独立一步历史;仅 data 字段且有选中目标时生效。
54
+ * 数据字段取值方式切换(静态值/表达式,工单 02):语义经内核 toggleDataMode
55
+ * 收口——非会话期正常切换(一步历史),编辑会话期命中编辑层只翻会话活标志
56
+ * (零文档变更零历史步,防御性路由;面板锁定段常态下不可达,路由兜宿主旁路)。
57
+ * 仅 data 字段且有选中目标时生效。
46
58
  */
47
59
  toggleDataMode(field: FieldDef): void;
48
60
  /** 锚点折叠区开合(写 store ui 分支,不进历史) */