@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,39 +1,42 @@
1
+ /// <reference lib="dom" />
1
2
  /**
2
3
  * Editor panels — extracted from studio.js (Phase 4g). Monaco-based function editor (JS mode) and
3
4
  * completion provider for state scope variables.
4
5
  */
5
6
 
6
- /** @typedef {import("../services/code-services.js").OxLintDiagnostic} OxLintDiagnostic */
7
-
8
7
  import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
9
8
  import { html, render as litRender, nothing } from "lit-html";
10
9
  import { ref } from "lit-html/directives/ref.js";
11
10
 
12
- import { renderOnly, canvasWrap, canvasPanels, getNodeAtPath } from "../store.js";
13
- import { activeTab } from "../workspace/workspace.js";
14
- import { transactDoc, mutateUpdateDef, mutateUpdateProperty } from "../tabs/transact.js";
15
- import { view } from "../view.js";
16
- import { codeService, setLintMarkers, getFunctionArgs } from "../services/code-services.js";
11
+ import { renderOnly, canvasWrap, canvasPanels, getNodeAtPath } from "../store";
12
+ import { activeTab } from "../workspace/workspace";
13
+ import { transactDoc, mutateUpdateDef, mutateUpdateProperty } from "../tabs/transact";
14
+ import { view } from "../view";
15
+ import { codeService, setLintMarkers, getFunctionArgs } from "../services/code-services";
16
+
17
+ import type { OxLintDiagnostic } from "../services/code-services";
18
+ import type { JxPrototypeDef, JxMutableNode } from "@jxsuite/schema/types";
19
+ import type { JxPath } from "../state";
17
20
 
18
- /** @typedef {{ type: "def"; defName: string } | { type: "event"; path: JxPath; eventKey: string }} EditingTarget */
21
+ type EditingTarget =
22
+ | { type: "def"; defName: string }
23
+ | { type: "event"; path: JxPath; eventKey: string };
19
24
 
20
25
  /** @param {EditingTarget | null | undefined} editing */
