@jxsuite/studio 0.23.2 → 0.24.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.
- package/dist/studio.js +2230 -714
- package/dist/studio.js.map +121 -104
- package/package.json +8 -7
- package/src/browse/{browse-modal.js → browse-modal.ts} +9 -10
- package/src/browse/{browse.js → browse.ts} +109 -84
- package/src/canvas/{canvas-diff.js → canvas-diff.ts} +42 -35
- package/src/canvas/{canvas-helpers.js → canvas-helpers.ts} +25 -19
- package/src/canvas/{canvas-live-render.js → canvas-live-render.ts} +53 -63
- package/src/canvas/{canvas-render.js → canvas-render.ts} +110 -121
- package/src/canvas/{canvas-utils.js → canvas-utils.ts} +48 -44
- package/src/canvas/{nested-site-style.js → nested-site-style.ts} +3 -3
- package/src/editor/{component-inline-edit.js → component-inline-edit.ts} +45 -33
- package/src/editor/{content-inline-edit.js → content-inline-edit.ts} +27 -45
- package/src/editor/{context-menu.js → context-menu.ts} +38 -36
- package/src/editor/{convert-targets.js → convert-targets.ts} +15 -12
- package/src/editor/{convert-to-component.js → convert-to-component.ts} +25 -26
- package/src/editor/{convert-to-repeater.js → convert-to-repeater.ts} +60 -40
- package/src/editor/{inline-edit.js → inline-edit.ts} +91 -55
- package/src/editor/{inline-format.js → inline-format.ts} +46 -51
- package/src/editor/{insertion-helper.js → insertion-helper.ts} +47 -63
- package/src/editor/{shortcuts.js → shortcuts.ts} +45 -31
- package/src/editor/{slash-menu.js → slash-menu.ts} +34 -35
- package/src/files/{components.js → components.ts} +12 -15
- package/src/files/{file-ops.js → file-ops.ts} +36 -29
- package/src/files/{files.js → files.ts} +102 -84
- package/src/github/{github-auth.js → github-auth.ts} +3 -3
- package/src/github/{github-publish.js → github-publish.ts} +20 -18
- package/src/markdown/{md-allowlist.js → md-allowlist.ts} +5 -2
- package/src/markdown/{md-convert.js → md-convert.ts} +146 -169
- package/src/new-project/{new-project-modal.js → new-project-modal.ts} +16 -18
- package/src/panels/{activity-bar.js → activity-bar.ts} +26 -34
- package/src/panels/{ai-panel.js → ai-panel.ts} +30 -30
- package/src/panels/{block-action-bar.js → block-action-bar.ts} +64 -73
- package/src/panels/{canvas-dnd.js → canvas-dnd.ts} +44 -49
- package/src/panels/{data-explorer.js → data-explorer.ts} +21 -15
- package/src/panels/dnd.ts +417 -0
- package/src/panels/{editors.js → editors.ts} +43 -50
- package/src/panels/{elements-panel.js → elements-panel.ts} +30 -27
- package/src/panels/{events-panel.js → events-panel.ts} +33 -25
- package/src/panels/{git-panel.js → git-panel.ts} +97 -83
- package/src/panels/{head-panel.js → head-panel.ts} +117 -139
- package/src/panels/{imports-panel.js → imports-panel.ts} +69 -89
- package/src/panels/{layers-panel.js → layers-panel.ts} +61 -57
- package/src/panels/{left-panel.js → left-panel.ts} +56 -63
- package/src/panels/{overlays.js → overlays.ts} +28 -36
- package/src/panels/{panel-events.js → panel-events.ts} +53 -51
- package/src/panels/{preview-render.js → preview-render.ts} +20 -15
- package/src/panels/{properties-panel.js → properties-panel.ts} +212 -246
- package/src/panels/{pseudo-preview.js → pseudo-preview.ts} +9 -8
- package/src/panels/{quick-search.js → quick-search.ts} +16 -17
- package/src/panels/{right-panel.js → right-panel.ts} +41 -59
- package/src/panels/{shared.js → shared.ts} +7 -5
- package/src/panels/{signals-panel.js → signals-panel.ts} +322 -362
- package/src/panels/{statusbar.js → statusbar.ts} +14 -14
- package/src/panels/{style-inputs.js → style-inputs.ts} +66 -48
- package/src/panels/{style-panel.js → style-panel.ts} +235 -290
- package/src/panels/{style-utils.js → style-utils.ts} +32 -31
- package/src/panels/{stylebook-layers-panel.js → stylebook-layers-panel.ts} +22 -14
- package/src/panels/{stylebook-panel.js → stylebook-panel.ts} +127 -140
- package/src/panels/{tab-strip.js → tab-strip.ts} +12 -14
- package/src/panels/{toolbar.js → toolbar.ts} +68 -70
- package/src/panels/{welcome-screen.js → welcome-screen.ts} +14 -16
- package/src/{platform.js → platform.ts} +5 -3
- package/src/platforms/{devserver.js → devserver.ts} +53 -44
- package/src/{recent-projects.js → recent-projects.ts} +17 -12
- package/src/{resize-edges.js → resize-edges.ts} +18 -13
- package/src/services/{cem-export.js → cem-export.ts} +14 -7
- package/src/services/{code-services.js → code-services.ts} +29 -20
- package/src/services/{monaco-setup.js → monaco-setup.ts} +2 -3
- package/src/settings/{content-types-editor.js → content-types-editor.ts} +88 -67
- package/src/settings/{css-vars-editor.js → css-vars-editor.ts} +78 -51
- package/src/settings/{defs-editor.js → defs-editor.ts} +70 -56
- package/src/settings/{general-settings.js → general-settings.ts} +29 -28
- package/src/settings/{head-editor.js → head-editor.ts} +37 -35
- package/src/settings/{schema-field-ui.js → schema-field-ui.ts} +86 -76
- package/src/settings/{settings-modal.js → settings-modal.ts} +14 -16
- package/src/{site-context.js → site-context.ts} +35 -32
- package/src/{state.js → state.ts} +95 -78
- package/src/{store.js → store.ts} +60 -63
- package/src/{studio.js → studio.ts} +117 -119
- package/src/tabs/tab.ts +196 -0
- package/src/tabs/{transact.js → transact.ts} +107 -60
- package/src/types.ts +185 -0
- package/src/ui/{button-group.js → button-group.ts} +21 -21
- package/src/ui/{color-selector.js → color-selector.ts} +44 -37
- package/src/ui/{expression-editor.js → expression-editor.ts} +65 -40
- package/src/ui/{field-row.js → field-row.ts} +19 -2
- package/src/ui/{icons.js → icons.ts} +2 -2
- package/src/ui/{layers.js → layers.ts} +33 -24
- package/src/ui/{media-picker.js → media-picker.ts} +13 -9
- package/src/ui/{panel-resize.js → panel-resize.ts} +9 -4
- package/src/ui/{spectrum.js → spectrum.ts} +4 -4
- package/src/ui/{unit-selector.js → unit-selector.ts} +16 -19
- package/src/ui/{value-selector.js → value-selector.ts} +28 -28
- package/src/ui/{widgets.js → widgets.ts} +62 -15
- package/src/utils/{canvas-media.js → canvas-media.ts} +29 -14
- package/src/utils/{edit-display.js → edit-display.ts} +23 -20
- package/src/utils/{google-fonts.js → google-fonts.ts} +14 -13
- package/src/utils/{inherited-style.js → inherited-style.ts} +15 -10
- package/src/utils/{studio-utils.js → studio-utils.ts} +35 -23
- package/src/{view.js → view.ts} +53 -55
- package/src/workspace/{workspace.js → workspace.ts} +44 -33
- package/src/panels/dnd.js +0 -426
- package/src/tabs/tab.js +0 -192
- /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
|
|
12
|
-
import {
|
|
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
|
|
20
|
-
import { renderFieldRow } from "../ui/field-row
|
|
21
|
-
import { renderExpressionEditor, expressionHint } from "../ui/expression-editor
|
|
22
|
-
import { renderMediaPicker } from "../ui/media-picker
|
|
23
|
-
import {
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
@
|
|
291
|
-
|
|
292
|
-
|
|
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(
|
|
304
|
-
return typeof p === "string" ? { name: 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 =
|
|
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
|
-
|
|
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=${(
|
|
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=${(
|
|
399
|
-
const type =
|
|
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
|
-
|
|
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
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
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=${(
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
516
|
+
label: string,
|
|
517
|
+
value: string,
|
|
518
|
+
onChange: (value: string) => void,
|
|
519
|
+
opts: { minHeight?: string; mono?: boolean } = {},
|
|
524
520
|
) => {
|
|
525
|
-
|
|
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=${(
|
|
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, (
|
|
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
|
-
|
|
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 || "", (
|
|
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=${(
|
|
579
|
+
@change=${(e: Event) =>
|
|
589
580
|
transactDoc(activeTab.value, (t) =>
|
|
590
581
|
mutateUpdateDef(t, name, {
|
|
591
|
-
reflects:
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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, (
|
|
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, (
|
|
639
|
-
|
|
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:
|
|
637
|
+
mutateUpdateDef(t, name, { default: parsed as JsonValue }),
|
|
653
638
|
);
|
|
654
639
|
})}
|
|
655
|
-
${signalFieldRow("Description", def.description || "", (
|
|
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
|
-
|
|
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=${(
|
|
659
|
+
@input=${(e: Event) => {
|
|
676
660
|
clearTimeout(debounce);
|
|
677
661
|
debounce = setTimeout(() => {
|
|
678
|
-
const expr =
|
|
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
|
-
(
|
|
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
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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 || "", (
|
|
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
|
-
(
|
|
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
|
-
|
|
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 || "", (
|
|
750
|
+
${signalFieldRow("Key", def.key || "", (v: string) =>
|
|
764
751
|
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { key: v })),
|
|
765
752
|
)}
|
|
766
|
-
${textareaRow("Default", defaultStr, (
|
|
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 || "", (
|
|
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 || "", (
|
|
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), (
|
|
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 || "", (
|
|
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 || ""), (
|
|
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, (
|
|
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
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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
|
-
|
|
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 || "", (
|
|
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 || "", (
|
|
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=${(
|
|
869
|
-
const v =
|
|
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
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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=${(
|
|
932
|
-
if (e.key === "Enter" &&
|
|
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
|
-
(
|
|
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=${(
|
|
952
|
+
@change=${(e: Event) => {
|
|
973
953
|
const next = [...params];
|
|
974
|
-
next[i] = { ...next[i], name:
|
|
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=${(
|
|
965
|
+
@change=${(e: Event) => {
|
|
986
966
|
const next = [...params];
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
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=${(
|
|
980
|
+
@change=${(e: Event) => {
|
|
1004
981
|
const next = [...params];
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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=${(
|
|
994
|
+
@change=${(e: Event) => {
|
|
1019
995
|
const next = [...params];
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
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=${(
|
|
1058
|
+
@change=${(e: Event) => {
|
|
1090
1059
|
const next = [...emits];
|
|
1091
|
-
next[i] = { ...next[i], name:
|
|
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=${(
|
|
1069
|
+
@change=${(e: Event) => {
|
|
1101
1070
|
const next = [...emits];
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
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=${(
|
|
1082
|
+
@change=${(e: Event) => {
|
|
1117
1083
|
const next = [...emits];
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
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
|
-
(
|
|
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 =
|
|
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 =
|
|
1141
|
+
const typeName = parentDef[paramName] as string | undefined;
|
|
1179
1142
|
if (typeName) {
|
|
1180
|
-
const ct =
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
const schema =
|
|
1184
|
-
const props =
|
|
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(
|
|
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=${(
|
|
1184
|
+
@change=${(e: Event) =>
|
|
1216
1185
|
onChange(
|
|
1217
|
-
|
|
1186
|
+
(e.target as HTMLInputElement).value === "__none__"
|
|
1218
1187
|
? undefined
|
|
1219
|
-
:
|
|
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=${(
|
|
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=${(
|
|
1209
|
+
@change=${(e: Event) => {
|
|
1244
1210
|
const parsed =
|
|
1245
1211
|
schema.type === "integer"
|
|
1246
|
-
? parseInt(
|
|
1247
|
-
: parseFloat(
|
|
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=${(
|
|
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
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
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=${(
|
|
1259
|
+
@change=${(e: Event) =>
|
|
1295
1260
|
transactDoc(activeTab.value, (t) =>
|
|
1296
1261
|
mutateUpdateDef(t, name, {
|
|
1297
|
-
[prop]:
|
|
1298
|
-
|
|
1299
|
-
|
|
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
|
-
(
|
|
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=${(
|
|
1278
|
+
@change=${(e: Event) =>
|
|
1313
1279
|
transactDoc(activeTab.value, (t) =>
|
|
1314
1280
|
mutateUpdateDef(t, name, {
|
|
1315
|
-
[prop]:
|
|
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=${(
|
|
1295
|
+
@change=${(e: Event) => {
|
|
1330
1296
|
clearTimeout(debounce);
|
|
1331
1297
|
debounce = setTimeout(() => {
|
|
1332
1298
|
const parsed =
|
|
1333
1299
|
ps.type === "integer"
|
|
1334
|
-
? parseInt(
|
|
1335
|
-
: parseFloat(
|
|
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 =
|
|
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=${(
|
|
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(
|
|
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 =
|
|
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
|
-
(
|
|
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=${(
|
|
1402
|
+
@click=${(e: Event) => {
|
|
1443
1403
|
e.stopPropagation();
|
|
1444
|
-
|
|
1445
|
-
const newRow = {};
|
|
1404
|
+
const newRow: Record<string, unknown> = {};
|
|
1446
1405
|
for (const [k, v] of Object.entries(itemProps)) {
|
|
1447
|
-
if (
|
|
1448
|
-
newRow[k] =
|
|
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=${(
|
|
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(
|
|
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=${(
|
|
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]:
|
|
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
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1480
|
+
S: SignalsPanelState,
|
|
1481
|
+
name: string,
|
|
1482
|
+
def: SignalDef,
|
|
1483
|
+
ctx: SignalsPanelCtx,
|
|
1525
1484
|
) {
|
|
1526
1485
|
// Schema-driven config fields (async with cache)
|
|
1527
|
-
|
|
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,
|
|
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 || "", (
|
|
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 || "", (
|
|
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 || "", (
|
|
1536
|
+
? signalFieldRow("Export", def.$export || "", (v: string) =>
|
|
1577
1537
|
transactDoc(activeTab.value, (t) =>
|
|
1578
1538
|
mutateUpdateDef(t, name, { $export: v || undefined }),
|
|
1579
1539
|
),
|