@jxsuite/studio 0.32.0 → 0.34.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/iframe-entry.js +6230 -0
- package/dist/iframe-entry.js.map +35 -0
- package/dist/studio.js +22791 -13709
- package/dist/studio.js.map +181 -74
- package/package.json +12 -7
- package/src/browse/browse.ts +11 -4
- package/src/canvas/canvas-helpers.ts +2 -56
- package/src/canvas/canvas-live-render.ts +102 -435
- package/src/canvas/canvas-origin.ts +66 -0
- package/src/canvas/canvas-patcher.ts +63 -403
- package/src/canvas/canvas-render.ts +70 -212
- package/src/canvas/canvas-utils.ts +37 -65
- package/src/canvas/iframe-channel.ts +154 -0
- package/src/canvas/iframe-drop.ts +484 -0
- package/src/canvas/iframe-entry.ts +600 -0
- package/src/canvas/iframe-host.ts +1373 -0
- package/src/canvas/iframe-inline-edit.ts +367 -0
- package/src/canvas/iframe-insert.ts +164 -0
- package/src/canvas/iframe-interaction.ts +176 -0
- package/src/canvas/iframe-keys.ts +85 -0
- package/src/canvas/iframe-overlay.ts +218 -0
- package/src/canvas/iframe-patch.ts +363 -0
- package/src/canvas/iframe-protocol.ts +361 -0
- package/src/canvas/iframe-render.ts +458 -0
- package/src/canvas/iframe-slash.ts +114 -0
- package/src/canvas/iframe-subtree.ts +113 -0
- package/src/canvas/path-mapping.ts +86 -0
- package/src/canvas/serialize-scope.ts +65 -0
- package/src/editor/canvas-context-menu.ts +40 -0
- package/src/editor/canvas-slash-bridge.ts +21 -0
- package/src/editor/context-menu.ts +2 -1
- package/src/editor/inline-edit-apply.ts +183 -0
- package/src/editor/inline-edit.ts +99 -21
- package/src/editor/inline-link.ts +89 -0
- package/src/editor/insert-zone-action.ts +35 -0
- package/src/editor/merge-tags.ts +26 -2
- package/src/editor/repeater-scope.ts +144 -0
- package/src/editor/shortcuts.ts +14 -28
- package/src/editor/slash-menu.ts +73 -42
- package/src/files/files.ts +2 -1
- package/src/page-params.ts +383 -0
- package/src/panels/ai-panel.ts +386 -328
- package/src/panels/block-action-bar.ts +296 -138
- package/src/panels/canvas-dnd-bridge.ts +397 -0
- package/src/panels/component-preview.ts +56 -0
- package/src/panels/dnd.ts +41 -17
- package/src/panels/drag-ghost.ts +62 -0
- package/src/panels/editors.ts +1 -1
- package/src/panels/overlays.ts +10 -125
- package/src/panels/properties-panel.ts +210 -0
- package/src/panels/right-panel.ts +0 -2
- package/src/panels/signals-panel.ts +136 -22
- package/src/panels/stylebook-doc.ts +373 -0
- package/src/panels/stylebook-panel.ts +46 -689
- package/src/panels/tab-bar.ts +159 -13
- package/src/panels/toolbar.ts +3 -2
- package/src/platforms/devserver.ts +18 -47
- package/src/services/ai-settings.ts +107 -0
- package/src/services/ai-system-prompt.ts +617 -0
- package/src/services/ai-tools.ts +854 -0
- package/src/services/context-manager.ts +200 -0
- package/src/services/document-assistant.ts +183 -0
- package/src/services/jx-validate.ts +65 -0
- package/src/services/monaco-setup.ts +12 -0
- package/src/services/render-critic.ts +75 -0
- package/src/services/token-lint.ts +140 -0
- package/src/services/tool-executor.ts +156 -0
- package/src/settings/css-vars-editor.ts +2 -2
- package/src/state.ts +29 -0
- package/src/store.ts +4 -62
- package/src/studio.ts +90 -40
- package/src/tabs/doc-op-apply.ts +89 -0
- package/src/tabs/patch-ops.ts +6 -2
- package/src/tabs/tab.ts +23 -4
- package/src/tabs/transact.ts +33 -69
- package/src/types.ts +16 -24
- package/src/ui/jx-theme.ts +63 -0
- package/src/ui/media-picker.ts +6 -4
- package/src/ui/spectrum.ts +5 -0
- package/src/utils/canvas-media.ts +0 -137
- package/src/utils/edit-display.ts +23 -3
- package/src/utils/geometry.ts +43 -0
- package/src/utils/link-target.ts +93 -0
- package/src/utils/strip-events.ts +54 -0
- package/src/view.ts +0 -23
- package/src/workspace/workspace.ts +14 -1
- package/src/canvas/canvas-subtree-render.ts +0 -113
- package/src/editor/component-inline-edit.ts +0 -349
- package/src/editor/content-inline-edit.ts +0 -207
- package/src/editor/insertion-helper.ts +0 -308
- package/src/panels/canvas-dnd.ts +0 -329
- package/src/panels/panel-events.ts +0 -306
- package/src/panels/preview-render.ts +0 -132
- package/src/panels/pseudo-preview.ts +0 -75
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/**
|
|
3
|
-
* Preview render — extracted from studio.js (Phase 4m). Structural preview renderer that creates
|
|
4
|
-
* DOM from Jx node trees as a fallback when runtime rendering fails.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { elToPath } from "../store";
|
|
8
|
-
import { isMappedArray, isRef } from "@jxsuite/schema/guards";
|
|
9
|
-
import { activeTab } from "../workspace/workspace";
|
|
10
|
-
import { applyCanvasStyle } from "../utils/canvas-media";
|
|
11
|
-
import { resolveDefaultForCanvas } from "../panels/signals-panel";
|
|
12
|
-
import type { JxPath } from "../state";
|
|
13
|
-
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Recursively render a Jx node to the canvas DOM. Media-aware: applies base styles + active
|
|
17
|
-
* breakpoint/feature overrides.
|
|
18
|
-
*
|
|
19
|
-
* @param {JxMutableNode | string | number | boolean | null | undefined} node
|
|
20
|
-
* @param {JxPath} path
|
|
21
|
-
* @param {HTMLElement} parent
|
|
22
|
-
* @param {Set<string>} activeBreakpoints
|
|
23
|
-
* @param {Record<string, boolean>} featureToggles
|
|
24
|
-
*/
|
|
25
|
-
export function renderCanvasNode(
|
|
26
|
-
node: JxMutableNode | string | number | boolean | null | undefined,
|
|
27
|
-
path: JxPath,
|
|
28
|
-
parent: HTMLElement,
|
|
29
|
-
activeBreakpoints: Set<string>,
|
|
30
|
-
featureToggles: Record<string, boolean>,
|
|
31
|
-
) {
|
|
32
|
-
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") {
|
|
33
|
-
parent.append(document.createTextNode(String(node)));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (!node || typeof node !== "object") {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Array pseudo-element: render as a repeater perimeter at the array's own path, with a single
|
|
41
|
-
// Template instance inside (matches the edit-mode visual).
|
|
42
|
-
if (isMappedArray(node)) {
|
|
43
|
-
const wrapper = document.createElement("div");
|
|
44
|
-
wrapper.className = "repeater-perimeter";
|
|
45
|
-
elToPath.set(wrapper, path);
|
|
46
|
-
const template = node.map;
|
|
47
|
-
if (template && typeof template === "object") {
|
|
48
|
-
renderCanvasNode(template, [...path, "map"], wrapper, activeBreakpoints, featureToggles);
|
|
49
|
-
}
|
|
50
|
-
wrapper.style.pointerEvents = "none";
|
|
51
|
-
parent.append(wrapper);
|
|
52
|
-
return wrapper;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const tag = node.tagName || "div";
|
|
56
|
-
const el = document.createElement(tag);
|
|
57
|
-
|
|
58
|
-
elToPath.set(el, path);
|
|
59
|
-
|
|
60
|
-
if (typeof node.textContent === "string") {
|
|
61
|
-
el.textContent = node.textContent;
|
|
62
|
-
} else if (isRef(node.textContent)) {
|
|
63
|
-
const tc = node.textContent;
|
|
64
|
-
const resolved = resolveDefaultForCanvas(tc, activeTab.value?.doc.document?.state);
|
|
65
|
-
el.textContent = typeof resolved === "string" ? resolved : null;
|
|
66
|
-
el.style.opacity = "0.7";
|
|
67
|
-
el.style.fontStyle = "italic";
|
|
68
|
-
el.title = `Bound: ${tc.$ref}`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (node.id) {
|
|
72
|
-
el.id = node.id;
|
|
73
|
-
}
|
|
74
|
-
if (node.className) {
|
|
75
|
-
el.className = node.className;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
applyCanvasStyle(el, node.style, activeBreakpoints, featureToggles);
|
|
79
|
-
|
|
80
|
-
if (node.attributes && typeof node.attributes === "object") {
|
|
81
|
-
for (const [attr, val] of Object.entries(node.attributes)) {
|
|
82
|
-
try {
|
|
83
|
-
if (isRef(val)) {
|
|
84
|
-
const resolved = resolveDefaultForCanvas(val, activeTab.value?.doc.document?.state);
|
|
85
|
-
el.setAttribute(attr, String(resolved ?? ""));
|
|
86
|
-
} else {
|
|
87
|
-
el.setAttribute(attr, String(val));
|
|
88
|
-
}
|
|
89
|
-
} catch {}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (Array.isArray(node.children)) {
|
|
94
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
95
|
-
renderCanvasNode(
|
|
96
|
-
node.children[i],
|
|
97
|
-
[...path, "children", i],
|
|
98
|
-
el,
|
|
99
|
-
activeBreakpoints,
|
|
100
|
-
featureToggles,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
} else if (isMappedArray(node.children)) {
|
|
104
|
-
const template = node.children.map;
|
|
105
|
-
if (template && typeof template === "object") {
|
|
106
|
-
const wrapper = document.createElement("div");
|
|
107
|
-
wrapper.className = "repeater-perimeter";
|
|
108
|
-
elToPath.set(wrapper, [...path, "children"]);
|
|
109
|
-
renderCanvasNode(
|
|
110
|
-
template,
|
|
111
|
-
[...path, "children", "map"],
|
|
112
|
-
wrapper,
|
|
113
|
-
activeBreakpoints,
|
|
114
|
-
featureToggles,
|
|
115
|
-
);
|
|
116
|
-
el.append(wrapper);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (node.$switch && node.cases && typeof node.cases === "object") {
|
|
121
|
-
const keys = Object.keys(node.cases);
|
|
122
|
-
const placeholder = document.createElement("div");
|
|
123
|
-
placeholder.textContent = `[$switch: ${keys.join(" | ")}]`;
|
|
124
|
-
placeholder.style.cssText =
|
|
125
|
-
"font-family:var(--font-mono);font-size:var(--spectrum-font-size-50,11px);padding:6px 10px;background:color-mix(in srgb, var(--danger) 8%, transparent);border:1px dashed color-mix(in srgb, var(--danger) 40%, transparent);border-radius:var(--radius);color:var(--danger);font-style:italic";
|
|
126
|
-
el.append(placeholder);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
el.style.pointerEvents = "none";
|
|
130
|
-
parent.append(el);
|
|
131
|
-
return el;
|
|
132
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/**
|
|
3
|
-
* Pseudo-state preview — extracted from studio.js (Phase 4m). When a pseudo-selector (:hover,
|
|
4
|
-
* :focus, etc.) is active in the style sidebar, force those styles onto the selected element.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { getNodeAtPath } from "../store";
|
|
8
|
-
import { getNestedStyle } from "@jxsuite/schema/guards";
|
|
9
|
-
import { activeTab } from "../workspace/workspace";
|
|
10
|
-
import { view } from "../view";
|
|
11
|
-
import { findCanvasElement, getActivePanel } from "../canvas/canvas-helpers";
|
|
12
|
-
|
|
13
|
-
import type { JxStyle } from "@jxsuite/schema/types";
|
|
14
|
-
|
|
15
|
-
const pseudoStyleHost = document.createElement("div");
|
|
16
|
-
pseudoStyleHost.style.display = "contents";
|
|
17
|
-
(document.querySelector("sp-theme") || document.body).append(pseudoStyleHost);
|
|
18
|
-
|
|
19
|
-
export function updateForcedPseudoPreview() {
|
|
20
|
-
if (view.forcedStyleTag) {
|
|
21
|
-
view.forcedStyleTag.remove();
|
|
22
|
-
view.forcedStyleTag = null;
|
|
23
|
-
}
|
|
24
|
-
if (view.forcedAttrEl) {
|
|
25
|
-
delete view.forcedAttrEl.dataset.studioForced;
|
|
26
|
-
view.forcedAttrEl = null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const tab = activeTab.value;
|
|
30
|
-
const sel = tab?.session.ui?.activeSelector;
|
|
31
|
-
if (!sel || !sel.startsWith(":") || !tab?.session.selection) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const panel = getActivePanel();
|
|
36
|
-
if (!panel) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const el = findCanvasElement(tab.session.selection, panel.canvas);
|
|
40
|
-
if (!el) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const node = getNodeAtPath(tab.doc.document, tab.session.selection);
|
|
45
|
-
if (!node?.style) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const { activeMedia } = tab.session.ui;
|
|
49
|
-
const ctx: JxStyle = activeMedia
|
|
50
|
-
? (getNestedStyle(node.style, `@${activeMedia}`) ?? {})
|
|
51
|
-
: node.style;
|
|
52
|
-
const rules = getNestedStyle(ctx, sel);
|
|
53
|
-
if (!rules) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const cssProps = Object.entries(rules)
|
|
58
|
-
.filter(([k]) => typeof rules[k] === "string" || typeof rules[k] === "number")
|
|
59
|
-
.map(
|
|
60
|
-
([k, v]) =>
|
|
61
|
-
`${k.replaceAll(/[A-Z]/g, (c: string) => `-${c.toLowerCase()}`)}: ${v} !important`,
|
|
62
|
-
)
|
|
63
|
-
.join("; ");
|
|
64
|
-
if (!cssProps) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
el.dataset.studioForced = "1";
|
|
69
|
-
view.forcedAttrEl = el;
|
|
70
|
-
|
|
71
|
-
const tag = document.createElement("style");
|
|
72
|
-
tag.textContent = `[data-studio-forced] { ${cssProps} }`;
|
|
73
|
-
pseudoStyleHost.append(tag);
|
|
74
|
-
view.forcedStyleTag = tag;
|
|
75
|
-
}
|