@jxsuite/studio 0.28.2 → 0.28.4

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 (104) hide show
  1. package/dist/studio.js +86144 -83971
  2. package/dist/studio.js.map +229 -219
  3. package/package.json +5 -5
  4. package/src/browse/browse-modal.ts +9 -3
  5. package/src/browse/browse.ts +139 -82
  6. package/src/canvas/canvas-diff.ts +35 -18
  7. package/src/canvas/canvas-helpers.ts +55 -21
  8. package/src/canvas/canvas-live-render.ts +140 -89
  9. package/src/canvas/canvas-render.ts +127 -82
  10. package/src/canvas/canvas-utils.ts +68 -42
  11. package/src/canvas/nested-site-style.ts +15 -7
  12. package/src/editor/component-inline-edit.ts +90 -51
  13. package/src/editor/content-inline-edit.ts +75 -72
  14. package/src/editor/context-menu.ts +125 -71
  15. package/src/editor/convert-targets.ts +17 -13
  16. package/src/editor/convert-to-component.ts +51 -28
  17. package/src/editor/convert-to-repeater.ts +44 -19
  18. package/src/editor/inline-edit.ts +107 -52
  19. package/src/editor/inline-format.ts +128 -60
  20. package/src/editor/insertion-helper.ts +26 -14
  21. package/src/editor/shortcuts.ts +89 -43
  22. package/src/editor/slash-menu.ts +41 -26
  23. package/src/files/components.ts +9 -7
  24. package/src/files/file-ops.ts +53 -33
  25. package/src/files/files.ts +246 -143
  26. package/src/format/constraints.ts +25 -15
  27. package/src/format/format-host.ts +33 -10
  28. package/src/github/github-auth.ts +24 -14
  29. package/src/github/github-publish.ts +20 -14
  30. package/src/new-project/new-project-modal.ts +27 -18
  31. package/src/panels/activity-bar.ts +27 -26
  32. package/src/panels/ai-panel.ts +100 -44
  33. package/src/panels/block-action-bar.ts +84 -52
  34. package/src/panels/canvas-dnd.ts +47 -28
  35. package/src/panels/data-explorer.ts +24 -11
  36. package/src/panels/dnd.ts +148 -100
  37. package/src/panels/editors.ts +54 -37
  38. package/src/panels/elements-panel.ts +23 -13
  39. package/src/panels/events-panel.ts +48 -38
  40. package/src/panels/git-panel.ts +95 -60
  41. package/src/panels/head-panel.ts +138 -84
  42. package/src/panels/imports-panel.ts +66 -29
  43. package/src/panels/layers-panel.ts +80 -36
  44. package/src/panels/left-panel.ts +86 -53
  45. package/src/panels/overlays.ts +36 -19
  46. package/src/panels/panel-events.ts +48 -27
  47. package/src/panels/panel-scheduler.ts +41 -23
  48. package/src/panels/preview-render.ts +26 -26
  49. package/src/panels/properties-panel.ts +155 -118
  50. package/src/panels/pseudo-preview.ts +31 -15
  51. package/src/panels/quick-search.ts +28 -13
  52. package/src/panels/right-panel.ts +35 -24
  53. package/src/panels/shared.ts +46 -29
  54. package/src/panels/signals-panel.ts +303 -186
  55. package/src/panels/statusbar.ts +27 -12
  56. package/src/panels/style-inputs.ts +30 -24
  57. package/src/panels/style-panel.ts +130 -90
  58. package/src/panels/style-utils.ts +63 -23
  59. package/src/panels/stylebook-layers-panel.ts +27 -30
  60. package/src/panels/stylebook-panel.ts +140 -72
  61. package/src/panels/tab-strip.ts +21 -10
  62. package/src/panels/toolbar.ts +52 -40
  63. package/src/panels/welcome-screen.ts +1 -1
  64. package/src/platform.ts +2 -1
  65. package/src/platforms/devserver.ts +221 -105
  66. package/src/recent-projects.ts +15 -7
  67. package/src/resize-edges.ts +7 -5
  68. package/src/services/cem-export.ts +73 -57
  69. package/src/services/code-services.ts +52 -25
  70. package/src/services/monaco-setup.ts +5 -5
  71. package/src/settings/content-types-editor.ts +133 -62
  72. package/src/settings/css-vars-editor.ts +31 -14
  73. package/src/settings/defs-editor.ts +125 -63
  74. package/src/settings/general-settings.ts +11 -6
  75. package/src/settings/head-editor.ts +30 -15
  76. package/src/settings/schema-field-ui.ts +75 -35
  77. package/src/settings/settings-modal.ts +35 -17
  78. package/src/site-context.ts +80 -47
  79. package/src/state.ts +98 -65
  80. package/src/store.ts +42 -23
  81. package/src/studio.ts +165 -144
  82. package/src/tabs/tab.ts +51 -45
  83. package/src/tabs/transact.ts +230 -109
  84. package/src/types.ts +60 -51
  85. package/src/ui/button-group.ts +3 -2
  86. package/src/ui/color-selector.ts +33 -15
  87. package/src/ui/expression-editor.ts +139 -86
  88. package/src/ui/field-input.ts +35 -18
  89. package/src/ui/field-row.ts +1 -1
  90. package/src/ui/icons.ts +5 -6
  91. package/src/ui/layers.ts +33 -26
  92. package/src/ui/media-picker.ts +13 -7
  93. package/src/ui/panel-resize.ts +39 -20
  94. package/src/ui/spectrum.ts +4 -2
  95. package/src/ui/unit-selector.ts +20 -11
  96. package/src/ui/value-selector.ts +13 -7
  97. package/src/ui/widgets.ts +34 -18
  98. package/src/utils/canvas-media.ts +66 -33
  99. package/src/utils/edit-display.ts +43 -44
  100. package/src/utils/google-fonts.ts +10 -6
  101. package/src/utils/inherited-style.ts +22 -8
  102. package/src/utils/studio-utils.ts +88 -45
  103. package/src/view.ts +9 -5
  104. package/src/workspace/workspace.ts +49 -29
