@jxsuite/studio 0.19.0 → 0.20.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 (93) hide show
  1. package/dist/studio.css +98 -98
  2. package/dist/studio.js +12577 -12183
  3. package/dist/studio.js.map +146 -144
  4. package/dist/workers/editor.worker.js +79 -79
  5. package/dist/workers/json.worker.js +109 -109
  6. package/dist/workers/ts.worker.js +82 -82
  7. package/package.json +17 -6
  8. package/src/browse/browse.js +25 -19
  9. package/src/canvas/canvas-diff.js +24 -16
  10. package/src/canvas/canvas-helpers.js +24 -19
  11. package/src/canvas/canvas-live-render.js +94 -39
  12. package/src/canvas/canvas-render.js +119 -73
  13. package/src/canvas/canvas-utils.js +38 -15
  14. package/src/canvas/nested-site-style.js +50 -0
  15. package/src/editor/component-inline-edit.js +14 -13
  16. package/src/editor/content-inline-edit.js +22 -10
  17. package/src/editor/context-menu.js +1 -1
  18. package/src/editor/convert-to-component.js +12 -10
  19. package/src/editor/inline-edit.js +66 -28
  20. package/src/editor/insertion-helper.js +16 -12
  21. package/src/editor/shortcuts.js +4 -2
  22. package/src/editor/slash-menu.js +6 -4
  23. package/src/files/components.js +1 -1
  24. package/src/files/file-ops.js +37 -16
  25. package/src/files/files.js +78 -52
  26. package/src/github/github-auth.js +122 -0
  27. package/src/github/github-publish.js +115 -0
  28. package/src/markdown/md-convert.js +172 -107
  29. package/src/new-project/new-project-modal.js +204 -0
  30. package/src/panels/activity-bar.js +22 -20
  31. package/src/panels/ai-panel.js +399 -0
  32. package/src/panels/block-action-bar.js +5 -5
  33. package/src/panels/canvas-dnd.js +8 -2
  34. package/src/panels/data-explorer.js +19 -13
  35. package/src/panels/dnd.js +144 -92
  36. package/src/panels/editors.js +55 -35
  37. package/src/panels/elements-panel.js +33 -19
  38. package/src/panels/events-panel.js +15 -10
  39. package/src/panels/git-panel.js +469 -98
  40. package/src/panels/head-panel.js +121 -81
  41. package/src/panels/imports-panel.js +88 -64
  42. package/src/panels/layers-panel.js +64 -43
  43. package/src/panels/left-panel.js +85 -47
  44. package/src/panels/overlays.js +1 -0
  45. package/src/panels/panel-events.js +45 -30
  46. package/src/panels/preview-render.js +23 -18
  47. package/src/panels/properties-panel.js +365 -249
  48. package/src/panels/pseudo-preview.js +2 -2
  49. package/src/panels/quick-search.js +7 -5
  50. package/src/panels/right-panel.js +26 -2
  51. package/src/panels/shared.js +4 -4
  52. package/src/panels/signals-panel.js +295 -166
  53. package/src/panels/statusbar.js +4 -4
  54. package/src/panels/style-inputs.js +67 -35
  55. package/src/panels/style-panel.js +233 -132
  56. package/src/panels/style-utils.js +34 -16
  57. package/src/panels/stylebook-layers-panel.js +12 -10
  58. package/src/panels/stylebook-panel.js +134 -66
  59. package/src/panels/toolbar.js +333 -109
  60. package/src/panels/welcome-screen.js +121 -0
  61. package/src/platform.js +2 -4
  62. package/src/platforms/devserver.js +113 -7
  63. package/src/resize-edges.js +98 -0
  64. package/src/services/cem-export.js +12 -7
  65. package/src/services/code-services.js +30 -12
  66. package/src/settings/content-types-editor.js +7 -7
  67. package/src/settings/css-vars-editor.js +30 -24
  68. package/src/settings/defs-editor.js +12 -7
  69. package/src/settings/general-settings.js +85 -3
  70. package/src/settings/head-editor.js +30 -24
  71. package/src/settings/schema-field-ui.js +58 -39
  72. package/src/site-context.js +41 -31
  73. package/src/state.js +70 -29
  74. package/src/store.js +21 -26
  75. package/src/studio.js +103 -81
  76. package/src/tabs/tab.js +67 -43
  77. package/src/tabs/transact.js +23 -13
  78. package/src/ui/button-group.js +24 -24
  79. package/src/ui/color-selector.js +28 -23
  80. package/src/ui/field-row.js +3 -3
  81. package/src/ui/icons.js +2 -2
  82. package/src/ui/media-picker.js +7 -7
  83. package/src/ui/spectrum.js +5 -1
  84. package/src/ui/unit-selector.js +18 -16
  85. package/src/ui/value-selector.js +21 -15
  86. package/src/ui/widgets.js +22 -19
  87. package/src/utils/canvas-media.js +5 -4
  88. package/src/utils/edit-display.js +31 -20
  89. package/src/utils/google-fonts.js +11 -11
  90. package/src/utils/inherited-style.js +9 -8
  91. package/src/utils/studio-utils.js +7 -7
  92. package/src/view.js +58 -1
  93. package/src/workspace/workspace.js +10 -7
