@jxsuite/studio 0.23.2 → 0.25.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 (106) hide show
  1. package/dist/studio.js +2311 -718
  2. package/dist/studio.js.map +121 -104
  3. package/package.json +8 -7
  4. package/src/browse/{browse-modal.js → browse-modal.ts} +9 -10
  5. package/src/browse/{browse.js → browse.ts} +109 -84
  6. package/src/canvas/{canvas-diff.js → canvas-diff.ts} +42 -35
  7. package/src/canvas/{canvas-helpers.js → canvas-helpers.ts} +25 -19
  8. package/src/canvas/{canvas-live-render.js → canvas-live-render.ts} +53 -63
  9. package/src/canvas/{canvas-render.js → canvas-render.ts} +110 -121
  10. package/src/canvas/{canvas-utils.js → canvas-utils.ts} +48 -44
  11. package/src/canvas/{nested-site-style.js → nested-site-style.ts} +3 -3
  12. package/src/editor/{component-inline-edit.js → component-inline-edit.ts} +45 -33
  13. package/src/editor/{content-inline-edit.js → content-inline-edit.ts} +27 -45
  14. package/src/editor/{context-menu.js → context-menu.ts} +38 -36
  15. package/src/editor/{convert-targets.js → convert-targets.ts} +15 -12
  16. package/src/editor/{convert-to-component.js → convert-to-component.ts} +25 -26
  17. package/src/editor/{convert-to-repeater.js → convert-to-repeater.ts} +60 -40
  18. package/src/editor/{inline-edit.js → inline-edit.ts} +91 -55
  19. package/src/editor/{inline-format.js → inline-format.ts} +46 -51
  20. package/src/editor/{insertion-helper.js → insertion-helper.ts} +47 -63
  21. package/src/editor/{shortcuts.js → shortcuts.ts} +45 -31
  22. package/src/editor/{slash-menu.js → slash-menu.ts} +34 -35
  23. package/src/files/{components.js → components.ts} +12 -15
  24. package/src/files/{file-ops.js → file-ops.ts} +36 -29
  25. package/src/files/{files.js → files.ts} +102 -84
  26. package/src/github/{github-auth.js → github-auth.ts} +3 -3
  27. package/src/github/{github-publish.js → github-publish.ts} +20 -18
  28. package/src/markdown/{md-allowlist.js → md-allowlist.ts} +5 -2
  29. package/src/markdown/{md-convert.js → md-convert.ts} +146 -169
  30. package/src/new-project/{new-project-modal.js → new-project-modal.ts} +16 -18
  31. package/src/panels/{activity-bar.js → activity-bar.ts} +26 -34
  32. package/src/panels/{ai-panel.js → ai-panel.ts} +30 -30
  33. package/src/panels/{block-action-bar.js → block-action-bar.ts} +64 -73
  34. package/src/panels/{canvas-dnd.js → canvas-dnd.ts} +44 -49
  35. package/src/panels/{data-explorer.js → data-explorer.ts} +21 -15
  36. package/src/panels/dnd.ts +417 -0
  37. package/src/panels/{editors.js → editors.ts} +43 -50
  38. package/src/panels/{elements-panel.js → elements-panel.ts} +30 -27
  39. package/src/panels/{events-panel.js → events-panel.ts} +33 -25
  40. package/src/panels/{git-panel.js → git-panel.ts} +97 -83
  41. package/src/panels/{head-panel.js → head-panel.ts} +117 -139
  42. package/src/panels/{imports-panel.js → imports-panel.ts} +69 -89
  43. package/src/panels/{layers-panel.js → layers-panel.ts} +61 -57
  44. package/src/panels/{left-panel.js → left-panel.ts} +56 -63
  45. package/src/panels/{overlays.js → overlays.ts} +28 -36
  46. package/src/panels/{panel-events.js → panel-events.ts} +53 -51
  47. package/src/panels/{preview-render.js → preview-render.ts} +20 -15
  48. package/src/panels/{properties-panel.js → properties-panel.ts} +212 -246
  49. package/src/panels/{pseudo-preview.js → pseudo-preview.ts} +9 -8
  50. package/src/panels/{quick-search.js → quick-search.ts} +16 -17
  51. package/src/panels/{right-panel.js → right-panel.ts} +41 -59
  52. package/src/panels/{shared.js → shared.ts} +8 -6
  53. package/src/panels/{signals-panel.js → signals-panel.ts} +322 -362
  54. package/src/panels/{statusbar.js → statusbar.ts} +14 -14
  55. package/src/panels/{style-inputs.js → style-inputs.ts} +66 -48
  56. package/src/panels/{style-panel.js → style-panel.ts} +235 -290
  57. package/src/panels/{style-utils.js → style-utils.ts} +32 -31
  58. package/src/panels/{stylebook-layers-panel.js → stylebook-layers-panel.ts} +22 -14
  59. package/src/panels/{stylebook-panel.js → stylebook-panel.ts} +127 -140
  60. package/src/panels/{tab-strip.js → tab-strip.ts} +12 -14
  61. package/src/panels/{toolbar.js → toolbar.ts} +68 -70
  62. package/src/panels/{welcome-screen.js → welcome-screen.ts} +14 -16
  63. package/src/{platform.js → platform.ts} +5 -3
  64. package/src/platforms/{devserver.js → devserver.ts} +53 -44
  65. package/src/{recent-projects.js → recent-projects.ts} +17 -12
  66. package/src/{resize-edges.js → resize-edges.ts} +18 -13
  67. package/src/services/{cem-export.js → cem-export.ts} +14 -7
  68. package/src/services/{code-services.js → code-services.ts} +29 -20
  69. package/src/services/{monaco-setup.js → monaco-setup.ts} +2 -3
  70. package/src/settings/{content-types-editor.js → content-types-editor.ts} +88 -67
  71. package/src/settings/{css-vars-editor.js → css-vars-editor.ts} +78 -51
  72. package/src/settings/{defs-editor.js → defs-editor.ts} +70 -56
  73. package/src/settings/{general-settings.js → general-settings.ts} +29 -28
  74. package/src/settings/{head-editor.js → head-editor.ts} +37 -35
  75. package/src/settings/{schema-field-ui.js → schema-field-ui.ts} +86 -76
  76. package/src/settings/{settings-modal.js → settings-modal.ts} +14 -16
  77. package/src/{site-context.js → site-context.ts} +35 -32
  78. package/src/{state.js → state.ts} +95 -78
  79. package/src/{store.js → store.ts} +60 -63
  80. package/src/{studio.js → studio.ts} +117 -119
  81. package/src/tabs/tab.ts +196 -0
  82. package/src/tabs/{transact.js → transact.ts} +107 -60
  83. package/src/types.ts +185 -0
  84. package/src/ui/{button-group.js → button-group.ts} +21 -21
  85. package/src/ui/{color-selector.js → color-selector.ts} +44 -37
  86. package/src/ui/{expression-editor.js → expression-editor.ts} +65 -40
  87. package/src/ui/{field-row.js → field-row.ts} +19 -2
  88. package/src/ui/{icons.js → icons.ts} +2 -2
  89. package/src/ui/{layers.js → layers.ts} +33 -24
  90. package/src/ui/{media-picker.js → media-picker.ts} +13 -9
  91. package/src/ui/{panel-resize.js → panel-resize.ts} +9 -4
  92. package/src/ui/{spectrum.js → spectrum.ts} +4 -4
  93. package/src/ui/{unit-selector.js → unit-selector.ts} +16 -19
  94. package/src/ui/{value-selector.js → value-selector.ts} +28 -28
  95. package/src/ui/{widgets.js → widgets.ts} +62 -15
  96. package/src/utils/{canvas-media.js → canvas-media.ts} +29 -14
  97. package/src/utils/edit-display.ts +298 -0
  98. package/src/utils/{google-fonts.js → google-fonts.ts} +14 -13
  99. package/src/utils/{inherited-style.js → inherited-style.ts} +15 -10
  100. package/src/utils/{studio-utils.js → studio-utils.ts} +35 -23
  101. package/src/{view.js → view.ts} +53 -55
  102. package/src/workspace/{workspace.js → workspace.ts} +44 -33
  103. package/src/panels/dnd.js +0 -426
  104. package/src/tabs/tab.js +0 -192
  105. package/src/utils/edit-display.js +0 -203
  106. /package/src/{reactivity.js → reactivity.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ /// <reference lib="dom" />
1
2
  /**
2
3
  * Signals panel — signal/def helpers, signals template, CEM editors, plugin schema forms.
3
4
  *
@@ -8,106 +9,116 @@ import { html, nothing } from "lit-html";
8
9
  import { classMap } from "lit-html/directives/class-map.js";
9
10
  import { ifDefined } from "lit-html/directives/if-defined.js";
10
11
  import { styleMap } from "lit-html/directives/style-map.js";
11
- import { projectState } from "../state.js";
12
- import { activeTab } from "../workspace/workspace.js";
12
+ import { projectState } from "../state";
13
+ import type { JsonValue } from "../types";
14
+ import { activeTab } from "../workspace/workspace";
13
15
  import {
14
16
  transactDoc,
15
17
  mutateUpdateDef,
16
18
  mutateAddDef,
17
19
  mutateRemoveDef,
18
20
  mutateRenameDef,
19
- } from "../tabs/transact.js";
20
- import { renderFieldRow } from "../ui/field-row.js";
21
- import { renderExpressionEditor, expressionHint } from "../ui/expression-editor.js";
22
- import { renderMediaPicker } from "../ui/media-picker.js";
23
- import { fetchPluginSchema, pluginSchemaCache } from "../services/code-services.js";
21
+ } from "../tabs/transact";
22
+ import { renderFieldRow } from "../ui/field-row";
23
+ import { renderExpressionEditor, expressionHint } from "../ui/expression-editor";
24
+ import { renderMediaPicker } from "../ui/media-picker";
25
+ import type { TabUi } from "../tabs/tab";
26
+ import type { JxMutableNode } from "@jxsuite/schema/types";
27
+ import { fetchPluginSchema, pluginSchemaCache } from "../services/code-services";
24
28
 
25
- /**
26
- * @typedef {{
27
- * document: JxMutableNode;
28
- * ui?: Record<string, unknown>;
29
- * mode?: string;
30
- * selection?: (string | number)[] | null;
31
- * canvas?: Record<string, unknown>;
32
- * _collapsedSignalCats?: Set<string>;
33
- * documentPath?: string | null;
34
- * }} SignalsPanelState
35
- *
36
- * @typedef {{ renderLeftPanel(): void; renderCanvas(): void; updateSession(patch: object): void }} SignalsPanelCtx
37
- *
38
- * @typedef {Record<string, unknown> & {
39
- * $prototype?: string;
40
- * $compute?: string;
41
- * $deps?: string[];
42
- * $handler?: unknown;
43
- * $src?: string;
44
- * $export?: string;
45
- * type?: string;
46
- * default?: unknown;
47
- * description?: string;
48
- * attribute?: string;
49
- * reflects?: boolean;
50
- * deprecated?: string | boolean;
51
- * format?: string;
52
- * url?: string;
53
- * method?: string;
54
- * timing?: string;
55
- * key?: string;
56
- * database?: string;
57
- * store?: string;
58
- * version?: number;
59
- * name?: string;
60
- * body?: string;
61
- * parameters?: Record<string, unknown>[];
62
- * emits?: Record<string, unknown>[];
63
- * fields?: unknown;
64
- * contentType?: string;
65
- * id?: unknown;
66
- * filter?: Record<string, unknown>;
67
- * sort?: { field?: string; order?: string };
68
- * limit?: number;
69
- * }} SignalDef
70
- *
71
- * @typedef {{ name: string; type?: { text?: string }; description?: string; optional?: boolean }} CemParameter
72
- *
73
- * @typedef {{ name: string; type?: { text?: string }; description?: string }} CemEvent
74
- *
75
- * @typedef {{
76
- * type?: string;
77
- * properties?: Record<string, SchemaProperty>;
78
- * required?: string[];
79
- * description?: string;
80
- * }} JsonSchema
81
- *
82
- * @typedef {{
83
- * type?: string;
84
- * enum?: string[];
85
- * default?: unknown;
86
- * format?: string;
87
- * minimum?: number;
88
- * maximum?: number;
89
- * description?: string;
90
- * examples?: string[];
91
- * name?: string;
92
- * items?: {
93
- * type?: string;
94
- * properties?: Record<string, Record<string, unknown>>;
95
- * required?: string[];
96
- * };
97
- * }} SchemaProperty
98
- */
29
+ interface SignalsPanelState {
30
+ document: JxMutableNode;
31
+ ui?: TabUi | Record<string, unknown>;
32
+ mode?: string;
33
+ selection?: (string | number)[] | null;
34
+ canvas?: Record<string, unknown>;
35
+ _collapsedSignalCats?: Set<string>;
36
+ documentPath?: string | null | undefined;
37
+ }
38
+
39
+ interface SignalsPanelCtx {
40
+ renderLeftPanel(): void;
41
+ renderCanvas(): void;
42
+ updateSession(patch: Record<string, unknown>): void;
43
+ }
44
+
45
+ interface CemParameter {
46
+ name: string;
47
+ type?: { text?: string };
48
+ description?: string;
49
+ optional?: boolean;
50
+ }
51
+
52
+ interface CemEvent {
53
+ name: string;
54
+ type?: { text?: string };
55
+ description?: string;
56
+ }
57
+
58
+ interface JsonSchema {
59
+ type?: string;
60
+ properties?: Record<string, SchemaProperty>;
61
+ required?: string[];
62
+ description?: string;
63
+ }
64
+
65
+ interface SchemaProperty {
66
+ type?: string;
67
+ enum?: string[];
68
+ default?: unknown;
69
+ format?: string;
70
+ minimum?: number;
71
+ maximum?: number;
72
+ description?: string;
73
+ examples?: string[];
74
+ name?: string;
75
+ items?: {
76
+ type?: string;
77
+ properties?: Record<string, Record<string, unknown>>;
78
+ required?: string[];
79
+ };
80
+ }
81
+
82
+ export interface SignalDef {
83
+ $prototype?: string;
84
+ $src?: string;
85
+ $export?: string;
86
+ $compute?: string;
87
+ $deps?: string[];
88
+ $expression?: Record<string, unknown>;
89
+ $handler?: string;
90
+ type?: string;
91
+ default?: unknown;
92
+ body?: string;
93
+ parameters?: string[];
94
+ timing?: string;
95
+ description?: string;
96
+ fields?: Record<string, unknown>;
97
+ url?: string;
98
+ method?: string;
99
+ key?: string;
100
+ database?: string;
101
+ store?: string;
102
+ version?: number;
103
+ name?: string;
104
+ attribute?: string;
105
+ reflects?: boolean;
106
+ deprecated?: string | boolean;
107
+ format?: string;
108
+ emits?: CemEvent[];
109
+ [key: string]: unknown;
110
+ }
99
111
 
100
112
  // ─── Module-local state ─────────────────────────────────────────────────────
101
113
 
102
114
  /** Expanded signal editor state (persists across renders). */
103
- /** @type {string | null} */
104
- let expandedSignal = null;
115
+ let expandedSignal: string | null = null;
105
116
 
106
117
  /** Track which functions have the advanced param editor open. */
107
118
  const advancedParamOpen = new Set();
108
119
 
109
120
  /** Default templates for creating new signal definitions. */
110
- const DEF_TEMPLATES = /** @type {Record<string, SignalDef>} */ ({
121
+ const DEF_TEMPLATES = {
111
122
  state: { type: "string", default: "" },
112
123
  computed: { $compute: "", $deps: [] },
113
124
  request: { $prototype: "Request", url: "", method: "GET", timing: "client" },
@@ -121,7 +132,7 @@ const DEF_TEMPLATES = /** @type {Record<string, SignalDef>} */ ({
121
132
  function: { $prototype: "Function", body: "", parameters: [] },
122
133
  expression: { $expression: { operator: "=", target: null } },
123
134
  external: { $prototype: "", $src: "" },
124
- });
135
+ } as Record<string, SignalDef>;
125
136
 
126
137
  /** Keys handled by the framework — skip when rendering schema fields. */
127
138
  const STUDIO_RESERVED_KEYS = new Set([
@@ -147,9 +158,9 @@ const STUDIO_RESERVED_KEYS = new Set([
147
158
  *
148
159
  * @param {SignalDef | unknown} def
149
160
  */
150
- export function defCategory(def) {
161
+ export function defCategory(def: SignalDef | unknown) {
151
162
  if (!def) return "state";
152
- const d = /** @type {SignalDef} */ (def);
163
+ const d = def as SignalDef;
153
164
  if (d.$expression) return "expression";
154
165
  if (d.$handler || d.$prototype === "Function") return "function";
155
166
  if (d.$compute) return "computed";
@@ -162,9 +173,9 @@ export function defCategory(def) {
162
173
  *
163
174
  * @param {SignalDef | unknown} def
164
175
  */
165
- export function defBadgeLabel(def) {
176
+ export function defBadgeLabel(def: SignalDef | unknown) {
166
177
  if (!def) return "S";
167
- const d = /** @type {SignalDef} */ (def);
178
+ const d = def as SignalDef;
168
179
  if (d.$expression) return "E";
169
180
  if (d.$handler || d.$prototype === "Function") return "F";
170
181
  if (d.$compute) return "C";
@@ -178,7 +189,7 @@ export function defBadgeLabel(def) {
178
189
  * @param {string} name
179
190
  * @param {SignalDef | null | undefined} def
180
191
  */
181
- export function defHint(name, def) {
192
+ export function defHint(name: string, def: SignalDef | null | undefined) {
182
193
  if (!def) return "";
183
194
  if (def.$expression) return expressionHint(def.$expression);
184
195
  if (def.$prototype === "Function") {
@@ -205,7 +216,7 @@ export function defHint(name, def) {
205
216
  *
206
217
  * @param {SignalsPanelState} S
207
218
  */
208
- export function isCustomElementDoc(S) {
219
+ export function isCustomElementDoc(S: SignalsPanelState) {
209
220
  return (S.document.tagName || "").includes("-");
210
221
  }
211
222
 
@@ -215,7 +226,10 @@ export function isCustomElementDoc(S) {
215
226
  * @param {JxMutableNode | null | undefined} node
216
227
  * @param {{ name: string; tag: string }[]} [parts]
217
228
  */
218
- export function collectCssParts(node, parts = []) {
229
+ export function collectCssParts(
230
+ node: JxMutableNode | null | undefined,
231
+ parts: { name: string; tag: string }[] = [],
232
+ ) {
219
233
  if (node?.attributes?.part)
220
234
  parts.push({ name: node.attributes.part, tag: node.tagName || "div" });
221
235
  if (Array.isArray(node?.children))
@@ -232,10 +246,12 @@ export function collectCssParts(node, parts = []) {
232
246
  * @param {unknown} value
233
247
  * @param {Record<string, SignalDef> | null | undefined} defs
234
248
  */
235
- export function resolveDefaultForCanvas(value, defs) {
236
- if (!value || typeof value !== "object" || !(/** @type {Record<string, unknown>} */ (value).$ref))
237
- return value;
238
- const ref = /** @type {string} */ (/** @type {Record<string, unknown>} */ (value).$ref);
249
+ export function resolveDefaultForCanvas(
250
+ value: unknown,
251
+ defs: Record<string, SignalDef> | null | undefined,
252
+ ) {
253
+ if (!value || typeof value !== "object" || !(value as Record<string, unknown>).$ref) return value;
254
+ const ref = (value as Record<string, unknown>).$ref as string;
239
255
  /** @type {string | undefined} */
240
256
  let defName;
241
257
  if (ref.startsWith("#/state/")) defName = ref.slice(8);
@@ -272,13 +288,7 @@ export function resolveDefaultForCanvas(value, defs) {
272
288
  // ─── Simple field row ────────────────────────────────────────────────────────
273
289
 
274
290
  /** Simple field row for signal editors — vertical stacked layout. */
275
- export function signalFieldRow(
276
- /** @type {string} */ label,
277
- /** @type {string} */ value,
278
- /** @type {(value: string) => void} */ onChange,
279
- ) {
280
- /** @type {ReturnType<typeof setTimeout> | undefined} */
281
- let debounce;
291
+ export function signalFieldRow(label: string, value: string, onChange: (value: string) => void) {
282
292
  return renderFieldRow({
283
293
  prop: label,
284
294
  label,
@@ -286,13 +296,10 @@ export function signalFieldRow(
286
296
  widget: html`
287
297
  <sp-textfield
288
298
  size="s"
289
- value=${value}
290
- @input=${(/** @type {Event} */ e) => {
291
- clearTimeout(debounce);
292
- debounce = setTimeout(
293
- () => onChange(/** @type {HTMLInputElement} */ (e.target).value),
294
- 400,
295
- );
299
+ .value=${value}
300
+ @change=${(e: Event) => {
301
+ const v = (e.target as HTMLInputElement).value;
302
+ if (v !== value) onChange(v);
296
303
  }}
297
304
  ></sp-textfield>
298
305
  `,
@@ -300,8 +307,8 @@ export function signalFieldRow(
300
307
  }
301
308
 
302
309
  /** Normalize a parameter entry to a CEM object. */
303
- export function normParam(/** @type {string | Record<string, unknown>} */ p) {
304
- return typeof p === "string" ? { name: p } : /** @type {CemParameter} */ (p);
310
+ export function normParam(p: string | Record<string, unknown>) {
311
+ return typeof p === "string" ? { name: p } : (p as unknown as CemParameter);
305
312
  }
306
313
 
307
314
  // ─── Left panel: Signals ─────────────────────────────────────────────────────
@@ -310,18 +317,18 @@ export function normParam(/** @type {string | Record<string, unknown>} */ p) {
310
317
  * @param {SignalsPanelState} S
311
318
  * @param {SignalsPanelCtx} ctx
312
319
  */
313
- export function renderSignalsTemplate(S, ctx) {
320
+ export function renderSignalsTemplate(S: SignalsPanelState, ctx: SignalsPanelCtx) {
314
321
  const defs = S.document.state || {};
315
322
  const entries = Object.entries(defs);
316
323
 
317
324
  // Group by category
318
- const groups = /** @type {Record<string, [string, SignalDef][]>} */ ({
325
+ const groups = {
319
326
  state: [],
320
327
  computed: [],
321
328
  data: [],
322
329
  expression: [],
323
330
  function: [],
324
- });
331
+ } as Record<string, [string, SignalDef][]>;
325
332
  for (const [name, def] of entries) {
326
333
  groups[defCategory(def)].push([name, def]);
327
334
  }
@@ -350,8 +357,7 @@ export function renderSignalsTemplate(S, ctx) {
350
357
  }}
351
358
  >
352
359
  ${items.map(([name, def]) => {
353
- /** @type {boolean} */
354
- const isExpanded = expandedSignal === name;
360
+ const isExpanded: boolean = expandedSignal === name;
355
361
  return html`
356
362
  <div
357
363
  class=${classMap({ "signal-row": true, expanded: isExpanded })}
@@ -367,7 +373,7 @@ export function renderSignalsTemplate(S, ctx) {
367
373
  quiet
368
374
  size="xs"
369
375
  class="signal-del"
370
- @click=${(/** @type {Event} */ e) => {
376
+ @click=${(e: Event) => {
371
377
  e.stopPropagation();
372
378
  transactDoc(activeTab.value, (t) => mutateRemoveDef(t, name));
373
379
  }}
@@ -395,8 +401,8 @@ export function renderSignalsTemplate(S, ctx) {
395
401
  size="s"
396
402
  label="+ Add…"
397
403
  placeholder="+ Add…"
398
- @change=${(/** @type {Event} */ e) => {
399
- const type = /** @type {HTMLInputElement} */ (e.target).value;
404
+ @change=${(e: Event) => {
405
+ const type = (e.target as HTMLInputElement).value;
400
406
  if (!type) return;
401
407
 
402
408
  // Handle import-based prototypes (e.g., "import:ContentCollection")
@@ -420,7 +426,7 @@ export function renderSignalsTemplate(S, ctx) {
420
426
  if (src) {
421
427
  fetchPluginSchema(
422
428
  { $prototype: protoName, $src: src },
423
- /** @type {{ documentPath?: string }} */ (S),
429
+ { ...(S.documentPath != null && { documentPath: S.documentPath }) },
424
430
  ).then(() => ctx.renderLeftPanel());
425
431
  } else {
426
432
  ctx.renderLeftPanel();
@@ -438,11 +444,7 @@ export function renderSignalsTemplate(S, ctx) {
438
444
  n = nameBase + i++;
439
445
  }
440
446
  transactDoc(activeTab.value, (t) =>
441
- mutateAddDef(
442
- t,
443
- n,
444
- /** @type {Record<string, JsonValue>} */ (structuredClone(template)),
445
- ),
447
+ mutateAddDef(t, n, structuredClone(template) as Record<string, JsonValue>),
446
448
  );
447
449
  expandedSignal = n;
448
450
  ctx.renderLeftPanel();
@@ -463,10 +465,7 @@ export function renderSignalsTemplate(S, ctx) {
463
465
  ${projectState?.projectConfig?.imports
464
466
  ? html`<sp-menu-divider></sp-menu-divider>${Object.keys(
465
467
  projectState.projectConfig.imports,
466
- ).map(
467
- (/** @type {string} */ k) =>
468
- html`<sp-menu-item value="import:${k}">${k}</sp-menu-item>`,
469
- )}`
468
+ ).map((k: string) => html`<sp-menu-item value="import:${k}">${k}</sp-menu-item>`)}`
470
469
  : nothing}
471
470
  <sp-menu-divider></sp-menu-divider>
472
471
  <sp-menu-item value="expression">Expression</sp-menu-item>
@@ -479,10 +478,10 @@ export function renderSignalsTemplate(S, ctx) {
479
478
 
480
479
  /** Render inline editor fields for a specific signal/def type. */
481
480
  function renderSignalEditorTemplate(
482
- /** @type {SignalsPanelState} */ S,
483
- /** @type {string} */ name,
484
- /** @type {SignalDef} */ def,
485
- /** @type {SignalsPanelCtx} */ ctx,
481
+ S: SignalsPanelState,
482
+ name: string,
483
+ def: SignalDef,
484
+ ctx: SignalsPanelCtx,
486
485
  ) {
487
486
  if (typeof def !== "object" || def === null) {
488
487
  def = { default: def };
@@ -491,10 +490,10 @@ function renderSignalEditorTemplate(
491
490
 
492
491
  // Helper for picker rows
493
492
  const pickerRow = (
494
- /** @type {string} */ label,
495
- /** @type {string[]} */ options,
496
- /** @type {string} */ currentVal,
497
- /** @type {(value: string) => void} */ onChange,
493
+ label: string,
494
+ options: string[],
495
+ currentVal: string,
496
+ onChange: (value: string) => void,
498
497
  ) => {
499
498
  return renderFieldRow({
500
499
  prop: label,
@@ -504,12 +503,9 @@ function renderSignalEditorTemplate(
504
503
  <sp-picker
505
504
  size="s"
506
505
  value=${currentVal}
507
- @change=${(/** @type {Event} */ e) =>
508
- onChange(/** @type {HTMLInputElement} */ (e.target).value)}
506
+ @change=${(e: Event) => onChange((e.target as HTMLInputElement).value)}
509
507
  >
510
- ${options.map(
511
- (/** @type {string} */ opt) => html`<sp-menu-item value=${opt}>${opt}</sp-menu-item>`,
512
- )}
508
+ ${options.map((opt: string) => html`<sp-menu-item value=${opt}>${opt}</sp-menu-item>`)}
513
509
  </sp-picker>
514
510
  `,
515
511
  });
@@ -517,13 +513,12 @@ function renderSignalEditorTemplate(
517
513
 
518
514
  // Helper for textarea rows
519
515
  const textareaRow = (
520
- /** @type {string} */ label,
521
- /** @type {string} */ value,
522
- /** @type {(value: string) => void} */ onChange,
523
- /** @type {{ minHeight?: string; mono?: boolean }} */ opts = {},
516
+ label: string,
517
+ value: string,
518
+ onChange: (value: string) => void,
519
+ opts: { minHeight?: string; mono?: boolean } = {},
524
520
  ) => {
525
- /** @type {ReturnType<typeof setTimeout> | undefined} */
526
- let debounce;
521
+ let debounce: ReturnType<typeof setTimeout> | undefined;
527
522
  return renderFieldRow({
528
523
  prop: label,
529
524
  label,
@@ -539,12 +534,9 @@ function renderSignalEditorTemplate(
539
534
  }),
540
535
  })}
541
536
  .value=${value}
542
- @input=${(/** @type {Event} */ e) => {
537
+ @input=${(e: Event) => {
543
538
  clearTimeout(debounce);
544
- debounce = setTimeout(
545
- () => onChange(/** @type {HTMLInputElement} */ (e.target).value),
546
- 500,
547
- );
539
+ debounce = setTimeout(() => onChange((e.target as HTMLInputElement).value), 500);
548
540
  }}
549
541
  ></textarea>
550
542
  `,
@@ -552,15 +544,14 @@ function renderSignalEditorTemplate(
552
544
  };
553
545
 
554
546
  // Name field (common to all)
555
- const nameField = signalFieldRow("Name", name, (/** @type {string} */ v) => {
547
+ const nameField = signalFieldRow("Name", name, (v: string) => {
556
548
  if (v && v !== name && !(S.document.state && S.document.state[v])) {
557
549
  expandedSignal = v;
558
550
  transactDoc(activeTab.value, (t) => mutateRenameDef(t, name, v));
559
551
  }
560
552
  });
561
553
 
562
- /** @type {import("lit-html").TemplateResult | typeof nothing} */
563
- let fields = nothing;
554
+ let fields: import("lit-html").TemplateResult | typeof nothing = nothing;
564
555
 
565
556
  if (cat === "state") {
566
557
  const defaultVal =
@@ -572,7 +563,7 @@ function renderSignalEditorTemplate(
572
563
 
573
564
  const cemFields = isCustomElementDoc(S)
574
565
  ? html`
575
- ${signalFieldRow("Attribute", def.attribute || "", (/** @type {string} */ v) =>
566
+ ${signalFieldRow("Attribute", def.attribute || "", (v: string) =>
576
567
  transactDoc(activeTab.value, (t) =>
577
568
  mutateUpdateDef(t, name, { attribute: v || undefined }),
578
569
  ),
@@ -585,10 +576,10 @@ function renderSignalEditorTemplate(
585
576
  <sp-checkbox
586
577
  class="field-check"
587
578
  ?checked=${!!def.reflects}
588
- @change=${(/** @type {Event} */ e) =>
579
+ @change=${(e: Event) =>
589
580
  transactDoc(activeTab.value, (t) =>
590
581
  mutateUpdateDef(t, name, {
591
- reflects: /** @type {HTMLInputElement} */ (e.target).checked || undefined,
582
+ reflects: (e.target as HTMLInputElement).checked || undefined,
592
583
  }),
593
584
  )}
594
585
  ></sp-checkbox>
@@ -597,7 +588,7 @@ function renderSignalEditorTemplate(
597
588
  ${signalFieldRow(
598
589
  "Deprecated",
599
590
  typeof def.deprecated === "string" ? def.deprecated : "",
600
- (/** @type {string} */ v) =>
591
+ (v: string) =>
601
592
  transactDoc(activeTab.value, (t) =>
602
593
  mutateUpdateDef(t, name, { deprecated: v || undefined }),
603
594
  ),
@@ -610,18 +601,13 @@ function renderSignalEditorTemplate(
610
601
  "Type",
611
602
  ["string", "integer", "number", "boolean", "array", "object"],
612
603
  def.type || "string",
613
- (/** @type {string} */ v) =>
614
- transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { type: v })),
604
+ (v: string) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { type: v })),
615
605
  )}
616
606
  ${def.type === "string" || !def.type
617
- ? pickerRow(
618
- "Format",
619
- ["", "image", "date", "color"],
620
- def.format || "",
621
- (/** @type {string} */ v) =>
622
- transactDoc(activeTab.value, (t) =>
623
- mutateUpdateDef(t, name, { format: v || undefined }),
624
- ),
607
+ ? pickerRow("Format", ["", "image", "date", "color"], def.format || "", (v: string) =>
608
+ transactDoc(activeTab.value, (t) =>
609
+ mutateUpdateDef(t, name, { format: v || undefined }),
610
+ ),
625
611
  )
626
612
  : nothing}
627
613
  ${def.format === "image"
@@ -629,15 +615,14 @@ function renderSignalEditorTemplate(
629
615
  prop: "Default",
630
616
  label: "Default",
631
617
  hasValue: false,
632
- widget: renderMediaPicker("default", defaultVal, (/** @type {string} */ v) => {
618
+ widget: renderMediaPicker("default", defaultVal, (v: string) => {
633
619
  transactDoc(activeTab.value, (t) =>
634
620
  mutateUpdateDef(t, name, { default: v || undefined }),
635
621
  );
636
622
  }),
637
623
  })
638
- : signalFieldRow("Default", defaultVal, (/** @type {string} */ v) => {
639
- /** @type {unknown} */
640
- let parsed = v;
624
+ : signalFieldRow("Default", defaultVal, (v: string) => {
625
+ let parsed: unknown = v;
641
626
  if (def.type === "integer") parsed = parseInt(v, 10) || 0;
642
627
  else if (def.type === "number") parsed = parseFloat(v) || 0;
643
628
  else if (def.type === "boolean") parsed = v === "true";
@@ -649,10 +634,10 @@ function renderSignalEditorTemplate(
649
634
  }
650
635
  }
651
636
  transactDoc(activeTab.value, (t) =>
652
- mutateUpdateDef(t, name, { default: /** @type {JsonValue} */ (parsed) }),
637
+ mutateUpdateDef(t, name, { default: parsed as JsonValue }),
653
638
  );
654
639
  })}
655
- ${signalFieldRow("Description", def.description || "", (/** @type {string} */ v) =>
640
+ ${signalFieldRow("Description", def.description || "", (v: string) =>
656
641
  transactDoc(activeTab.value, (t) =>
657
642
  mutateUpdateDef(t, name, { description: v || undefined }),
658
643
  ),
@@ -660,8 +645,7 @@ function renderSignalEditorTemplate(
660
645
  ${cemFields}
661
646
  `;
662
647
  } else if (cat === "computed") {
663
- /** @type {ReturnType<typeof setTimeout> | undefined} */
664
- let debounce;
648
+ let debounce: ReturnType<typeof setTimeout> | undefined;
665
649
  fields = html`
666
650
  ${renderFieldRow({
667
651
  prop: "expression",
@@ -672,10 +656,10 @@ function renderSignalEditorTemplate(
672
656
  class="field-input"
673
657
  style="min-height:40px"
674
658
  .value=${def.$compute || ""}
675
- @input=${(/** @type {Event} */ e) => {
659
+ @input=${(e: Event) => {
676
660
  clearTimeout(debounce);
677
661
  debounce = setTimeout(() => {
678
- const expr = /** @type {HTMLInputElement} */ (e.target).value;
662
+ const expr = (e.target as HTMLInputElement).value;
679
663
  const depMatches = expr.match(/\$[a-zA-Z_]\w*/g) || [];
680
664
  const deps = [...new Set(depMatches)].map((d) => `#/state/${d}`);
681
665
  transactDoc(activeTab.value, (t) =>
@@ -693,9 +677,7 @@ function renderSignalEditorTemplate(
693
677
  hasValue: false,
694
678
  widget: html`
695
679
  <span class="signal-hint" style="flex:1;max-width:none"
696
- >${def.$deps
697
- .map((/** @type {string} */ d) => d.replace("#/state/", ""))
698
- .join(", ")}</span
680
+ >${def.$deps.map((d: string) => d.replace("#/state/", "")).join(", ")}</span
699
681
  >
700
682
  `,
701
683
  })
@@ -710,7 +692,7 @@ function renderSignalEditorTemplate(
710
692
  fields = html`
711
693
  ${renderExpressionEditor(
712
694
  exprNode,
713
- (/** @type {any} */ newNode) =>
695
+ (newNode: any) =>
714
696
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $expression: newNode })),
715
697
  { stateDefs: Object.keys(S.document.state || {}), allowEventRef: false },
716
698
  )}
@@ -722,33 +704,38 @@ function renderSignalEditorTemplate(
722
704
 
723
705
  /** Data source fields for signal editor */
724
706
  function renderDataSourceFields(
725
- /** @type {SignalsPanelState} */ S,
726
- /** @type {string} */ name,
727
- /** @type {SignalDef} */ def,
728
- /** @type {Function} */ textareaRow,
729
- /** @type {Function} */ pickerRow,
730
- /** @type {SignalsPanelCtx} */ ctx,
707
+ S: SignalsPanelState,
708
+ name: string,
709
+ def: SignalDef,
710
+ textareaRow: (
711
+ label: string,
712
+ value: string,
713
+ onChange: (value: string) => void,
714
+ opts?: { minHeight?: string; mono?: boolean },
715
+ ) => import("lit-html").TemplateResult,
716
+ pickerRow: (
717
+ label: string,
718
+ options: string[],
719
+ currentVal: string,
720
+ onChange: (value: string) => void,
721
+ ) => import("lit-html").TemplateResult,
722
+ ctx: SignalsPanelCtx,
731
723
  ) {
732
724
  const proto = def.$prototype;
733
725
 
734
726
  if (proto === "Request") {
735
727
  return html`
736
- ${signalFieldRow("URL", def.url || "", (/** @type {string} */ v) =>
728
+ ${signalFieldRow("URL", def.url || "", (v: string) =>
737
729
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { url: v })),
738
730
  )}
739
731
  ${pickerRow(
740
732
  "Method",
741
733
  ["GET", "POST", "PUT", "DELETE", "PATCH"],
742
734
  def.method || "GET",
743
- (/** @type {string} */ v) =>
744
- transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { method: v })),
735
+ (v: string) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { method: v })),
745
736
  )}
746
- ${pickerRow(
747
- "Timing",
748
- ["client", "server"],
749
- def.timing || "client",
750
- (/** @type {string} */ v) =>
751
- transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { timing: v })),
737
+ ${pickerRow("Timing", ["client", "server"], def.timing || "client", (v: string) =>
738
+ transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { timing: v })),
752
739
  )}
753
740
  `;
754
741
  }
@@ -760,10 +747,10 @@ function renderDataSourceFields(
760
747
  : String(def.default)
761
748
  : "";
762
749
  return html`
763
- ${signalFieldRow("Key", def.key || "", (/** @type {string} */ v) =>
750
+ ${signalFieldRow("Key", def.key || "", (v: string) =>
764
751
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { key: v })),
765
752
  )}
766
- ${textareaRow("Default", defaultStr, (/** @type {string} */ v) => {
753
+ ${textareaRow("Default", defaultStr, (v: string) => {
767
754
  try {
768
755
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: JSON.parse(v) }));
769
756
  } catch {
@@ -774,13 +761,13 @@ function renderDataSourceFields(
774
761
  }
775
762
  if (proto === "IndexedDB") {
776
763
  return html`
777
- ${signalFieldRow("Database", def.database || "", (/** @type {string} */ v) =>
764
+ ${signalFieldRow("Database", def.database || "", (v: string) =>
778
765
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { database: v })),
779
766
  )}
780
- ${signalFieldRow("Store", def.store || "", (/** @type {string} */ v) =>
767
+ ${signalFieldRow("Store", def.store || "", (v: string) =>
781
768
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { store: v })),
782
769
  )}
783
- ${signalFieldRow("Version", String(def.version || 1), (/** @type {string} */ v) =>
770
+ ${signalFieldRow("Version", String(def.version || 1), (v: string) =>
784
771
  transactDoc(activeTab.value, (t) =>
785
772
  mutateUpdateDef(t, name, { version: parseInt(v, 10) || 1 }),
786
773
  ),
@@ -789,10 +776,10 @@ function renderDataSourceFields(
789
776
  }
790
777
  if (proto === "Cookie") {
791
778
  return html`
792
- ${signalFieldRow("Cookie", def.name || "", (/** @type {string} */ v) =>
779
+ ${signalFieldRow("Cookie", def.name || "", (v: string) =>
793
780
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { name: v })),
794
781
  )}
795
- ${signalFieldRow("Default", String(def.default || ""), (/** @type {string} */ v) =>
782
+ ${signalFieldRow("Default", String(def.default || ""), (v: string) =>
796
783
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: v })),
797
784
  )}
798
785
  `;
@@ -806,7 +793,7 @@ function renderDataSourceFields(
806
793
  : proto === "FormData"
807
794
  ? JSON.stringify(def.fields || {}, null, 2)
808
795
  : "";
809
- return textareaRow(fieldLabel, defaultStr, (/** @type {string} */ v) => {
796
+ return textareaRow(fieldLabel, defaultStr, (v: string) => {
810
797
  try {
811
798
  transactDoc(activeTab.value, (t) =>
812
799
  mutateUpdateDef(t, name, { [fieldName]: JSON.parse(v) }),
@@ -820,27 +807,27 @@ function renderDataSourceFields(
820
807
 
821
808
  /** Function fields for signal editor */
822
809
  function renderFunctionFields(
823
- /** @type {SignalsPanelState} */ S,
824
- /** @type {string} */ name,
825
- /** @type {SignalDef} */ def,
826
- /** @type {Function} */ textareaRow,
827
- /** @type {SignalsPanelCtx} */ ctx,
810
+ S: SignalsPanelState,
811
+ name: string,
812
+ def: SignalDef,
813
+ textareaRow: (
814
+ label: string,
815
+ value: string,
816
+ onChange: (value: string) => void,
817
+ opts?: { minHeight?: string; mono?: boolean },
818
+ ) => import("lit-html").TemplateResult,
819
+ ctx: SignalsPanelCtx,
828
820
  ) {
829
- const descriptionField = signalFieldRow(
830
- "Description",
831
- def.description || "",
832
- (/** @type {string} */ v) =>
833
- transactDoc(activeTab.value, (t) =>
834
- mutateUpdateDef(t, name, { description: v || undefined }),
835
- ),
821
+ const descriptionField = signalFieldRow("Description", def.description || "", (v: string) =>
822
+ transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { description: v || undefined })),
836
823
  );
837
824
 
838
825
  const bodyField = def.$src
839
826
  ? html`
840
- ${signalFieldRow("Source", def.$src || "", (/** @type {string} */ v) =>
827
+ ${signalFieldRow("Source", def.$src || "", (v: string) =>
841
828
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $src: v || undefined })),
842
829
  )}
843
- ${signalFieldRow("Export", def.$export || "", (/** @type {string} */ v) =>
830
+ ${signalFieldRow("Export", def.$export || "", (v: string) =>
844
831
  transactDoc(activeTab.value, (t) =>
845
832
  mutateUpdateDef(t, name, { $export: v || undefined }),
846
833
  ),
@@ -865,8 +852,8 @@ function renderFunctionFields(
865
852
  class="field-input"
866
853
  style="min-height:60px;font-family:monospace;font-size:11px"
867
854
  .value=${def.body || ""}
868
- @input=${(/** @type {Event} */ e) => {
869
- const v = /** @type {HTMLInputElement} */ (e.target).value;
855
+ @input=${(e: Event) => {
856
+ const v = (e.target as HTMLInputElement).value;
870
857
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { body: v }));
871
858
  }}
872
859
  ></textarea>
@@ -882,10 +869,10 @@ function renderFunctionFields(
882
869
 
883
870
  /** Render CEM parameter editor with basic/advanced toggle. */
884
871
  function renderParameterEditorTemplate(
885
- /** @type {SignalsPanelState} */ S,
886
- /** @type {string} */ name,
887
- /** @type {SignalDef} */ def,
888
- /** @type {SignalsPanelCtx} */ ctx,
872
+ S: SignalsPanelState,
873
+ name: string,
874
+ def: SignalDef,
875
+ ctx: SignalsPanelCtx,
889
876
  ) {
890
877
  const params = (def.parameters || []).map(normParam);
891
878
  const isAdvanced = advancedParamOpen.has(name);
@@ -899,7 +886,7 @@ function renderParameterEditorTemplate(
899
886
  widget: html`
900
887
  <div style="display:flex;flex-wrap:wrap;gap:4px;align-items:center">
901
888
  ${params.map(
902
- (/** @type {CemParameter} */ p, /** @type {number} */ i) => html`
889
+ (p: CemParameter, i: number) => html`
903
890
  <span
904
891
  style="display:inline-flex;align-items:center;gap:2px;padding:1px 6px;border-radius:3px;background:var(--bg-hover);font-size:11px;font-family:monospace"
905
892
  >
@@ -909,12 +896,8 @@ function renderParameterEditorTemplate(
909
896
  @click=${() => {
910
897
  transactDoc(activeTab.value, (t) =>
911
898
  mutateUpdateDef(t, name, {
912
- parameters: params.filter(
913
- (/** @type {unknown} */ _, /** @type {number} */ j) => j !== i,
914
- ).length
915
- ? params.filter(
916
- (/** @type {unknown} */ _, /** @type {number} */ j) => j !== i,
917
- )
899
+ parameters: params.filter((_: unknown, j: number) => j !== i).length
900
+ ? params.filter((_: unknown, j: number) => j !== i)
918
901
  : undefined,
919
902
  }),
920
903
  );
@@ -928,14 +911,11 @@ function renderParameterEditorTemplate(
928
911
  class="field-input"
929
912
  style="width:60px;flex:0 0 auto;font-size:11px"
930
913
  placeholder="+"
931
- @keydown=${(/** @type {KeyboardEvent} */ e) => {
932
- if (e.key === "Enter" && /** @type {HTMLInputElement} */ (e.target).value.trim()) {
914
+ @keydown=${(e: KeyboardEvent) => {
915
+ if (e.key === "Enter" && (e.target as HTMLInputElement).value.trim()) {
933
916
  transactDoc(activeTab.value, (t) =>
934
917
  mutateUpdateDef(t, name, {
935
- parameters: [
936
- ...params,
937
- { name: /** @type {HTMLInputElement} */ (e.target).value.trim() },
938
- ],
918
+ parameters: [...params, { name: (e.target as HTMLInputElement).value.trim() }],
939
919
  }),
940
920
  );
941
921
  }
@@ -962,16 +942,16 @@ function renderParameterEditorTemplate(
962
942
  widget: html`
963
943
  <div style="display:flex;flex-direction:column;gap:4px">
964
944
  ${params.map(
965
- (/** @type {CemParameter} */ p, /** @type {number} */ i) => html`
945
+ (p: CemParameter, i: number) => html`
966
946
  <div style="display:flex;gap:4px;align-items:center">
967
947
  <input
968
948
  class="field-input"
969
949
  .value=${p.name || ""}
970
950
  placeholder="name"
971
951
  style="flex:1"
972
- @change=${(/** @type {Event} */ e) => {
952
+ @change=${(e: Event) => {
973
953
  const next = [...params];
974
- next[i] = { ...next[i], name: /** @type {HTMLInputElement} */ (e.target).value };
954
+ next[i] = { ...next[i], name: (e.target as HTMLInputElement).value };
975
955
  transactDoc(activeTab.value, (t) =>
976
956
  mutateUpdateDef(t, name, { parameters: next }),
977
957
  );
@@ -982,14 +962,11 @@ function renderParameterEditorTemplate(
982
962
  .value=${p.type?.text || ""}
983
963
  placeholder="type"
984
964
  style="flex:1"
985
- @change=${(/** @type {Event} */ e) => {
965
+ @change=${(e: Event) => {
986
966
  const next = [...params];
987
- next[i] = {
988
- ...next[i],
989
- type: /** @type {HTMLInputElement} */ (e.target).value
990
- ? { text: /** @type {HTMLInputElement} */ (e.target).value }
991
- : undefined,
992
- };
967
+ const val = (e.target as HTMLInputElement).value;
968
+ const { type: _t, ...rest } = next[i];
969
+ next[i] = val ? { ...rest, type: { text: val } } : rest;
993
970
  transactDoc(activeTab.value, (t) =>
994
971
  mutateUpdateDef(t, name, { parameters: next }),
995
972
  );
@@ -1000,12 +977,11 @@ function renderParameterEditorTemplate(
1000
977
  .value=${p.description || ""}
1001
978
  placeholder="desc"
1002
979
  style="flex:2"
1003
- @change=${(/** @type {Event} */ e) => {
980
+ @change=${(e: Event) => {
1004
981
  const next = [...params];
1005
- next[i] = {
1006
- ...next[i],
1007
- description: /** @type {HTMLInputElement} */ (e.target).value || undefined,
1008
- };
982
+ const val = (e.target as HTMLInputElement).value;
983
+ const { description: _d, ...rest } = next[i];
984
+ next[i] = val ? { ...rest, description: val } : rest;
1009
985
  transactDoc(activeTab.value, (t) =>
1010
986
  mutateUpdateDef(t, name, { parameters: next }),
1011
987
  );
@@ -1015,12 +991,11 @@ function renderParameterEditorTemplate(
1015
991
  type="checkbox"
1016
992
  title="optional"
1017
993
  .checked=${!!p.optional}
1018
- @change=${(/** @type {Event} */ e) => {
994
+ @change=${(e: Event) => {
1019
995
  const next = [...params];
1020
- next[i] = {
1021
- ...next[i],
1022
- optional: /** @type {HTMLInputElement} */ (e.target).checked || undefined,
1023
- };
996
+ const checked = (e.target as HTMLInputElement).checked;
997
+ const { optional: _o, ...rest } = next[i];
998
+ next[i] = checked ? { ...rest, optional: true } : rest;
1024
999
  transactDoc(activeTab.value, (t) =>
1025
1000
  mutateUpdateDef(t, name, { parameters: next }),
1026
1001
  );
@@ -1029,9 +1004,7 @@ function renderParameterEditorTemplate(
1029
1004
  <span
1030
1005
  style="cursor:pointer;opacity:0.5"
1031
1006
  @click=${() => {
1032
- const next = params.filter(
1033
- (/** @type {unknown} */ _, /** @type {number} */ j) => j !== i,
1034
- );
1007
+ const next = params.filter((_: unknown, j: number) => j !== i);
1035
1008
  transactDoc(activeTab.value, (t) =>
1036
1009
  mutateUpdateDef(t, name, { parameters: next.length ? next : undefined }),
1037
1010
  );
@@ -1064,12 +1037,8 @@ function renderParameterEditorTemplate(
1064
1037
  }
1065
1038
 
1066
1039
  /** Render CEM emits editor for function state entries. */
1067
- function renderEmitsEditorTemplate(
1068
- /** @type {SignalsPanelState} */ S,
1069
- /** @type {string} */ name,
1070
- /** @type {SignalDef} */ def,
1071
- ) {
1072
- const emits = /** @type {CemEvent[]} */ (def.emits || []);
1040
+ function renderEmitsEditorTemplate(S: SignalsPanelState, name: string, def: SignalDef) {
1041
+ const emits = def.emits || ([] as CemEvent[]);
1073
1042
  if (emits.length === 0 && !isCustomElementDoc(S)) return nothing;
1074
1043
 
1075
1044
  return html`
@@ -1079,16 +1048,16 @@ function renderEmitsEditorTemplate(
1079
1048
  Emits
1080
1049
  </div>
1081
1050
  ${emits.map(
1082
- (/** @type {CemEvent} */ ev, /** @type {number} */ i) => html`
1051
+ (ev: CemEvent, i: number) => html`
1083
1052
  <div style="display:flex;gap:4px;align-items:center;margin-bottom:4px">
1084
1053
  <input
1085
1054
  class="field-input"
1086
1055
  .value=${ev.name || ""}
1087
1056
  placeholder="event name"
1088
1057
  style="flex:1"
1089
- @change=${(/** @type {Event} */ e) => {
1058
+ @change=${(e: Event) => {
1090
1059
  const next = [...emits];
1091
- next[i] = { ...next[i], name: /** @type {HTMLInputElement} */ (e.target).value };
1060
+ next[i] = { ...next[i], name: (e.target as HTMLInputElement).value };
1092
1061
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
1093
1062
  }}
1094
1063
  />
@@ -1097,14 +1066,11 @@ function renderEmitsEditorTemplate(
1097
1066
  .value=${ev.type?.text || ""}
1098
1067
  placeholder="type"
1099
1068
  style="flex:1"
1100
- @change=${(/** @type {Event} */ e) => {
1069
+ @change=${(e: Event) => {
1101
1070
  const next = [...emits];
1102
- next[i] = {
1103
- ...next[i],
1104
- type: /** @type {HTMLInputElement} */ (e.target).value
1105
- ? { text: /** @type {HTMLInputElement} */ (e.target).value }
1106
- : undefined,
1107
- };
1071
+ const val = (e.target as HTMLInputElement).value;
1072
+ const { type: _t, ...rest } = next[i];
1073
+ next[i] = val ? { ...rest, type: { text: val } } : rest;
1108
1074
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
1109
1075
  }}
1110
1076
  />
@@ -1113,12 +1079,11 @@ function renderEmitsEditorTemplate(
1113
1079
  .value=${ev.description || ""}
1114
1080
  placeholder="description"
1115
1081
  style="flex:2"
1116
- @change=${(/** @type {Event} */ e) => {
1082
+ @change=${(e: Event) => {
1117
1083
  const next = [...emits];
1118
- next[i] = {
1119
- ...next[i],
1120
- description: /** @type {HTMLInputElement} */ (e.target).value || undefined,
1121
- };
1084
+ const val = (e.target as HTMLInputElement).value;
1085
+ const { description: _d, ...rest } = next[i];
1086
+ next[i] = val ? { ...rest, description: val } : rest;
1122
1087
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
1123
1088
  }}
1124
1089
  />
@@ -1127,10 +1092,8 @@ function renderEmitsEditorTemplate(
1127
1092
  @click=${() => {
1128
1093
  transactDoc(activeTab.value, (t) =>
1129
1094
  mutateUpdateDef(t, name, {
1130
- emits: emits.filter(
1131
- (/** @type {unknown} */ _, /** @type {number} */ j) => j !== i,
1132
- ).length
1133
- ? emits.filter((/** @type {unknown} */ _, /** @type {number} */ j) => j !== i)
1095
+ emits: emits.filter((_: unknown, j: number) => j !== i).length
1096
+ ? emits.filter((_: unknown, j: number) => j !== i)
1134
1097
  : undefined,
1135
1098
  }),
1136
1099
  );
@@ -1164,10 +1127,10 @@ function renderEmitsEditorTemplate(
1164
1127
  * @param {Record<string, unknown>} [parentDef] - Parent def for resolving dependent refs
1165
1128
  * @returns {string[] | undefined}
1166
1129
  */
1167
- function resolveSchemaEnum(enumDef, parentDef) {
1130
+ function resolveSchemaEnum(enumDef: unknown, parentDef?: Record<string, unknown>) {
1168
1131
  if (Array.isArray(enumDef)) return enumDef;
1169
1132
  if (enumDef && typeof enumDef === "object") {
1170
- const ref = /** @type {Record<string, unknown>} */ (enumDef).$ref;
1133
+ const ref = (enumDef as Record<string, unknown>).$ref;
1171
1134
  if (ref === "#/$context/contentTypes") {
1172
1135
  return Object.keys(projectState?.projectConfig?.contentTypes ?? {});
1173
1136
  }
@@ -1175,13 +1138,13 @@ function resolveSchemaEnum(enumDef, parentDef) {
1175
1138
  const match = ref.match(/#\/\$context\/contentTypes\/\{@(\w+)\}\/schema\/properties/);
1176
1139
  if (match && parentDef) {
1177
1140
  const paramName = match[1];
1178
- const typeName = /** @type {string | undefined} */ (parentDef[paramName]);
1141
+ const typeName = parentDef[paramName] as string | undefined;
1179
1142
  if (typeName) {
1180
- const ct = /** @type {Record<string, unknown> | undefined} */ (
1181
- projectState?.projectConfig?.contentTypes?.[typeName]
1182
- );
1183
- const schema = /** @type {Record<string, unknown> | undefined} */ (ct?.schema);
1184
- const props = /** @type {Record<string, unknown> | undefined} */ (schema?.properties);
1143
+ const ct = projectState?.projectConfig?.contentTypes?.[typeName] as
1144
+ | Record<string, unknown>
1145
+ | undefined;
1146
+ const schema = ct?.schema as Record<string, unknown> | undefined;
1147
+ const props = schema?.properties as Record<string, unknown> | undefined;
1185
1148
  if (props) return Object.keys(props);
1186
1149
  }
1187
1150
  }
@@ -1204,7 +1167,13 @@ function resolveSchemaEnum(enumDef, parentDef) {
1204
1167
  * @param {(val: unknown) => void} onChange
1205
1168
  * @param {Record<string, unknown>} [parentDef] - Parent def for resolving dependent enum refs
1206
1169
  */
1207
- function renderInlineField(key, schema, value, onChange, parentDef) {
1170
+ function renderInlineField(
1171
+ key: string,
1172
+ schema: Record<string, unknown>,
1173
+ value: unknown,
1174
+ onChange: (val: unknown) => void,
1175
+ parentDef?: Record<string, unknown>,
1176
+ ) {
1208
1177
  const enumValues = resolveSchemaEnum(schema.enum, parentDef);
1209
1178
 
1210
1179
  if (enumValues) {
@@ -1212,25 +1181,22 @@ function renderInlineField(key, schema, value, onChange, parentDef) {
1212
1181
  size="s"
1213
1182
  label=${key}
1214
1183
  value=${value !== undefined ? String(value) : "__none__"}
1215
- @change=${(/** @type {Event} */ e) =>
1184
+ @change=${(e: Event) =>
1216
1185
  onChange(
1217
- /** @type {HTMLInputElement} */ (e.target).value === "__none__"
1186
+ (e.target as HTMLInputElement).value === "__none__"
1218
1187
  ? undefined
1219
- : /** @type {HTMLInputElement} */ (e.target).value,
1188
+ : (e.target as HTMLInputElement).value,
1220
1189
  )}
1221
1190
  >
1222
1191
  <sp-menu-item value="__none__">—</sp-menu-item>
1223
- ${enumValues.map(
1224
- (/** @type {string} */ v) => html`<sp-menu-item value=${v}>${v}</sp-menu-item>`,
1225
- )}
1192
+ ${enumValues.map((v: string) => html`<sp-menu-item value=${v}>${v}</sp-menu-item>`)}
1226
1193
  </sp-picker>`;
1227
1194
  }
1228
1195
  if (schema.type === "boolean") {
1229
1196
  return html`<sp-switch
1230
1197
  size="s"
1231
1198
  ?checked=${!!value}
1232
- @change=${(/** @type {Event} */ e) =>
1233
- onChange(/** @type {HTMLInputElement} */ (e.target).checked)}
1199
+ @change=${(e: Event) => onChange((e.target as HTMLInputElement).checked)}
1234
1200
  >${key}</sp-switch
1235
1201
  >`;
1236
1202
  }
@@ -1240,11 +1206,11 @@ function renderInlineField(key, schema, value, onChange, parentDef) {
1240
1206
  label=${key}
1241
1207
  .value=${value !== undefined ? value : nothing}
1242
1208
  step=${schema.type === "integer" ? "1" : nothing}
1243
- @change=${(/** @type {Event} */ e) => {
1209
+ @change=${(e: Event) => {
1244
1210
  const parsed =
1245
1211
  schema.type === "integer"
1246
- ? parseInt(/** @type {HTMLInputElement} */ (e.target).value, 10)
1247
- : parseFloat(/** @type {HTMLInputElement} */ (e.target).value);
1212
+ ? parseInt((e.target as HTMLInputElement).value, 10)
1213
+ : parseFloat((e.target as HTMLInputElement).value);
1248
1214
  onChange(isNaN(parsed) ? undefined : parsed);
1249
1215
  }}
1250
1216
  ></sp-number-field>`;
@@ -1254,8 +1220,7 @@ function renderInlineField(key, schema, value, onChange, parentDef) {
1254
1220
  label=${key}
1255
1221
  placeholder=${key}
1256
1222
  .value=${value ?? ""}
1257
- @input=${(/** @type {Event} */ e) =>
1258
- onChange(/** @type {HTMLInputElement} */ (e.target).value || undefined)}
1223
+ @input=${(e: Event) => onChange((e.target as HTMLInputElement).value || undefined)}
1259
1224
  ></sp-textfield>`;
1260
1225
  }
1261
1226
 
@@ -1264,11 +1229,11 @@ function renderInlineField(key, schema, value, onChange, parentDef) {
1264
1229
  * appropriate form controls.
1265
1230
  */
1266
1231
  export function renderSchemaFieldsTemplate(
1267
- /** @type {JsonSchema | null | undefined} */ schema,
1268
- /** @type {SignalDef} */ def,
1269
- /** @type {string} */ name,
1270
- /** @type {SignalsPanelState} */ _S,
1271
- /** @type {SignalsPanelCtx | null} */ ctx = null,
1232
+ schema: JsonSchema | null | undefined,
1233
+ def: SignalDef,
1234
+ name: string,
1235
+ _S: SignalsPanelState,
1236
+ ctx: SignalsPanelCtx | null = null,
1272
1237
  ) {
1273
1238
  if (!schema?.properties) return nothing;
1274
1239
 
@@ -1291,34 +1256,35 @@ export function renderSchemaFieldsTemplate(
1291
1256
  : ps.default !== undefined
1292
1257
  ? String(ps.default)
1293
1258
  : "__none__"}
1294
- @change=${(/** @type {Event} */ e) =>
1259
+ @change=${(e: Event) =>
1295
1260
  transactDoc(activeTab.value, (t) =>
1296
1261
  mutateUpdateDef(t, name, {
1297
- [prop]: /** @type {HTMLInputElement} */ (e.target).value === "__none__"
1298
- ? undefined
1299
- : /** @type {HTMLInputElement} */ (e.target).value,
1262
+ [prop]:
1263
+ (e.target as HTMLInputElement).value === "__none__"
1264
+ ? undefined
1265
+ : (e.target as HTMLInputElement).value,
1300
1266
  }),
1301
1267
  )}
1302
1268
  >
1303
1269
  ${!required.has(prop) ? html`<sp-menu-item value="__none__">—</sp-menu-item>` : nothing}
1304
1270
  ${enumValues.map(
1305
- (/** @type {string} */ val) => html`<sp-menu-item value=${val}>${val}</sp-menu-item>`,
1271
+ (val: string) => html`<sp-menu-item value=${val}>${val}</sp-menu-item>`,
1306
1272
  )}
1307
1273
  </sp-picker>
1308
1274
  `;
1309
1275
  } else if (ps.type === "boolean") {
1310
1276
  control = html`<sp-checkbox
1311
1277
  ?checked=${currentValue ?? ps.default ?? false}
1312
- @change=${(/** @type {Event} */ e) =>
1278
+ @change=${(e: Event) =>
1313
1279
  transactDoc(activeTab.value, (t) =>
1314
1280
  mutateUpdateDef(t, name, {
1315
- [prop]: /** @type {HTMLInputElement} */ (e.target).checked,
1281
+ [prop]: (e.target as HTMLInputElement).checked,
1316
1282
  }),
1317
1283
  )}
1318
1284
  ></sp-checkbox>`;
1319
1285
  } else if (ps.type === "integer" || ps.type === "number") {
1320
1286
  /** @type {ReturnType<typeof setTimeout> | undefined} */
1321
- let debounce;
1287
+ let debounce: ReturnType<typeof setTimeout> | undefined;
1322
1288
  control = html`<sp-number-field
1323
1289
  size="s"
1324
1290
  min=${ifDefined(ps.minimum)}
@@ -1326,13 +1292,13 @@ export function renderSchemaFieldsTemplate(
1326
1292
  step=${ps.type === "integer" ? "1" : nothing}
1327
1293
  .value=${currentValue !== undefined ? currentValue : nothing}
1328
1294
  placeholder=${ps.default != null ? String(ps.default) : nothing}
1329
- @change=${(/** @type {Event} */ e) => {
1295
+ @change=${(e: Event) => {
1330
1296
  clearTimeout(debounce);
1331
1297
  debounce = setTimeout(() => {
1332
1298
  const parsed =
1333
1299
  ps.type === "integer"
1334
- ? parseInt(/** @type {HTMLInputElement} */ (e.target).value, 10)
1335
- : parseFloat(/** @type {HTMLInputElement} */ (e.target).value);
1300
+ ? parseInt((e.target as HTMLInputElement).value, 10)
1301
+ : parseFloat((e.target as HTMLInputElement).value);
1336
1302
  transactDoc(activeTab.value, (t) =>
1337
1303
  mutateUpdateDef(t, name, { [prop]: isNaN(parsed) ? undefined : parsed }),
1338
1304
  );
@@ -1342,18 +1308,16 @@ export function renderSchemaFieldsTemplate(
1342
1308
  } else if (ps.format === "json-schema") {
1343
1309
  const hasValue =
1344
1310
  currentValue && typeof currentValue === "object" && Object.keys(currentValue).length > 0;
1345
- const cv = /** @type {Record<string, unknown>} */ (currentValue);
1311
+ const cv = currentValue as Record<string, unknown>;
1346
1312
  const isRef = hasValue && cv.$ref;
1347
1313
  /** @type {ReturnType<typeof setTimeout> | undefined} */
1348
- let debounce;
1314
+ let debounce: ReturnType<typeof setTimeout> | undefined;
1349
1315
  control = html`
1350
1316
  <div class="schema-param-editor">
1351
1317
  ${hasValue && !isRef && cv.properties
1352
1318
  ? html`
1353
1319
  <div style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:4px">
1354
- ${Object.entries(
1355
- /** @type {Record<string, Record<string, unknown>>} */ (cv.properties),
1356
- ).map(
1320
+ ${Object.entries(cv.properties as Record<string, Record<string, unknown>>).map(
1357
1321
  ([k, v]) => html`
1358
1322
  <span
1359
1323
  style="background:var(--bg-alt);padding:1px 6px;border-radius:3px;font-size:10px;color:var(--fg-dim)"
@@ -1374,13 +1338,13 @@ export function renderSchemaFieldsTemplate(
1374
1338
  })}
1375
1339
  .value=${currentValue !== undefined ? JSON.stringify(currentValue, null, 2) : ""}
1376
1340
  placeholder=${ps.description ?? "JSON Schema defining the data shape\u2026"}
1377
- @input=${(/** @type {Event} */ e) => {
1341
+ @input=${(e: Event) => {
1378
1342
  clearTimeout(debounce);
1379
1343
  debounce = setTimeout(() => {
1380
1344
  try {
1381
1345
  transactDoc(activeTab.value, (t) =>
1382
1346
  mutateUpdateDef(t, name, {
1383
- [prop]: JSON.parse(/** @type {HTMLInputElement} */ (e.target).value),
1347
+ [prop]: JSON.parse((e.target as HTMLInputElement).value),
1384
1348
  }),
1385
1349
  );
1386
1350
  } catch {}
@@ -1392,13 +1356,11 @@ export function renderSchemaFieldsTemplate(
1392
1356
  } else if (ps.type === "array" && ps.items?.type === "object" && ps.items?.properties) {
1393
1357
  // Array of objects with defined schema → multi-row inline form
1394
1358
  const rows = Array.isArray(currentValue) ? currentValue : [];
1395
- const itemProps = /** @type {Record<string, Record<string, unknown>>} */ (
1396
- ps.items.properties
1397
- );
1359
+ const itemProps = ps.items.properties as Record<string, Record<string, unknown>>;
1398
1360
  control = html`
1399
1361
  <div class="array-object-field">
1400
1362
  ${rows.map(
1401
- (/** @type {Record<string, unknown>} */ row, /** @type {number} */ idx) => html`
1363
+ (row: Record<string, unknown>, idx: number) => html`
1402
1364
  <div
1403
1365
  class="array-object-row"
1404
1366
  style="display:flex;gap:4px;align-items:center;margin-bottom:4px"
@@ -1422,9 +1384,7 @@ export function renderSchemaFieldsTemplate(
1422
1384
  quiet
1423
1385
  size="s"
1424
1386
  @click=${() => {
1425
- const updated = rows.filter(
1426
- (/** @type {unknown} */ _, /** @type {number} */ i) => i !== idx,
1427
- );
1387
+ const updated = rows.filter((_: unknown, i: number) => i !== idx);
1428
1388
  transactDoc(activeTab.value, (t) =>
1429
1389
  mutateUpdateDef(t, name, { [prop]: updated.length ? updated : undefined }),
1430
1390
  );
@@ -1439,13 +1399,12 @@ export function renderSchemaFieldsTemplate(
1439
1399
  <sp-action-button
1440
1400
  quiet
1441
1401
  size="s"
1442
- @click=${(/** @type {Event} */ e) => {
1402
+ @click=${(e: Event) => {
1443
1403
  e.stopPropagation();
1444
- /** @type {Record<string, unknown>} */
1445
- const newRow = {};
1404
+ const newRow: Record<string, unknown> = {};
1446
1405
  for (const [k, v] of Object.entries(itemProps)) {
1447
- if (/** @type {Record<string, unknown>} */ (v).default !== undefined)
1448
- newRow[k] = /** @type {Record<string, unknown>} */ (v).default;
1406
+ if ((v as Record<string, unknown>).default !== undefined)
1407
+ newRow[k] = (v as Record<string, unknown>).default;
1449
1408
  }
1450
1409
  transactDoc(activeTab.value, (t) =>
1451
1410
  mutateUpdateDef(t, name, { [prop]: [...rows, newRow] }),
@@ -1458,20 +1417,20 @@ export function renderSchemaFieldsTemplate(
1458
1417
  `;
1459
1418
  } else if (ps.type === "array" || ps.type === "object") {
1460
1419
  /** @type {ReturnType<typeof setTimeout> | undefined} */
1461
- let debounce;
1420
+ let debounce: ReturnType<typeof setTimeout> | undefined;
1462
1421
  control = html`<sp-textfield
1463
1422
  multiline
1464
1423
  size="s"
1465
1424
  style="min-height:40px"
1466
1425
  .value=${currentValue !== undefined ? JSON.stringify(currentValue, null, 2) : ""}
1467
1426
  placeholder=${ps.default !== undefined ? JSON.stringify(ps.default) : nothing}
1468
- @input=${(/** @type {Event} */ e) => {
1427
+ @input=${(e: Event) => {
1469
1428
  clearTimeout(debounce);
1470
1429
  debounce = setTimeout(() => {
1471
1430
  try {
1472
1431
  transactDoc(activeTab.value, (t) =>
1473
1432
  mutateUpdateDef(t, name, {
1474
- [prop]: JSON.parse(/** @type {HTMLInputElement} */ (e.target).value),
1433
+ [prop]: JSON.parse((e.target as HTMLInputElement).value),
1475
1434
  }),
1476
1435
  );
1477
1436
  } catch {}
@@ -1480,20 +1439,20 @@ export function renderSchemaFieldsTemplate(
1480
1439
  ></sp-textfield>`;
1481
1440
  } else {
1482
1441
  /** @type {ReturnType<typeof setTimeout> | undefined} */
1483
- let debounce;
1442
+ let debounce: ReturnType<typeof setTimeout> | undefined;
1484
1443
  const ph = ps.default !== undefined ? String(ps.default) : (ps.examples?.[0] ?? "");
1485
1444
  control = html`<sp-textfield
1486
1445
  size="s"
1487
1446
  .value=${currentValue ?? ""}
1488
1447
  placeholder=${ph || nothing}
1489
1448
  title=${ps.description || nothing}
1490
- @input=${(/** @type {Event} */ e) => {
1449
+ @input=${(e: Event) => {
1491
1450
  clearTimeout(debounce);
1492
1451
  debounce = setTimeout(
1493
1452
  () =>
1494
1453
  transactDoc(activeTab.value, (t) =>
1495
1454
  mutateUpdateDef(t, name, {
1496
- [prop]: /** @type {HTMLInputElement} */ (e.target).value || undefined,
1455
+ [prop]: (e.target as HTMLInputElement).value || undefined,
1497
1456
  }),
1498
1457
  ),
1499
1458
  400,
@@ -1518,14 +1477,13 @@ export function renderSchemaFieldsTemplate(
1518
1477
  * schema-driven config fields.
1519
1478
  */
1520
1479
  export function renderExternalPrototypeEditorTemplate(
1521
- /** @type {SignalsPanelState} */ S,
1522
- /** @type {string} */ name,
1523
- /** @type {SignalDef} */ def,
1524
- /** @type {SignalsPanelCtx} */ ctx,
1480
+ S: SignalsPanelState,
1481
+ name: string,
1482
+ def: SignalDef,
1483
+ ctx: SignalsPanelCtx,
1525
1484
  ) {
1526
1485
  // Schema-driven config fields (async with cache)
1527
- /** @type {import("lit-html").TemplateResult | typeof nothing} */
1528
- let schemaContent = nothing;
1486
+ let schemaContent: import("lit-html").TemplateResult | typeof nothing = nothing;
1529
1487
  const importedPath = def.$prototype
1530
1488
  ? projectState?.projectConfig?.imports?.[def.$prototype]
1531
1489
  : null;
@@ -1549,7 +1507,9 @@ export function renderExternalPrototypeEditorTemplate(
1549
1507
  >
1550
1508
  Loading schema…
1551
1509
  </div>`;
1552
- fetchPluginSchema(def, /** @type {{ documentPath?: string }} */ (S)).then((schema) => {
1510
+ fetchPluginSchema(def, {
1511
+ ...(S.documentPath != null && { documentPath: S.documentPath }),
1512
+ }).then((schema) => {
1553
1513
  if (schema) ctx.renderLeftPanel();
1554
1514
  });
1555
1515
  }
@@ -1561,11 +1521,11 @@ export function renderExternalPrototypeEditorTemplate(
1561
1521
  ${def.$prototype}
1562
1522
  </div>`
1563
1523
  : html`
1564
- ${signalFieldRow("Source", def.$src || "", (/** @type {string} */ v) => {
1524
+ ${signalFieldRow("Source", def.$src || "", (v: string) => {
1565
1525
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $src: v || undefined }));
1566
1526
  pluginSchemaCache.delete(`${v}::${def.$prototype}`);
1567
1527
  })}
1568
- ${signalFieldRow("Prototype", def.$prototype || "", (/** @type {string} */ v) => {
1528
+ ${signalFieldRow("Prototype", def.$prototype || "", (v: string) => {
1569
1529
  transactDoc(activeTab.value, (t) =>
1570
1530
  mutateUpdateDef(t, name, { $prototype: v || undefined }),
1571
1531
  );
@@ -1573,7 +1533,7 @@ export function renderExternalPrototypeEditorTemplate(
1573
1533
  })}
1574
1534
  `}
1575
1535
  ${def.$export
1576
- ? signalFieldRow("Export", def.$export || "", (/** @type {string} */ v) =>
1536
+ ? signalFieldRow("Export", def.$export || "", (v: string) =>
1577
1537
  transactDoc(activeTab.value, (t) =>
1578
1538
  mutateUpdateDef(t, name, { $export: v || undefined }),
1579
1539
  ),