21
- function getFunctionBody(editing) {
26
+ function getFunctionBody(editing: EditingTarget | null | undefined) {
22
27
  const document = activeTab.value?.doc.document;
23
28
  if (editing?.type === "def") {
24
29
  return document?.state?.[editing.defName]?.body || "";
25
30
  } else if (editing?.type === "event") {
26
- const node = getNodeAtPath(/** @type {JxMutableNode} */ (document), editing.path);
31
+ const node = getNodeAtPath(document!, editing.path);
27
32
  return node?.[editing.eventKey]?.body || "";
28
33
  }
29
34
  return "";
30
35
  }
31
36
 
32
37
  /** @param {() => void} closeFunctionEditor */
33
- export function renderFunctionEditor(closeFunctionEditor) {
34
- const editing = /** @type {EditingTarget | null | undefined} */ (
35
- activeTab.value?.session.ui.editingFunction
36
- );
38
+ export function renderFunctionEditor(closeFunctionEditor: () => void) {
39
+ const editing = activeTab.value?.session.ui.editingFunction as EditingTarget | null | undefined;
37
40
 
38
41
  // If editor already exists and matches current target, just sync value
39
42
  if (view.functionEditor && view.functionEditor._editingTarget === JSON.stringify(editing)) {
@@ -73,12 +76,11 @@ export function renderFunctionEditor(closeFunctionEditor) {
73
76
 
74
77
  const tab = activeTab.value;
75
78
  const docName = tab?.documentPath?.split("/").pop() || tab?.doc.document?.tagName || "document";
76
- const ed = /** @type {EditingTarget} */ (editing);
79
+ const ed = editing as EditingTarget;
77
80
  const funcLabel = ed.type === "def" ? `ƒ ${ed.defName}` : `ƒ ${ed.eventKey}`;
78
81
 
79
82
  // Editor container
80
- /** @type {HTMLDivElement | null} */
81
- let editorContainer = null;
83
+ let editorContainer: HTMLDivElement | null = null;
82
84
  litRender(
83
85
  html`<div class="source-wrap">
84
86
  <div class="source-toolbar">
@@ -93,7 +95,7 @@ export function renderFunctionEditor(closeFunctionEditor) {
93
95
  <div
94
96
  class="source-editor"
95
97
  ${ref((el) => {
96
- if (el) editorContainer = /** @type {HTMLDivElement} */ (el);
98
+ if (el) editorContainer = el as HTMLDivElement;
97
99
  })}
98
100
  ></div>
99
101
  </div>`,
@@ -102,26 +104,23 @@ export function renderFunctionEditor(closeFunctionEditor) {
102
104
 
103
105
  const body = getFunctionBody(editing);
104
106
  const args = getFunctionArgs(
105
- /** @type {EditingTarget} */ (editing),
107
+ /** @type {EditingTarget} */ (editing as EditingTarget),
106
108
  activeTab.value?.doc.document,
107
109
  );
108
110
 
109
- view.functionEditor = monaco.editor.create(
110
- /** @type {HTMLElement} */ (/** @type {unknown} */ (editorContainer)),
111
- {
112
- value: body,
113
- language: "javascript",
114
- theme: "vs-dark",
115
- automaticLayout: true,
116
- minimap: { enabled: false },
117
- fontSize: 12,
118
- fontFamily: "'SF Mono', 'Fira Code', 'Consolas', monospace",
119
- lineNumbers: "on",
120
- scrollBeyondLastLine: false,
121
- wordWrap: "on",
122
- tabSize: 2,
123
- },
124
- );
111
+ view.functionEditor = monaco.editor.create(editorContainer as unknown as HTMLElement, {
112
+ value: body,
113
+ language: "javascript",
114
+ theme: "vs-dark",
115
+ automaticLayout: true,
116
+ minimap: { enabled: false },
117
+ fontSize: 12,
118
+ fontFamily: "'SF Mono', 'Fira Code', 'Consolas', monospace",
119
+ lineNumbers: "on",
120
+ scrollBeyondLastLine: false,
121
+ wordWrap: "on",
122
+ tabSize: 2,
123
+ });
125
124
  view.functionEditor._editingTarget = JSON.stringify(editing);
126
125
  const editor = view.functionEditor;
127
126
 
@@ -134,14 +133,14 @@ export function renderFunctionEditor(closeFunctionEditor) {
134
133
  });
135
134
  codeService("lint", { code: body, args }).then((result) => {
136
135
  if (result?.diagnostics && view.functionEditor)
137
- setLintMarkers(view.functionEditor, /** @type {OxLintDiagnostic[]} */ (result.diagnostics));
136
+ setLintMarkers(view.functionEditor, result.diagnostics as OxLintDiagnostic[]);
138
137
  });
139
138
 
140
139
  // Debounced sync back to state + lint on edit
141
140
  /** @type {ReturnType<typeof setTimeout> | undefined} */
142
- let syncDebounce;
141
+ let syncDebounce: ReturnType<typeof setTimeout> | undefined;
143
142
  /** @type {ReturnType<typeof setTimeout> | undefined} */
144
- let lintDebounce;
143
+ let lintDebounce: ReturnType<typeof setTimeout> | undefined;
145
144
  let lintGen = 0;
146
145
  editor.onDidChangeModelContent(() => {
147
146
  if (editor._ignoreNextChange) {
@@ -152,14 +151,11 @@ export function renderFunctionEditor(closeFunctionEditor) {
152
151
  clearTimeout(syncDebounce);
153
152
  syncDebounce = setTimeout(() => {
154
153
  const newBody = editor.getValue();
155
- const ed = /** @type {EditingTarget} */ (editing);
154
+ const ed = editing as EditingTarget;
156
155
  if (ed.type === "def") {
157
156
  transactDoc(activeTab.value, (t) => mutateUpdateDef(t, ed.defName, { body: newBody }));
158
157
  } else if (ed.type === "event") {
159
- const node = getNodeAtPath(
160
- /** @type {JxMutableNode} */ (activeTab.value?.doc.document),
161
- ed.path,
162
- );
158
+ const node = getNodeAtPath(activeTab.value?.doc.document as JxMutableNode, ed.path);
163
159
  const current = node?.[ed.eventKey] || {};
164
160
  transactDoc(activeTab.value, (t) =>
165
161
  mutateUpdateProperty(t, ed.path, ed.eventKey, {
@@ -179,10 +175,7 @@ export function renderFunctionEditor(closeFunctionEditor) {
179
175
  codeService("lint", { code: currentCode, args }).then((result) => {
180
176
  if (gen !== lintGen) return;
181
177
  if (result?.diagnostics && view.functionEditor)
182
- setLintMarkers(
183
- view.functionEditor,
184
- /** @type {OxLintDiagnostic[]} */ (result.diagnostics),
185
- );
178
+ setLintMarkers(view.functionEditor, result.diagnostics as OxLintDiagnostic[]);
186
179
  });
187
180
  }, 750);
188
181
  });
@@ -207,11 +200,11 @@ export function registerFunctionCompletions() {
207
200
  const suggestions = Object.entries(defs).map(([key, def]) => {
208
201
  let kind = monaco.languages.CompletionItemKind.Variable;
209
202
  if (
210
- /** @type {JxPrototypeDef} */ (def)?.$prototype === "Function" ||
211
- /** @type {{ $handler?: unknown }} */ (def)?.$handler
203
+ (def as JxPrototypeDef)?.$prototype === "Function" ||
204
+ (def as Record<string, unknown>)?.$handler
212
205
  )
213
206
  kind = monaco.languages.CompletionItemKind.Function;
214
- else if (/** @type {JxPrototypeDef} */ (def)?.$prototype)
207
+ else if ((def as JxPrototypeDef)?.$prototype)
215
208
  kind = monaco.languages.CompletionItemKind.Property;
216
209
  return {
217
210
  label: `state.${key}`,
@@ -1,14 +1,16 @@
1
+ /// <reference lib="dom" />
1
2
  /** Elements panel — block/component palette with categorized accordion and search filter. */
2
3
 
3
4
  import { html, nothing } from "lit-html";
4
- import { getNodeAtPath } from "../store.js";
5
- import { activeTab } from "../workspace/workspace.js";
6
- import { transactDoc, mutateInsertNode } from "../tabs/transact.js";
7
- import { view } from "../view.js";
8
- import { getEffectiveElements } from "../site-context.js";
9
- import { componentRegistry } from "../files/components.js";
5
+ import { getNodeAtPath } from "../store";
6
+ import { activeTab } from "../workspace/workspace";
7
+ import { transactDoc, mutateInsertNode } from "../tabs/transact";
8
+ import { view } from "../view";
9
+ import { getEffectiveElements } from "../site-context";
10
+ import { componentRegistry } from "../files/components";
10
11
 
11
- /** @typedef {import("../files/components.js").ComponentEntry} ComponentEntry */
12
+ import type { ComponentEntry } from "../files/components";
13
+ import type { JxElement, JxMutableNode } from "@jxsuite/schema/types";
12
14
 
13
15
  /**
14
16
  * @param {{
@@ -18,7 +20,11 @@ import { componentRegistry } from "../files/components.js";
18
20
  * }} ctx
19
21
  * @returns {import("lit-html").TemplateResult}
20
22
  */
21
- export function renderElementsTemplate(ctx) {
23
+ export function renderElementsTemplate(ctx: {
24
+ webdata: { elements: Record<string, { tag: string }[]> };
25
+ defaultDef: (tag: string) => JxMutableNode;
26
+ rerender: () => void;
27
+ }) {
22
28
  const tab = activeTab.value;
23
29
 
24
30
  const categories = Object.entries(ctx.webdata.elements).map(
@@ -32,8 +38,8 @@ export function renderElementsTemplate(ctx) {
32
38
  <sp-accordion-item
33
39
  label=${category}
34
40
  ?open=${!view.elementsCollapsed.has(category)}
35
- @sp-accordion-item-toggle=${(/** @type {Event} */ e) => {
36
- if (/** @type {HTMLElement & { open: boolean }} */ (e.target).open)
41
+ @sp-accordion-item-toggle=${(e: Event) => {
42
+ if ((e.target as HTMLElement & { open: boolean }).open)
37
43
  view.elementsCollapsed.delete(category);
38
44
  else view.elementsCollapsed.add(category);
39
45
  }}
@@ -47,9 +53,9 @@ export function renderElementsTemplate(ctx) {
47
53
  @click=${() => {
48
54
  const t = activeTab.value;
49
55
  const parentPath = t?.session.selection || [];
50
- const parent = getNodeAtPath(t?.doc.document, parentPath);
56
+ const parent = getNodeAtPath(t!.doc.document, parentPath);
51
57
  const idx = parent?.children ? parent.children.length : 0;
52
- transactDoc(t, (tr) =>
58
+ transactDoc(t!, (tr) =>
53
59
  mutateInsertNode(tr, parentPath, idx, structuredClone(def)),
54
60
  );
55
61
  }}
@@ -65,14 +71,13 @@ export function renderElementsTemplate(ctx) {
65
71
  );
66
72
 
67
73
  const effectiveEls = getEffectiveElements(
68
- /** @type {(string | JxElement)[] | undefined} */ (tab?.doc.document?.$elements),
74
+ tab?.doc.document?.$elements as (string | JxElement)[] | undefined,
69
75
  );
70
- /** @type {Set<string>} */
71
- const enabledTags = new Set();
76
+ const enabledTags: Set<string> = new Set();
72
77
  for (const entry of effectiveEls) {
73
78
  if (typeof entry !== "string") continue;
74
79
  const comp = componentRegistry.find(
75
- (/** @type {ComponentEntry} */ c) =>
80
+ (c: ComponentEntry) =>
76
81
  c.source === "npm" && c.modulePath && entry === `${c.package}/${c.modulePath}`,
77
82
  );
78
83
  if (comp) {
@@ -86,11 +91,9 @@ export function renderElementsTemplate(ctx) {
86
91
  const compsFiltered =
87
92
  componentRegistry.length > 0
88
93
  ? componentRegistry
94
+ .filter((c: ComponentEntry) => c.source !== "npm" || enabledTags.has(c.tagName))
89
95
  .filter(
90
- (/** @type {ComponentEntry} */ c) => c.source !== "npm" || enabledTags.has(c.tagName),
91
- )
92
- .filter(
93
- (/** @type {ComponentEntry} */ c) =>
96
+ (c: ComponentEntry) =>
94
97
  !view.elementsFilter || c.tagName.toLowerCase().includes(view.elementsFilter),
95
98
  )
96
99
  : [];
@@ -101,15 +104,15 @@ export function renderElementsTemplate(ctx) {
101
104
  <sp-accordion-item
102
105
  label="Components"
103
106
  ?open=${!view.elementsCollapsed.has("Components")}
104
- @sp-accordion-item-toggle=${(/** @type {Event} */ e) => {
105
- if (/** @type {HTMLElement & { open: boolean }} */ (e.target).open)
107
+ @sp-accordion-item-toggle=${(e: Event) => {
108
+ if ((e.target as HTMLElement & { open: boolean }).open)
106
109
  view.elementsCollapsed.delete("Components");
107
110
  else view.elementsCollapsed.add("Components");
108
111
  }}
109
112
  >
110
113
  <div class="components-section">
111
114
  ${compsFiltered.map(
112
- (/** @type {ComponentEntry} */ comp) => html`
115
+ (comp: ComponentEntry) => html`
113
116
  <div
114
117
  class="element-card"
115
118
  data-component-tag=${comp.tagName}
@@ -119,7 +122,7 @@ export function renderElementsTemplate(ctx) {
119
122
  @click=${() => {
120
123
  const t = activeTab.value;
121
124
  const parentPath = t?.session.selection || [];
122
- const parent = getNodeAtPath(t?.doc.document, parentPath);
125
+ const parent = getNodeAtPath(t!.doc.document, parentPath);
123
126
  const idx = parent?.children ? parent.children.length : 0;
124
127
  const instanceDef = {
125
128
  tagName: comp.tagName,
@@ -132,7 +135,7 @@ export function renderElementsTemplate(ctx) {
132
135
  ),
133
136
  ),
134
137
  };
135
- transactDoc(t, (tr) =>
138
+ transactDoc(t!, (tr) =>
136
139
  mutateInsertNode(tr, parentPath, idx, structuredClone(instanceDef)),
137
140
  );
138
141
  }}
@@ -156,8 +159,8 @@ export function renderElementsTemplate(ctx) {
156
159
  size="s"
157
160
  placeholder="Filter elements…"
158
161
  value=${view.elementsFilter}
159
- @input=${(/** @type {Event} */ e) => {
160
- view.elementsFilter = /** @type {HTMLInputElement} */ (e.target).value.toLowerCase();
162
+ @input=${(e: Event) => {
163
+ view.elementsFilter = (e.target as HTMLInputElement).value.toLowerCase();
161
164
  ctx.rerender();
162
165
  }}
163
166
  ></sp-search>
@@ -1,9 +1,12 @@
1
- import { getNodeAtPath } from "../store.js";
1
+ /// <reference lib="dom" />
2
+ import { getNodeAtPath } from "../store";
2
3
  import { html, nothing } from "lit-html";
3
4
  import { live } from "lit-html/directives/live.js";
4
- import { activeTab } from "../workspace/workspace.js";
5
- import { transactDoc, mutateUpdateProperty } from "../tabs/transact.js";
6
- import { renderExpressionEditor } from "../ui/expression-editor.js";
5
+ import { activeTab } from "../workspace/workspace";
6
+ import { transactDoc, mutateUpdateProperty } from "../tabs/transact";
7
+ import { renderExpressionEditor } from "../ui/expression-editor";
8
+
9
+ import type { JxPrototypeDef } from "@jxsuite/schema/types";
7
10
 
8
11
  export const EVENT_NAMES = [
9
12
  "onclick",
@@ -19,28 +22,29 @@ export const EVENT_NAMES = [
19
22
  ];
20
23
 
21
24
  /** @param {{ isCustomElementDoc: () => boolean }} helpers */
22
- export function eventsSidebarTemplate(helpers) {
25
+ export function eventsSidebarTemplate(helpers: { isCustomElementDoc: () => boolean }) {
23
26
  const { isCustomElementDoc } = helpers;
24
27
  const tab = activeTab.value;
25
28
  const selection = tab?.session.selection;
26
29
  const document = tab?.doc.document;
27
30
  if (!selection) return html`<div class="empty-state">Select an element to edit events</div>`;
28
- const node = getNodeAtPath(document, selection);
31
+ const node = getNodeAtPath(document!, selection);
29
32
  if (!node) return html`<div class="empty-state">Node not found</div>`;
30
33
 
31
- const defs = document.state || {};
34
+ const defs = document!.state || {};
32
35
  const functionDefs = Object.entries(defs).filter(
33
- ([, d]) => d.$prototype === "Function" || d.$handler,
36
+ ([, d]) =>
37
+ (d as JxPrototypeDef)?.$prototype === "Function" || (d as Record<string, unknown>)?.$handler,
34
38
  );
35
39
 
36
40
  // Declared CEM events (custom element docs)
37
- /** @type {unknown} */
38
- let declaredEventsT = nothing;
41
+ let declaredEventsT: unknown = nothing;
39
42
  if (isCustomElementDoc()) {
40
- const allEmits = [];
43
+ const allEmits: Record<string, unknown>[] = [];
41
44
  for (const [fnName, d] of Object.entries(defs)) {
42
- if (Array.isArray(d.emits)) {
43
- for (const ev of d.emits) allEmits.push({ ...ev, _fn: fnName });
45
+ if (Array.isArray((d as Record<string, unknown>).emits)) {
46
+ for (const ev of (d as Record<string, unknown>).emits as Record<string, unknown>[])
47
+ allEmits.push({ ...ev, _fn: fnName });
44
48
  }
45
49
  }
46
50
  if (allEmits.length > 0) {
@@ -52,7 +56,11 @@ export function eventsSidebarTemplate(helpers) {
52
56
  <div class="declared-event-row" title=${ev.description || ""}>
53
57
  <code class="event-code">${ev.name || "(unnamed)"}</code>
54
58
  <span class="event-source">← ${ev._fn}</span>
55
- ${ev.type?.text ? html`<span class="event-type">${ev.type.text}</span>` : nothing}
59
+ ${(ev.type as Record<string, unknown>)?.text
60
+ ? html`<span class="event-type"
61
+ >${(ev.type as Record<string, unknown>).text}</span
62
+ >`
63
+ : nothing}
56
64
  </div>
57
65
  `,
58
66
  )}
@@ -89,8 +97,8 @@ export function eventsSidebarTemplate(helpers) {
89
97
  size="s"
90
98
  class="event-name"
91
99
  .value=${live(evKey)}
92
- @change=${(/** @type {Event} */ e) => {
93
- const newKey = /** @type {HTMLInputElement} */ (e.target).value;
100
+ @change=${(e: Event) => {
101
+ const newKey = (e.target as HTMLInputElement).value;
94
102
  if (newKey && newKey !== evKey) {
95
103
  transactDoc(activeTab.value, (t) => {
96
104
  mutateUpdateProperty(t, selection, evKey, undefined);
@@ -107,8 +115,8 @@ export function eventsSidebarTemplate(helpers) {
107
115
  size="s"
108
116
  class="event-mode"
109
117
  .value=${live(currentMode)}
110
- @change=${(/** @type {Event} */ e) => {
111
- const newMode = /** @type {HTMLInputElement} */ (e.target).value;
118
+ @change=${(e: Event) => {
119
+ const newMode = (e.target as HTMLInputElement).value;
112
120
  if (newMode === "inline") {
113
121
  transactDoc(activeTab.value, (t) =>
114
122
  mutateUpdateProperty(t, selection, evKey, {
@@ -160,11 +168,11 @@ export function eventsSidebarTemplate(helpers) {
160
168
  grows
161
169
  placeholder="// handler body"
162
170
  .value=${live(evVal.body || "")}
163
- @input=${(/** @type {Event} */ e) => {
171
+ @input=${(e: Event) => {
164
172
  transactDoc(activeTab.value, (t) =>
165
173
  mutateUpdateProperty(t, selection, evKey, {
166
174
  $prototype: "Function",
167
- body: /** @type {HTMLInputElement} */ (e.target).value,
175
+ body: (e.target as HTMLInputElement).value,
168
176
  parameters: evVal.parameters || [],
169
177
  }),
170
178
  );
@@ -192,7 +200,7 @@ export function eventsSidebarTemplate(helpers) {
192
200
  <div class="event-body-row">
193
201
  ${renderExpressionEditor(
194
202
  evVal.$expression,
195
- (/** @type {any} */ newNode) =>
203
+ (newNode: any) =>
196
204
  transactDoc(activeTab.value, (t) =>
197
205
  mutateUpdateProperty(t, selection, evKey, {
198
206
  $expression: newNode,
@@ -207,14 +215,14 @@ export function eventsSidebarTemplate(helpers) {
207
215
  size="s"
208
216
  class="event-handler"
209
217
  .value=${live(evVal.$ref || "__none__")}
210
- @change=${(/** @type {Event} */ e) => {
218
+ @change=${(e: Event) => {
211
219
  if (
212
- /** @type {HTMLInputElement} */ (e.target).value &&
213
- /** @type {HTMLInputElement} */ (e.target).value !== "__none__"
220
+ (e.target as HTMLInputElement).value &&
221
+ (e.target as HTMLInputElement).value !== "__none__"
214
222
  ) {
215
223
  transactDoc(activeTab.value, (t) =>
216
224
  mutateUpdateProperty(t, selection, evKey, {
217
- $ref: /** @type {HTMLInputElement} */ (e.target).value,
225
+ $ref: (e.target as HTMLInputElement).value,
218
226
  }),
219
227
  );
220
228
  } else {