@@ -34,7 +34,7 @@ export function updateForcedPseudoPreview() {
34
34
  const node = getNodeAtPath(tab.doc.document, tab.session.selection);
35
35
  if (!node?.style) return;
36
36
  const activeMedia = tab.session.ui.activeMedia;
37
- /** @type {any} */
37
+ /** @type {JxStyle} */
38
38
  const ctx = activeMedia ? node.style[`@${activeMedia}`] || {} : node.style;
39
39
  const rules = ctx[sel];
40
40
  if (!rules || typeof rules !== "object") return;
@@ -43,7 +43,7 @@ export function updateForcedPseudoPreview() {
43
43
  .filter(([k]) => typeof rules[k] === "string" || typeof rules[k] === "number")
44
44
  .map(
45
45
  ([k, v]) =>
46
- `${k.replace(/[A-Z]/g, (/** @type {any} */ c) => `-${c.toLowerCase()}`)}: ${v} !important`,
46
+ `${k.replace(/[A-Z]/g, (/** @type {string} */ c) => `-${c.toLowerCase()}`)}: ${v} !important`,
47
47
  )
48
48
  .join("; ");
49
49
  if (!cssProps) return;
@@ -8,7 +8,7 @@ import { getLayerSlot } from "../ui/layers.js";
8
8
 
9
9
  let _open = false;
10
10
  let _query = "";
11
- /** @type {any[]} */
11
+ /** @type {{ path: string; name?: string }[]} */
12
12
  let _results = [];
13
13
  let _selectedIndex = 0;
14
14
  let _debounceTimer = 0;
@@ -60,7 +60,9 @@ async function doSearch(/** @type {string} */ query) {
60
60
  function onInput(/** @type {Event} */ e) {
61
61
  _query = /** @type {HTMLInputElement} */ (e.target).value;
62
62
  clearTimeout(_debounceTimer);
63
- _debounceTimer = /** @type {any} */ (setTimeout(() => doSearch(_query), 150));
63
+ _debounceTimer = /** @type {number} */ (
64
+ /** @type {unknown} */ (setTimeout(() => doSearch(_query), 150))
65
+ );
64
66
  renderOverlay();
65
67
  }
66
68
 
@@ -88,10 +90,10 @@ function onKeydown(/** @type {KeyboardEvent} */ e) {
88
90
  }
89
91
  }
90
92
 
91
- function selectItem(/** @type {any} */ item) {
93
+ function selectItem(/** @type {{ path: string; name?: string }} */ item) {
92
94
  closeQuickSearch();
93
95
  const path = item.path;
94
- trackRecentFile({ path, name: path.split("/").pop() });
96
+ trackRecentFile({ path, name: path.split("/").pop() || "" });
95
97
  openFileInTab(path);
96
98
  }
97
99
 
@@ -156,7 +158,7 @@ function renderOverlay() {
156
158
  }}
157
159
  >
158
160
  <span class="quick-search-icon"
159
- >${fileIcon(item.name || item.path.split("/").pop())}</span
161
+ >${fileIcon(item.name || item.path.split("/").pop() || "")}</span
160
162
  >
161
163
  <span class="quick-search-name">${item.name || item.path.split("/").pop()}</span>
162
164
  <span class="quick-search-path">${dirPart(item.path)}</span>
@@ -15,6 +15,12 @@ import { isCustomElementDoc } from "./signals-panel.js";
15
15
  import { isColorPopoverOpen } from "../ui/color-selector.js";
16
16
  import { renderStylePanelTemplate } from "./style-panel.js";
17
17
  import { renderPropertiesPanelTemplate } from "./properties-panel.js";
18
+ import {
19
+ renderAiPanelTemplate,
20
+ mountAiPanel,
21
+ mountQuikChat,
22
+ registerRightPanelRender,
23
+ } from "./ai-panel.js";
18
24
 
19
25
  /**
20
26
  * @typedef {{
@@ -41,6 +47,8 @@ let _scheduled = false;
41
47
  */
42
48
  export function mount(ctx) {
43
49
  _ctx = ctx;
50
+ mountAiPanel();
51
+ registerRightPanelRender(render);
44
52
  _scope = effectScope();
45
53
  _scope.run(() => {
46
54
  effect(() => {
@@ -113,6 +121,7 @@ function _flush() {
113
121
  } finally {
114
122
  _rendering = false;
115
123
  }
124
+ requestAnimationFrame(() => mountQuikChat());
116
125
  _ctx.updateForcedPseudoPreview();
117
126
  }
118
127
 
@@ -120,7 +129,14 @@ function rightPanelTemplate() {
120
129
  const ctx = /** @type {RightPanelCtx} */ (_ctx);
121
130
  const aTab = activeTab.value;
122
131
  if (!aTab) return nothing;
123
- const S = /** @type {any} */ ({
132
+ const S = /**
133
+ * @type {{
134
+ * ui: Record<string, unknown>;
135
+ * document: JxMutableNode;
136
+ * mode: string;
137
+ * selection: (string | number)[] | null;
138
+ * }}
139
+ */ ({
124
140
  ui: aTab.session.ui,
125
141
  document: aTab.doc.document,
126
142
  mode: aTab.doc.mode,
@@ -132,6 +148,7 @@ function rightPanelTemplate() {
132
148
  { value: "properties", icon: "sp-icon-properties", label: "Properties" },
133
149
  { value: "events", icon: "sp-icon-event", label: "Events" },
134
150
  { value: "style", icon: "sp-icon-brush", label: "Style" },
151
+ { value: "assistant", icon: "sp-icon-chat", label: "Assistant" },
135
152
  ];
136
153
 
137
154
  const tabsT = html`
@@ -171,10 +188,17 @@ function rightPanelTemplate() {
171
188
  } catch (/** @type {unknown} */ e) {
172
189
  console.error("[renderStylePanelTemplate]", e);
173
190
  }
191
+ } else if (tab === "assistant") {
192
+ bodyT = renderAiPanelTemplate();
174
193
  }
175
194
 
176
195
  return html`
177
196
  ${tabsT}
178
- <div class="panel-body">${bodyT}</div>
197
+ <div
198
+ class="panel-body"
199
+ style=${tab === "assistant" ? "display:flex;flex-direction:column;overflow:hidden" : ""}
200
+ >
201
+ ${bodyT}
202
+ </div>
179
203
  `;
180
204
  }
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Convert a $media key like "--tablet" to a friendly display name "Tablet". "--" returns "Base".
8
8
  *
9
- * @param {any} name
9
+ * @param {string} name
10
10
  */
11
11
  export function mediaDisplayName(name) {
12
12
  if (name === "--") return "Base";
@@ -14,7 +14,7 @@ export function mediaDisplayName(name) {
14
14
  name
15
15
  .replace(/^--/, "")
16
16
  .replace(/-/g, " ")
17
- .replace(/\b\w/g, (/** @type {any} */ c) => c.toUpperCase()) || name
17
+ .replace(/\b\w/g, (/** @type {string} */ c) => c.toUpperCase()) || name
18
18
  );
19
19
  }
20
20
 
@@ -23,10 +23,10 @@ export const unsafeTags = new Set(["script", "style", "link", "iframe", "object"
23
23
  /**
24
24
  * Generate a sensible default Jx node for a given tag name.
25
25
  *
26
- * @param {any} tag
26
+ * @param {string} tag
27
27
  */
28
28
  export function defaultDef(tag) {
29
- /** @type {any} */
29
+ /** @type {JxMutableNode} */
30
30
  const def = { tagName: tag };
31
31
  if (/^h[1-6]$/.test(tag)) def.textContent = "Heading";
32
32
  else if (tag === "p") def.textContent = "Paragraph text";