@@ -10,17 +10,18 @@ import {
10
10
  monitorForElements,
11
11
  } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
12
12
 
13
- import { elToPath, canvasPanels, getNodeAtPath, VOID_ELEMENTS, isAncestor } from "../store";
13
+ import { VOID_ELEMENTS, canvasPanels, elToPath, getNodeAtPath, isAncestor } from "../store";
14
14
  import { activeTab } from "../workspace/workspace";
15
15
  import { view } from "../view";
16
16
  import { applyDropInstruction } from "../panels/dnd";
17
17
  import { effectiveZoom } from "../canvas/canvas-helpers";
18
18
 
19
19
  import type { CanvasPanel } from "../types";
20
- export type { CanvasPanel };
21
20
 
22
21
  import type { JxPath } from "../state";
23
22
 
23
+ export type { CanvasPanel };
24
+
24
25
  interface DropInstruction {
25
26
  type: "reorder-above" | "reorder-below" | "make-child";
26
27
  }
@@ -43,8 +44,8 @@ export function registerPanelDnD(panel: CanvasPanel) {
43
44
  const allEls = canvas.querySelectorAll("*");
44
45
 
45
46
  // Drop-target callbacks fire on EVERY target in the stack (innermost → outermost),
46
- // and every canvas element is a drop target — so the indicator and the drop are
47
- // driven from the monitor using only the innermost target.
47
+ // And every canvas element is a drop target — so the indicator and the drop are
48
+ // Driven from the monitor using only the innermost target.
48
49
  /** Innermost drop target if it belongs to this panel's canvas, else null */
49
50
  const innermostCanvasTarget = (location: {
50
51
  current: {
@@ -54,22 +55,19 @@ export function registerPanelDnD(panel: CanvasPanel) {
54
55
  }[];
55
56
  };
56
57
  }) => {
57
- const target = location.current.dropTargets[0];
58
- if (!target) return null;
58
+ const [target] = location.current.dropTargets;
59
+ if (!target) {
60
+ return null;
61
+ }
59
62
  const tEl = target.element as HTMLElement;
60
63
  const tPath = target.data.path;
61
- if (!canvas.contains(tEl) || !Array.isArray(tPath)) return null;
62
- return { el: tEl, path: tPath as JxPath, isLeaf: !!target.data._isVoid };
64
+ if (!canvas.contains(tEl) || !Array.isArray(tPath)) {
65
+ return null;
66
+ }
67
+ return { el: tEl, isLeaf: Boolean(target.data._isVoid), path: tPath as JxPath };
63
68
  };
64
69
 
65
70
  const monitorCleanup = monitorForElements({
66
- onDragStart({ location }) {
67
- view.lastDragInput = location.current.input;
68
- for (const el of canvas.querySelectorAll("*")) {
69
- (el as HTMLElement).style.pointerEvents = "auto";
70
- }
71
- for (const p of canvasPanels) p.overlayClk.style.pointerEvents = "none";
72
- },
73
71
  onDrag({ location }) {
74
72
  view.lastDragInput = location.current.input;
75
73
  const target = innermostCanvasTarget(location);
@@ -81,8 +79,8 @@ export function registerPanelDnD(panel: CanvasPanel) {
81
79
  showCanvasDropIndicator(target.el, target.path, target.isLeaf, panel);
82
80
  } else if (location.current.dropTargets.length > 0) {
83
81
  // Pointer is over a non-canvas target (e.g. a layer row) — hide this panel's
84
- // indicator. When over dead space (no targets at all) keep the last indicator
85
- // visible so it persists for the whole drag.
82
+ // Indicator. When over dead space (no targets at all) keep the last indicator
83
+ // Visible so it persists for the whole drag.
86
84
  if (_activeDropEl && canvas.contains(_activeDropEl)) {
87
85
  _activeDropEl.classList.remove("canvas-drop-target");
88
86
  _activeDropEl = null;
@@ -90,6 +88,15 @@ export function registerPanelDnD(panel: CanvasPanel) {
90
88
  dropLine.style.display = "none";
91
89
  }
92
90
  },
91
+ onDragStart({ location }) {
92
+ view.lastDragInput = location.current.input;
93
+ for (const el of canvas.querySelectorAll("*")) {
94
+ (el as HTMLElement).style.pointerEvents = "auto";
95
+ }
96
+ for (const p of canvasPanels) {
97
+ p.overlayClk.style.pointerEvents = "none";
98
+ }
99
+ },
93
100
  onDrop({ source, location }) {
94
101
  const target = innermostCanvasTarget(location);
95
102
  if (target) {
@@ -103,13 +110,17 @@ export function registerPanelDnD(panel: CanvasPanel) {
103
110
  _activeDropEl?.classList.remove("canvas-drop-target");
104
111
  _activeDropEl = null;
105
112
  for (const p of canvasPanels) {
106
- if (p.dropLine) p.dropLine.style.display = "none";
113
+ if (p.dropLine) {
114
+ p.dropLine.style.display = "none";
115
+ }
107
116
  }
108
117
  view.lastDragInput = null;
109
118
  for (const el of canvas.querySelectorAll("*")) {
110
119
  (el as HTMLElement).style.pointerEvents = "none";
111
120
  }
112
- for (const p of canvasPanels) p.overlayClk.style.pointerEvents = "";
121
+ for (const p of canvasPanels) {
122
+ p.overlayClk.style.pointerEvents = "";
123
+ }
113
124
  },
114
125
  });
115
126
  view.canvasDndCleanups.push(monitorCleanup);
@@ -117,7 +128,9 @@ export function registerPanelDnD(panel: CanvasPanel) {
117
128
  const document = activeTab.value?.doc.document;
118
129
  for (const el of allEls) {
119
130
  const elPath = elToPath.get(el);
120
- if (!elPath) continue;
131
+ if (!elPath) {
132
+ continue;
133
+ }
121
134
 
122
135
  const node = getNodeAtPath(document!, elPath);
123
136
  const tag = (node?.tagName || "div").toLowerCase();
@@ -127,14 +140,16 @@ export function registerPanelDnD(panel: CanvasPanel) {
127
140
  const isLeaf = VOID_ELEMENTS.has(tag) || !hasElementChildren;
128
141
 
129
142
  const cleanup = dropTargetForElements({
130
- element: /** @type {HTMLElement} */ el,
131
143
  canDrop({ source }) {
132
144
  const srcPath = source.data.path as JxPath | undefined;
133
- if (srcPath && isAncestor(srcPath, elPath)) return false;
145
+ if (srcPath && isAncestor(srcPath, elPath)) {
146
+ return false;
147
+ }
134
148
  return true;
135
149
  },
150
+ element: /** @type {HTMLElement} */ el,
136
151
  getData() {
137
- return { path: elPath, _isVoid: isLeaf };
152
+ return { _isVoid: isLeaf, path: elPath };
138
153
  },
139
154
  });
140
155
  view.canvasDndCleanups.push(cleanup);
@@ -148,22 +163,24 @@ export function registerPanelDnD(panel: CanvasPanel) {
148
163
  * @returns {DropResult}
149
164
  */
150
165
  function getCanvasDropResult(el: HTMLElement, elPath: JxPath, isLeaf: boolean): DropResult {
151
- if (!view.lastDragInput)
166
+ if (!view.lastDragInput) {
152
167
  return {
153
168
  instruction: { type: "make-child" },
154
169
  referenceEl: el,
155
170
  targetPath: elPath,
156
171
  };
172
+ }
157
173
  const y = view.lastDragInput.clientY;
158
174
 
159
175
  if (elPath.length === 0) {
160
- const children = Array.from(el.children) as HTMLElement[];
161
- if (children.length === 0)
176
+ const children = [...el.children] as HTMLElement[];
177
+ if (children.length === 0) {
162
178
  return {
163
179
  instruction: { type: "make-child" },
164
180
  referenceEl: el,
165
181
  targetPath: elPath,
166
182
  };
183
+ }
167
184
  return nearestChildEdge(children, y, elPath);
168
185
  }
169
186
 
@@ -176,18 +193,20 @@ function getCanvasDropResult(el: HTMLElement, elPath: JxPath, isLeaf: boolean):
176
193
  return { instruction, referenceEl: el, targetPath: elPath };
177
194
  }
178
195
 
179
- if (relY < 0.25)
196
+ if (relY < 0.25) {
180
197
  return {
181
198
  instruction: { type: "reorder-above" },
182
199
  referenceEl: el,
183
200
  targetPath: elPath,
184
201
  };
185
- if (relY > 0.75)
202
+ }
203
+ if (relY > 0.75) {
186
204
  return {
187
205
  instruction: { type: "reorder-below" },
188
206
  referenceEl: el,
189
207
  targetPath: elPath,
190
208
  };
209
+ }
191
210
  return {
192
211
  instruction: { type: "make-child" },
193
212
  referenceEl: el,
@@ -3,24 +3,34 @@
3
3
 
4
4
  import { html, nothing } from "lit-html";
5
5
  import { classMap } from "lit-html/directives/class-map.js";
6
+ import type { TemplateResult } from "lit-html";
6
7
 
7
8
  /** Expanded data entries set — persists across renders. */
8
9
  const expandedDataKeys = new Set();
9
10
 
10
11
  /** Unwrap a Vue ref (has .value and .__v_isRef) to get the underlying value. */
11
12
  function unwrapSignal(value: unknown) {
12
- if (value && typeof value === "object" && (value as Record<string, unknown>).__v_isRef)
13
+ if (value && typeof value === "object" && (value as Record<string, unknown>).__v_isRef) {
13
14
  return (value as Record<string, unknown>).value;
15
+ }
14
16
  return value;
15
17
  }
16
18
 
17
19
  /** Type label for a signal value in the data explorer. */
18
20
  function dataTypeLabel(value: unknown) {
19
21
  const v = unwrapSignal(value);
20
- if (v === null) return "null";
21
- if (v === undefined) return "pending";
22
- if (Array.isArray(v)) return `Array(${v.length})`;
23
- if (typeof v === "object") return `{${Object.keys(v).length}}`;
22
+ if (v === null) {
23
+ return "null";
24
+ }
25
+ if (v === undefined) {
26
+ return "pending";
27
+ }
28
+ if (Array.isArray(v)) {
29
+ return `Array(${v.length})`;
30
+ }
31
+ if (typeof v === "object") {
32
+ return `{${Object.keys(v).length}}`;
33
+ }
24
34
  return typeof v;
25
35
  }
26
36
 
@@ -82,8 +92,11 @@ export function renderDataExplorerTemplate(
82
92
  expanded: isExpanded,
83
93
  })}
84
94
  @click=${() => {
85
- if (expandedDataKeys.has(name)) expandedDataKeys.delete(name);
86
- else expandedDataKeys.add(name);
95
+ if (expandedDataKeys.has(name)) {
96
+ expandedDataKeys.delete(name);
97
+ } else {
98
+ expandedDataKeys.add(name);
99
+ }
87
100
  renderLeftPanel();
88
101
  }}
89
102
  >
@@ -91,8 +104,8 @@ export function renderDataExplorerTemplate(
91
104
  <span class="data-name">${name}</span>
92
105
  <span
93
106
  class=${classMap({
94
- "data-type": true,
95
107
  "data-pending": unwrapped === null,
108
+ "data-type": true,
96
109
  })}
97
110
  >${dataTypeLabel(value)}</span
98
111
  >
@@ -115,7 +128,7 @@ export function renderDataTreeTemplate(
115
128
  value: unknown,
116
129
  depth: number,
117
130
  maxDepth = 5,
118
- ): import("lit-html").TemplateResult {
131
+ ): TemplateResult {
119
132
  const indent = `${(depth + 1) * 12}px`;
120
133
 
121
134
  if (depth > maxDepth) {
@@ -140,7 +153,7 @@ export function renderDataTreeTemplate(
140
153
 
141
154
  if (Array.isArray(value)) {
142
155
  const cap = 20;
143
- const items: import("lit-html").TemplateResult[] = value.slice(0, cap).map((item, i) => {
156
+ const items: TemplateResult[] = value.slice(0, cap).map((item, i) => {
144
157
  if (item === null || item === undefined || typeof item !== "object") {
145
158
  const valText =
146
159
  typeof item === "string" && item.length > 80
@@ -171,7 +184,7 @@ export function renderDataTreeTemplate(
171
184
  const obj = value as Record<string, unknown>;
172
185
  const keys = Object.keys(obj);
173
186
  const cap = 30;
174
- const items: import("lit-html").TemplateResult[] = keys.slice(0, cap).map((key) => {
187
+ const items: TemplateResult[] = keys.slice(0, cap).map((key) => {
175
188
  const v = obj[key];
176
189
  if (v === null || v === undefined || typeof v !== "object") {
177
190
  const valText =