@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.
- package/dist/studio.js +86144 -83971
- package/dist/studio.js.map +229 -219
- package/package.json +5 -5
- package/src/browse/browse-modal.ts +9 -3
- package/src/browse/browse.ts +139 -82
- package/src/canvas/canvas-diff.ts +35 -18
- package/src/canvas/canvas-helpers.ts +55 -21
- package/src/canvas/canvas-live-render.ts +140 -89
- package/src/canvas/canvas-render.ts +127 -82
- package/src/canvas/canvas-utils.ts +68 -42
- package/src/canvas/nested-site-style.ts +15 -7
- package/src/editor/component-inline-edit.ts +90 -51
- package/src/editor/content-inline-edit.ts +75 -72
- package/src/editor/context-menu.ts +125 -71
- package/src/editor/convert-targets.ts +17 -13
- package/src/editor/convert-to-component.ts +51 -28
- package/src/editor/convert-to-repeater.ts +44 -19
- package/src/editor/inline-edit.ts +107 -52
- package/src/editor/inline-format.ts +128 -60
- package/src/editor/insertion-helper.ts +26 -14
- package/src/editor/shortcuts.ts +89 -43
- package/src/editor/slash-menu.ts +41 -26
- package/src/files/components.ts +9 -7
- package/src/files/file-ops.ts +53 -33
- package/src/files/files.ts +246 -143
- package/src/format/constraints.ts +25 -15
- package/src/format/format-host.ts +33 -10
- package/src/github/github-auth.ts +24 -14
- package/src/github/github-publish.ts +20 -14
- package/src/new-project/new-project-modal.ts +27 -18
- package/src/panels/activity-bar.ts +27 -26
- package/src/panels/ai-panel.ts +100 -44
- package/src/panels/block-action-bar.ts +84 -52
- package/src/panels/canvas-dnd.ts +47 -28
- package/src/panels/data-explorer.ts +24 -11
- package/src/panels/dnd.ts +148 -100
- package/src/panels/editors.ts +54 -37
- package/src/panels/elements-panel.ts +23 -13
- package/src/panels/events-panel.ts +48 -38
- package/src/panels/git-panel.ts +95 -60
- package/src/panels/head-panel.ts +138 -84
- package/src/panels/imports-panel.ts +66 -29
- package/src/panels/layers-panel.ts +80 -36
- package/src/panels/left-panel.ts +86 -53
- package/src/panels/overlays.ts +36 -19
- package/src/panels/panel-events.ts +48 -27
- package/src/panels/panel-scheduler.ts +41 -23
- package/src/panels/preview-render.ts +26 -26
- package/src/panels/properties-panel.ts +155 -118
- package/src/panels/pseudo-preview.ts +31 -15
- package/src/panels/quick-search.ts +28 -13
- package/src/panels/right-panel.ts +35 -24
- package/src/panels/shared.ts +46 -29
- package/src/panels/signals-panel.ts +303 -186
- package/src/panels/statusbar.ts +27 -12
- package/src/panels/style-inputs.ts +30 -24
- package/src/panels/style-panel.ts +130 -90
- package/src/panels/style-utils.ts +63 -23
- package/src/panels/stylebook-layers-panel.ts +27 -30
- package/src/panels/stylebook-panel.ts +140 -72
- package/src/panels/tab-strip.ts +21 -10
- package/src/panels/toolbar.ts +52 -40
- package/src/panels/welcome-screen.ts +1 -1
- package/src/platform.ts +2 -1
- package/src/platforms/devserver.ts +221 -105
- package/src/recent-projects.ts +15 -7
- package/src/resize-edges.ts +7 -5
- package/src/services/cem-export.ts +73 -57
- package/src/services/code-services.ts +52 -25
- package/src/services/monaco-setup.ts +5 -5
- package/src/settings/content-types-editor.ts +133 -62
- package/src/settings/css-vars-editor.ts +31 -14
- package/src/settings/defs-editor.ts +125 -63
- package/src/settings/general-settings.ts +11 -6
- package/src/settings/head-editor.ts +30 -15
- package/src/settings/schema-field-ui.ts +75 -35
- package/src/settings/settings-modal.ts +35 -17
- package/src/site-context.ts +80 -47
- package/src/state.ts +98 -65
- package/src/store.ts +42 -23
- package/src/studio.ts +165 -144
- package/src/tabs/tab.ts +51 -45
- package/src/tabs/transact.ts +230 -109
- package/src/types.ts +60 -51
- package/src/ui/button-group.ts +3 -2
- package/src/ui/color-selector.ts +33 -15
- package/src/ui/expression-editor.ts +139 -86
- package/src/ui/field-input.ts +35 -18
- package/src/ui/field-row.ts +1 -1
- package/src/ui/icons.ts +5 -6
- package/src/ui/layers.ts +33 -26
- package/src/ui/media-picker.ts +13 -7
- package/src/ui/panel-resize.ts +39 -20
- package/src/ui/spectrum.ts +4 -2
- package/src/ui/unit-selector.ts +20 -11
- package/src/ui/value-selector.ts +13 -7
- package/src/ui/widgets.ts +34 -18
- package/src/utils/canvas-media.ts +66 -33
- package/src/utils/edit-display.ts +43 -44
- package/src/utils/google-fonts.ts +10 -6
- package/src/utils/inherited-style.ts +22 -8
- package/src/utils/studio-utils.ts +88 -45
- package/src/view.ts +9 -5
- package/src/workspace/workspace.ts +49 -29
|
@@ -8,6 +8,8 @@ import { componentRegistry } from "../files/components";
|
|
|
8
8
|
|
|
9
9
|
import type { StylebookEntry } from "./stylebook-panel";
|
|
10
10
|
import type { JxStyle } from "@jxsuite/schema/types";
|
|
11
|
+
import type { TemplateResult } from "lit-html";
|
|
12
|
+
import type { ComponentEntry } from "../files/components.js";
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* @param {JxStyle} rootStyle
|
|
@@ -45,12 +47,8 @@ export function renderStylebookLayersTemplate(ctx: {
|
|
|
45
47
|
* @param {string} parentPath
|
|
46
48
|
* @returns {import("lit-html").TemplateResult}
|
|
47
49
|
*/
|
|
48
|
-
const renderEntryRow = (
|
|
49
|
-
entry
|
|
50
|
-
depth: number = 0,
|
|
51
|
-
parentPath: string = "",
|
|
52
|
-
): import("lit-html").TemplateResult => {
|
|
53
|
-
const tag = entry.tag;
|
|
50
|
+
const renderEntryRow = (entry: StylebookEntry, depth = 0, parentPath = ""): TemplateResult => {
|
|
51
|
+
const { tag } = entry;
|
|
54
52
|
const fullPath = parentPath ? `${parentPath} ${tag}` : tag;
|
|
55
53
|
const uniqueChildren = entry.children
|
|
56
54
|
? [...new Map(entry.children.map((c: StylebookEntry) => [c.tag, c])).values()]
|
|
@@ -83,7 +81,7 @@ export function renderStylebookLayersTemplate(ctx: {
|
|
|
83
81
|
`;
|
|
84
82
|
};
|
|
85
83
|
|
|
86
|
-
const elementRows:
|
|
84
|
+
const elementRows: TemplateResult[] = [];
|
|
87
85
|
for (const section of ctx.stylebookMeta.$sections) {
|
|
88
86
|
for (const entry of section.elements) {
|
|
89
87
|
elementRows.push(renderEntryRow(entry, 0));
|
|
@@ -91,7 +89,7 @@ export function renderStylebookLayersTemplate(ctx: {
|
|
|
91
89
|
}
|
|
92
90
|
const compRows = componentRegistry.map(
|
|
93
91
|
/** @param {import("../files/components.js").ComponentEntry} comp */ (
|
|
94
|
-
comp:
|
|
92
|
+
comp: ComponentEntry,
|
|
95
93
|
) => html`
|
|
96
94
|
<div
|
|
97
95
|
class=${classMap({
|
|
@@ -109,27 +107,26 @@ export function renderStylebookLayersTemplate(ctx: {
|
|
|
109
107
|
`,
|
|
110
108
|
);
|
|
111
109
|
return html`${elementRows}${compRows}`;
|
|
112
|
-
} else {
|
|
113
|
-
const style = rootStyle;
|
|
114
|
-
const vars = Object.entries(style).filter(([k]) => k.startsWith("--"));
|
|
115
|
-
if (vars.length === 0) {
|
|
116
|
-
return html`<div style="padding:16px;text-align:center;color:var(--fg-dim);font-size:12px">
|
|
117
|
-
No variables defined
|
|
118
|
-
</div>`;
|
|
119
|
-
}
|
|
120
|
-
return html`${vars.map(
|
|
121
|
-
([k, v]) => html`
|
|
122
|
-
<div class="layer-row">
|
|
123
|
-
<span class="layer-tag" style="font-size:10px;font-family:'SF Mono','Fira Code',monospace"
|
|
124
|
-
>var</span
|
|
125
|
-
>
|
|
126
|
-
<span class="layer-label">${k}</span>
|
|
127
|
-
<span
|
|
128
|
-
style="font-size:11px;color:var(--fg-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:80px"
|
|
129
|
-
>${String(v)}</span
|
|
130
|
-
>
|
|
131
|
-
</div>
|
|
132
|
-
`,
|
|
133
|
-
)}`;
|
|
134
110
|
}
|
|
111
|
+
const style = rootStyle;
|
|
112
|
+
const vars = Object.entries(style).filter(([k]) => k.startsWith("--"));
|
|
113
|
+
if (vars.length === 0) {
|
|
114
|
+
return html`<div style="padding:16px;text-align:center;color:var(--fg-dim);font-size:12px">
|
|
115
|
+
No variables defined
|
|
116
|
+
</div>`;
|
|
117
|
+
}
|
|
118
|
+
return html`${vars.map(
|
|
119
|
+
([k, v]) => html`
|
|
120
|
+
<div class="layer-row">
|
|
121
|
+
<span class="layer-tag" style="font-size:10px;font-family:'SF Mono','Fira Code',monospace"
|
|
122
|
+
>var</span
|
|
123
|
+
>
|
|
124
|
+
<span class="layer-label">${k}</span>
|
|
125
|
+
<span
|
|
126
|
+
style="font-size:11px;color:var(--fg-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:80px"
|
|
127
|
+
>${String(v)}</span
|
|
128
|
+
>
|
|
129
|
+
</div>
|
|
130
|
+
`,
|
|
131
|
+
)}`;
|
|
135
132
|
}
|
|
@@ -12,22 +12,25 @@ import { styleMap } from "lit-html/directives/style-map.js";
|
|
|
12
12
|
import { live } from "lit-html/directives/live.js";
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
|
-
updateSession,
|
|
16
|
-
updateUi,
|
|
17
|
-
canvasWrap,
|
|
18
15
|
canvasPanels,
|
|
16
|
+
canvasWrap,
|
|
19
17
|
elToPath,
|
|
20
18
|
projectState,
|
|
19
|
+
updateSession,
|
|
20
|
+
updateUi,
|
|
21
21
|
} from "../store";
|
|
22
22
|
import { activeTab } from "../workspace/workspace";
|
|
23
23
|
import { view } from "../view";
|
|
24
24
|
import { defineElement, setSkipServerFunctions } from "@jxsuite/runtime";
|
|
25
25
|
import { componentRegistry } from "../files/components";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import type { ComponentEntry } from "../files/components";
|
|
27
|
+
import { getEffectiveMedia, getEffectiveStyle } from "../site-context";
|
|
28
|
+
import { activeBreakpointsForWidth, parseMediaEntries } from "../utils/canvas-media";
|
|
28
29
|
import { mediaDisplayName } from "./shared";
|
|
29
30
|
import { panToCanvasEl } from "../canvas/canvas-utils";
|
|
30
31
|
import stylebookMeta from "../../data/stylebook-meta.json";
|
|
32
|
+
import type { TemplateResult } from "lit-html";
|
|
33
|
+
import type { CanvasPanel } from "../types";
|
|
31
34
|
|
|
32
35
|
export interface StylebookEntry {
|
|
33
36
|
tag: string;
|
|
@@ -56,7 +59,7 @@ interface StylebookCtx {
|
|
|
56
59
|
label: string | null,
|
|
57
60
|
fullWidth: boolean,
|
|
58
61
|
width?: number | null,
|
|
59
|
-
) => { tpl:
|
|
62
|
+
) => { tpl: TemplateResult; panel: CanvasPanel };
|
|
60
63
|
applyTransform: () => void;
|
|
61
64
|
observeCenterUntilStable: () => void;
|
|
62
65
|
renderZoomIndicator: () => void;
|
|
@@ -64,7 +67,7 @@ interface StylebookCtx {
|
|
|
64
67
|
overlayBoxDescriptor: (
|
|
65
68
|
el: Element,
|
|
66
69
|
type: string,
|
|
67
|
-
panel:
|
|
70
|
+
panel: CanvasPanel,
|
|
68
71
|
) => {
|
|
69
72
|
cls: string;
|
|
70
73
|
top: string;
|
|
@@ -75,13 +78,6 @@ interface StylebookCtx {
|
|
|
75
78
|
effectiveZoom: () => number;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
interface ComponentEntry {
|
|
79
|
-
source?: string;
|
|
80
|
-
tagName: string;
|
|
81
|
-
path?: string;
|
|
82
|
-
props?: Array<{ name: string; default?: string }>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
81
|
export { stylebookMeta };
|
|
86
82
|
|
|
87
83
|
/**
|
|
@@ -95,7 +91,9 @@ function _resolveNestedStyle(style: Record<string, unknown>, tagPath: string) {
|
|
|
95
91
|
const parts = tagPath.split(" ");
|
|
96
92
|
let obj = style;
|
|
97
93
|
for (const part of parts) {
|
|
98
|
-
if (!obj || typeof obj !== "object")
|
|
94
|
+
if (!obj || typeof obj !== "object") {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
99
97
|
obj = obj[part] as Record<string, unknown>;
|
|
100
98
|
}
|
|
101
99
|
return obj && typeof obj === "object" ? (obj as Record<string, unknown>) : null;
|
|
@@ -154,8 +152,8 @@ export function renderStylebookMode(ctx: StylebookCtx) {
|
|
|
154
152
|
/>
|
|
155
153
|
<button
|
|
156
154
|
class=${classMap({
|
|
155
|
+
active: Boolean(tab?.session.ui.stylebookCustomizedOnly),
|
|
157
156
|
"tb-toggle": true,
|
|
158
|
-
active: !!tab?.session.ui.stylebookCustomizedOnly,
|
|
159
157
|
})}
|
|
160
158
|
@click=${onCustomizedToggle}
|
|
161
159
|
>
|
|
@@ -171,17 +169,17 @@ export function renderStylebookMode(ctx: StylebookCtx) {
|
|
|
171
169
|
const allPanelDefs = [];
|
|
172
170
|
if (hasMedia) {
|
|
173
171
|
allPanelDefs.push({
|
|
174
|
-
|
|
172
|
+
activeSet: activeBreakpointsForWidth(sizeBreakpoints, baseWidth),
|
|
175
173
|
displayName: mediaDisplayName("--"),
|
|
174
|
+
name: "base",
|
|
176
175
|
width: baseWidth,
|
|
177
|
-
activeSet: activeBreakpointsForWidth(sizeBreakpoints, baseWidth),
|
|
178
176
|
});
|
|
179
177
|
for (const bp of sizeBreakpoints) {
|
|
180
178
|
allPanelDefs.push({
|
|
181
|
-
|
|
179
|
+
activeSet: activeBreakpointsForWidth(sizeBreakpoints, bp.width),
|
|
182
180
|
displayName: mediaDisplayName(bp.name),
|
|
181
|
+
name: bp.name,
|
|
183
182
|
width: bp.width,
|
|
184
|
-
activeSet: activeBreakpointsForWidth(sizeBreakpoints, bp.width),
|
|
185
183
|
});
|
|
186
184
|
}
|
|
187
185
|
}
|
|
@@ -219,12 +217,12 @@ export function renderStylebookMode(ctx: StylebookCtx) {
|
|
|
219
217
|
!hasBaseWidth,
|
|
220
218
|
hasBaseWidth ? baseWidth : undefined,
|
|
221
219
|
);
|
|
222
|
-
panelEntries = [{
|
|
220
|
+
panelEntries = [{ activeSet: new Set<string>(), panel: entry.panel, tpl: entry.tpl }];
|
|
223
221
|
} else {
|
|
224
222
|
panelEntries = allPanelDefs.map((def) => {
|
|
225
223
|
const label = `${def.displayName} (${def.width}px)`;
|
|
226
224
|
const { tpl, panel } = ctx.canvasPanelTemplate(def.name, label, false, def.width);
|
|
227
|
-
return {
|
|
225
|
+
return { activeSet: def.activeSet, panel, tpl };
|
|
228
226
|
});
|
|
229
227
|
}
|
|
230
228
|
|
|
@@ -235,7 +233,9 @@ export function renderStylebookMode(ctx: StylebookCtx) {
|
|
|
235
233
|
class="panzoom-wrap"
|
|
236
234
|
style="transform-origin:0 0;padding-top:40px"
|
|
237
235
|
${ref((el) => {
|
|
238
|
-
if (el)
|
|
236
|
+
if (el) {
|
|
237
|
+
view.panzoomWrap = el as HTMLDivElement;
|
|
238
|
+
}
|
|
239
239
|
})}
|
|
240
240
|
>
|
|
241
241
|
${panelEntries.map((e) => e.tpl)}
|
|
@@ -260,7 +260,9 @@ export function renderStylebookMode(ctx: StylebookCtx) {
|
|
|
260
260
|
/** Fast-path: re-apply styles to existing stylebook elements without rebuilding the DOM. */
|
|
261
261
|
export function refreshStylebookStyles() {
|
|
262
262
|
const tab = activeTab.value;
|
|
263
|
-
if (!tab)
|
|
263
|
+
if (!tab) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
264
266
|
const rootStyle = getEffectiveStyle(tab.doc.document?.style);
|
|
265
267
|
|
|
266
268
|
for (const panel of canvasPanels) {
|
|
@@ -281,11 +283,13 @@ export function refreshStylebookStyles() {
|
|
|
281
283
|
const allEls = canvas.querySelectorAll("*");
|
|
282
284
|
for (const el of allEls) {
|
|
283
285
|
const tag = view.stylebookElToTag.get(el);
|
|
284
|
-
if (!tag)
|
|
286
|
+
if (!tag) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
285
289
|
const htmlEl = el as HTMLElement;
|
|
286
290
|
// Determine if it's a compound selector (e.g. "ul li") or simple tag
|
|
287
291
|
const parts = tag.split(" ");
|
|
288
|
-
const leafTag = parts
|
|
292
|
+
const leafTag = parts.at(-1);
|
|
289
293
|
const entry = _entryByTag.get(leafTag);
|
|
290
294
|
|
|
291
295
|
// Reset to base style
|
|
@@ -304,9 +308,13 @@ export function refreshStylebookStyles() {
|
|
|
304
308
|
// Media overrides nested in tag style
|
|
305
309
|
if (activeBreakpoints.size > 0) {
|
|
306
310
|
for (const [key, val] of Object.entries(tagStyle)) {
|
|
307
|
-
if (!key.startsWith("@") || typeof val !== "object" || val === null)
|
|
311
|
+
if (!key.startsWith("@") || typeof val !== "object" || val === null) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
308
314
|
const mediaName = key.slice(1);
|
|
309
|
-
if (mediaName === "--")
|
|
315
|
+
if (mediaName === "--") {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
310
318
|
if (activeBreakpoints.has(mediaName)) {
|
|
311
319
|
for (const [prop, v] of Object.entries(val as Record<string, unknown>)) {
|
|
312
320
|
if (typeof v === "string" || typeof v === "number") {
|
|
@@ -322,9 +330,13 @@ export function refreshStylebookStyles() {
|
|
|
322
330
|
// Top-level @media keys
|
|
323
331
|
if (activeBreakpoints.size > 0) {
|
|
324
332
|
for (const [key, val] of Object.entries(rootStyle)) {
|
|
325
|
-
if (!key.startsWith("@") || typeof val !== "object" || val === null)
|
|
333
|
+
if (!key.startsWith("@") || typeof val !== "object" || val === null) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
326
336
|
const mediaName = key.slice(1);
|
|
327
|
-
if (mediaName === "--")
|
|
337
|
+
if (mediaName === "--") {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
328
340
|
if (activeBreakpoints.has(mediaName)) {
|
|
329
341
|
const mediaTagStyle = _resolveNestedStyle(
|
|
330
342
|
/** @type {Record<string, unknown>} */ val,
|
|
@@ -358,9 +370,9 @@ export function selectStylebookTag(tag: string, media?: string | null, { panCanv
|
|
|
358
370
|
updateSession({
|
|
359
371
|
selection: [],
|
|
360
372
|
ui: {
|
|
361
|
-
stylebookSelection: tag,
|
|
362
|
-
rightTab: "style",
|
|
363
373
|
activeSelector: tag,
|
|
374
|
+
rightTab: "style",
|
|
375
|
+
stylebookSelection: tag,
|
|
364
376
|
...(media !== undefined ? { activeMedia: media } : {}),
|
|
365
377
|
},
|
|
366
378
|
});
|
|
@@ -368,14 +380,20 @@ export function selectStylebookTag(tag: string, media?: string | null, { panCanv
|
|
|
368
380
|
|
|
369
381
|
if (tag && panCanvas && canvasPanels.length > 0) {
|
|
370
382
|
const el = findStylebookEl(canvasPanels[0].canvas, tag);
|
|
371
|
-
if (el)
|
|
383
|
+
if (el) {
|
|
384
|
+
panToCanvasEl(el);
|
|
385
|
+
}
|
|
372
386
|
}
|
|
373
387
|
}
|
|
374
388
|
|
|
375
389
|
/** Draw selection + hover overlays for stylebook elements */
|
|
376
390
|
export function renderStylebookOverlays() {
|
|
377
|
-
if (!_ctx)
|
|
378
|
-
|
|
391
|
+
if (!_ctx) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (canvasPanels.length === 0) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
379
397
|
|
|
380
398
|
const selectedTag = activeTab.value?.session.ui.stylebookSelection;
|
|
381
399
|
|
|
@@ -395,20 +413,22 @@ export function renderStylebookOverlays() {
|
|
|
395
413
|
|
|
396
414
|
if (hoverTag && hoverTag !== selectedTag) {
|
|
397
415
|
const el = findStylebookEl(panel.canvas, hoverTag);
|
|
398
|
-
if (el)
|
|
416
|
+
if (el) {
|
|
399
417
|
boxes.push({
|
|
400
418
|
..._ctx.overlayBoxDescriptor(el, "hover", panel),
|
|
401
419
|
label: undefined,
|
|
402
420
|
});
|
|
421
|
+
}
|
|
403
422
|
}
|
|
404
423
|
|
|
405
424
|
if (selectedTag) {
|
|
406
425
|
const el = findStylebookEl(panel.canvas, selectedTag);
|
|
407
|
-
if (el)
|
|
426
|
+
if (el) {
|
|
408
427
|
boxes.push({
|
|
409
428
|
..._ctx.overlayBoxDescriptor(el, "selection", panel),
|
|
410
429
|
label: `<${selectedTag}>`,
|
|
411
430
|
});
|
|
431
|
+
}
|
|
412
432
|
}
|
|
413
433
|
|
|
414
434
|
litRender(
|
|
@@ -419,10 +439,10 @@ export function renderStylebookOverlays() {
|
|
|
419
439
|
<div
|
|
420
440
|
class=${b.cls}
|
|
421
441
|
style=${styleMap({
|
|
422
|
-
|
|
442
|
+
height: b.height,
|
|
423
443
|
left: b.left,
|
|
444
|
+
top: b.top,
|
|
424
445
|
width: b.width,
|
|
425
|
-
height: b.height,
|
|
426
446
|
})}
|
|
427
447
|
>
|
|
428
448
|
${b.label ? html`<div class="overlay-label">${b.label}</div>` : nothing}
|
|
@@ -452,7 +472,9 @@ export function buildStylebookElement(
|
|
|
452
472
|
parentTag: string | null = null,
|
|
453
473
|
) {
|
|
454
474
|
const el = document.createElement(entry.tag);
|
|
455
|
-
if (entry.text)
|
|
475
|
+
if (entry.text) {
|
|
476
|
+
el.textContent = entry.text;
|
|
477
|
+
}
|
|
456
478
|
if (entry.attributes) {
|
|
457
479
|
for (const [k, v] of Object.entries(entry.attributes)) {
|
|
458
480
|
try {
|
|
@@ -460,7 +482,9 @@ export function buildStylebookElement(
|
|
|
460
482
|
} catch {}
|
|
461
483
|
}
|
|
462
484
|
}
|
|
463
|
-
if (entry.style)
|
|
485
|
+
if (entry.style) {
|
|
486
|
+
el.style.cssText = entry.style;
|
|
487
|
+
}
|
|
464
488
|
const compoundTag = parentTag && parentTag !== entry.tag ? `${parentTag} ${entry.tag}` : null;
|
|
465
489
|
const tagStyle =
|
|
466
490
|
(compoundTag && _resolveNestedStyle(rootStyle, compoundTag)) ||
|
|
@@ -476,9 +500,13 @@ export function buildStylebookElement(
|
|
|
476
500
|
if (activeBreakpoints) {
|
|
477
501
|
// Check media overrides nested inside the tag style (selector wraps media)
|
|
478
502
|
for (const [key, val] of Object.entries(tagStyle)) {
|
|
479
|
-
if (!key.startsWith("@") || typeof val !== "object" || val === null)
|
|
503
|
+
if (!key.startsWith("@") || typeof val !== "object" || val === null) {
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
480
506
|
const mediaName = key.slice(1);
|
|
481
|
-
if (mediaName === "--")
|
|
507
|
+
if (mediaName === "--") {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
482
510
|
if (activeBreakpoints.has(mediaName)) {
|
|
483
511
|
for (const [prop, v] of Object.entries(val as Record<string, unknown>)) {
|
|
484
512
|
if (typeof v === "string" || typeof v === "number") {
|
|
@@ -495,9 +523,13 @@ export function buildStylebookElement(
|
|
|
495
523
|
if (activeBreakpoints) {
|
|
496
524
|
const tagPath = compoundTag || entry.tag;
|
|
497
525
|
for (const [key, val] of Object.entries(rootStyle)) {
|
|
498
|
-
if (!key.startsWith("@") || typeof val !== "object" || val === null)
|
|
526
|
+
if (!key.startsWith("@") || typeof val !== "object" || val === null) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
499
529
|
const mediaName = key.slice(1);
|
|
500
|
-
if (mediaName === "--")
|
|
530
|
+
if (mediaName === "--") {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
501
533
|
if (activeBreakpoints.has(mediaName)) {
|
|
502
534
|
const mediaTagStyle = _resolveNestedStyle(val as Record<string, unknown>, tagPath);
|
|
503
535
|
if (mediaTagStyle && typeof mediaTagStyle === "object") {
|
|
@@ -514,7 +546,7 @@ export function buildStylebookElement(
|
|
|
514
546
|
}
|
|
515
547
|
if (entry.children) {
|
|
516
548
|
for (const child of entry.children) {
|
|
517
|
-
el.
|
|
549
|
+
el.append(buildStylebookElement(child, rootStyle, activeBreakpoints, entry.tag));
|
|
518
550
|
}
|
|
519
551
|
}
|
|
520
552
|
return el;
|
|
@@ -539,19 +571,19 @@ export async function renderComponentPreview(comp: ComponentEntry) {
|
|
|
539
571
|
return _componentFallback(comp.tagName);
|
|
540
572
|
}
|
|
541
573
|
const root = projectState?.projectRoot;
|
|
542
|
-
const url = `${location.origin}/${root ? root
|
|
574
|
+
const url = `${location.origin}/${root ? `${root}/` : ""}${comp.path}`;
|
|
543
575
|
await defineElement(url);
|
|
544
576
|
}
|
|
545
577
|
const el = document.createElement(comp.tagName);
|
|
546
578
|
for (const p of comp.props || []) {
|
|
547
579
|
if (p.default !== undefined && p.default !== "false" && p.default !== "''") {
|
|
548
|
-
const val = String(p.default).
|
|
580
|
+
const val = String(p.default).replaceAll(/^'|'$/g, "");
|
|
549
581
|
el.setAttribute(p.name, val);
|
|
550
582
|
}
|
|
551
583
|
}
|
|
552
584
|
return el;
|
|
553
|
-
} catch (
|
|
554
|
-
console.warn("Component preview failed:", comp.tagName,
|
|
585
|
+
} catch (error) {
|
|
586
|
+
console.warn("Component preview failed:", comp.tagName, error);
|
|
555
587
|
return _componentFallback(comp.tagName);
|
|
556
588
|
}
|
|
557
589
|
}
|
|
@@ -571,11 +603,17 @@ function _componentFallback(tagName: string) {
|
|
|
571
603
|
*/
|
|
572
604
|
function hasTagStyle(rootStyle: Record<string, unknown>, tag: string) {
|
|
573
605
|
const s = _resolveNestedStyle(rootStyle, tag);
|
|
574
|
-
if (s && typeof s === "object" && Object.keys(s).length > 0)
|
|
606
|
+
if (s && typeof s === "object" && Object.keys(s).length > 0) {
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
575
609
|
for (const [key, val] of Object.entries(rootStyle)) {
|
|
576
|
-
if (!key.startsWith("@") || typeof val !== "object" || val === null)
|
|
610
|
+
if (!key.startsWith("@") || typeof val !== "object" || val === null) {
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
577
613
|
const ms = _resolveNestedStyle(val as Record<string, unknown>, tag);
|
|
578
|
-
if (ms && typeof ms === "object" && Object.keys(ms).length > 0)
|
|
614
|
+
if (ms && typeof ms === "object" && Object.keys(ms).length > 0) {
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
579
617
|
}
|
|
580
618
|
return false;
|
|
581
619
|
}
|
|
@@ -600,7 +638,7 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
600
638
|
}
|
|
601
639
|
}
|
|
602
640
|
|
|
603
|
-
const sectionTemplates:
|
|
641
|
+
const sectionTemplates: TemplateResult[] = [];
|
|
604
642
|
|
|
605
643
|
for (const section of stylebookMeta.$sections) {
|
|
606
644
|
let entries = section.elements as StylebookEntry[];
|
|
@@ -613,7 +651,9 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
613
651
|
if (customizedOnly) {
|
|
614
652
|
entries = entries.filter((e: StylebookEntry) => hasTagStyle(rootStyle, e.tag));
|
|
615
653
|
}
|
|
616
|
-
if (entries.length === 0)
|
|
654
|
+
if (entries.length === 0) {
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
617
657
|
|
|
618
658
|
const cardTemplates = entries.map((entry: StylebookEntry) => {
|
|
619
659
|
const el = buildStylebookElement(entry, rootStyle, activeBreakpoints);
|
|
@@ -621,7 +661,9 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
621
661
|
<div
|
|
622
662
|
class="element-card"
|
|
623
663
|
${ref((card) => {
|
|
624
|
-
if (!card)
|
|
664
|
+
if (!card) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
625
667
|
view.stylebookElToTag.set(card, entry.tag);
|
|
626
668
|
elToPath.set(card, ["__sb", entry.tag]);
|
|
627
669
|
for (const child of el.querySelectorAll("*")) {
|
|
@@ -639,7 +681,7 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
639
681
|
${ref((c) => {
|
|
640
682
|
if (c) {
|
|
641
683
|
c.textContent = "";
|
|
642
|
-
c.
|
|
684
|
+
c.append(el);
|
|
643
685
|
}
|
|
644
686
|
})}
|
|
645
687
|
></div>
|
|
@@ -659,10 +701,12 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
659
701
|
// Custom components from registry
|
|
660
702
|
if (componentRegistry.length > 0) {
|
|
661
703
|
let comps = componentRegistry;
|
|
662
|
-
if (filter)
|
|
704
|
+
if (filter) {
|
|
663
705
|
comps = comps.filter((c: ComponentEntry) => c.tagName.toLowerCase().includes(filter));
|
|
664
|
-
|
|
706
|
+
}
|
|
707
|
+
if (customizedOnly) {
|
|
665
708
|
comps = comps.filter((c: ComponentEntry) => hasTagStyle(rootStyle, c.tagName));
|
|
709
|
+
}
|
|
666
710
|
if (comps.length > 0) {
|
|
667
711
|
const compCards = comps.map((comp: ComponentEntry) => {
|
|
668
712
|
let previewEl: HTMLDivElement | null = null;
|
|
@@ -671,7 +715,9 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
671
715
|
class="element-card"
|
|
672
716
|
style="display:inline-flex;width:auto"
|
|
673
717
|
${ref((card) => {
|
|
674
|
-
if (!card)
|
|
718
|
+
if (!card) {
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
675
721
|
view.stylebookElToTag.set(card, comp.tagName);
|
|
676
722
|
elToPath.set(card, ["__sb", comp.tagName]);
|
|
677
723
|
})}
|
|
@@ -679,7 +725,9 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
679
725
|
<div
|
|
680
726
|
class="element-card-preview"
|
|
681
727
|
${ref((c) => {
|
|
682
|
-
if (c)
|
|
728
|
+
if (c) {
|
|
729
|
+
previewEl = c as HTMLDivElement;
|
|
730
|
+
}
|
|
683
731
|
})}
|
|
684
732
|
></div>
|
|
685
733
|
<div class="element-card-label"><${comp.tagName}></div>
|
|
@@ -687,7 +735,9 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
687
735
|
`;
|
|
688
736
|
renderComponentPreview(comp)
|
|
689
737
|
.then((el) => {
|
|
690
|
-
if (previewEl)
|
|
738
|
+
if (previewEl) {
|
|
739
|
+
previewEl.append(el);
|
|
740
|
+
}
|
|
691
741
|
})
|
|
692
742
|
.catch(() => {});
|
|
693
743
|
return cardTpl;
|
|
@@ -726,41 +776,55 @@ function registerStylebookPanelEvents(panel: StylebookPanel) {
|
|
|
726
776
|
|
|
727
777
|
overlayClk.addEventListener("click", (e: MouseEvent) => {
|
|
728
778
|
const els = canvas.querySelectorAll("*");
|
|
729
|
-
for (const el of els)
|
|
779
|
+
for (const el of els) {
|
|
780
|
+
(el as HTMLElement).style.pointerEvents = "auto";
|
|
781
|
+
}
|
|
730
782
|
overlayClk.style.display = "none";
|
|
731
783
|
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
732
784
|
overlayClk.style.display = "";
|
|
733
|
-
for (const el of els)
|
|
785
|
+
for (const el of els) {
|
|
786
|
+
(el as HTMLElement).style.pointerEvents = "none";
|
|
787
|
+
}
|
|
734
788
|
|
|
735
789
|
for (const el of elements) {
|
|
736
|
-
if (!canvas.contains(el) || el === canvas)
|
|
790
|
+
if (!canvas.contains(el) || el === canvas) {
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
737
793
|
let cur = el as Element | null;
|
|
738
794
|
while (cur && cur !== canvas) {
|
|
739
795
|
const tag = view.stylebookElToTag.get(cur);
|
|
740
796
|
if (tag) {
|
|
741
797
|
const newMedia = panel.mediaName === "base" ? null : (panel.mediaName ?? null);
|
|
742
798
|
selectStylebookTag(tag, newMedia);
|
|
743
|
-
if (_ctx)
|
|
799
|
+
if (_ctx) {
|
|
800
|
+
_ctx.updateActivePanelHeaders();
|
|
801
|
+
}
|
|
744
802
|
return;
|
|
745
803
|
}
|
|
746
804
|
cur = cur.parentElement;
|
|
747
805
|
}
|
|
748
806
|
}
|
|
749
|
-
updateSession({ ui: {
|
|
807
|
+
updateSession({ ui: { activeSelector: null, stylebookSelection: null } });
|
|
750
808
|
renderStylebookOverlays();
|
|
751
809
|
});
|
|
752
810
|
|
|
753
811
|
overlayClk.addEventListener("mousemove", (e: MouseEvent) => {
|
|
754
812
|
const els = canvas.querySelectorAll("*");
|
|
755
|
-
for (const el of els)
|
|
813
|
+
for (const el of els) {
|
|
814
|
+
(el as HTMLElement).style.pointerEvents = "auto";
|
|
815
|
+
}
|
|
756
816
|
overlayClk.style.display = "none";
|
|
757
817
|
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
758
818
|
overlayClk.style.display = "";
|
|
759
|
-
for (const el of els)
|
|
819
|
+
for (const el of els) {
|
|
820
|
+
(el as HTMLElement).style.pointerEvents = "none";
|
|
821
|
+
}
|
|
760
822
|
|
|
761
823
|
let hoverTag = null;
|
|
762
824
|
for (const el of elements) {
|
|
763
|
-
if (!canvas.contains(el) || el === canvas)
|
|
825
|
+
if (!canvas.contains(el) || el === canvas) {
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
764
828
|
let cur = el as Element | null;
|
|
765
829
|
while (cur && cur !== canvas) {
|
|
766
830
|
const tag = view.stylebookElToTag.get(cur);
|
|
@@ -770,7 +834,9 @@ function registerStylebookPanelEvents(panel: StylebookPanel) {
|
|
|
770
834
|
}
|
|
771
835
|
cur = cur.parentElement;
|
|
772
836
|
}
|
|
773
|
-
if (hoverTag)
|
|
837
|
+
if (hoverTag) {
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
774
840
|
}
|
|
775
841
|
|
|
776
842
|
if (hoverTag !== panel._lastHoverTag) {
|
|
@@ -783,7 +849,9 @@ function registerStylebookPanelEvents(panel: StylebookPanel) {
|
|
|
783
849
|
/** Find a stylebook element by tag in the canvas */
|
|
784
850
|
function findStylebookEl(canvasEl: HTMLElement, tag: string) {
|
|
785
851
|
for (const child of canvasEl.querySelectorAll("*")) {
|
|
786
|
-
if (view.stylebookElToTag.get(child) === tag)
|
|
852
|
+
if (view.stylebookElToTag.get(child) === tag) {
|
|
853
|
+
return child as HTMLElement;
|
|
854
|
+
}
|
|
787
855
|
}
|
|
788
856
|
return null;
|
|
789
857
|
}
|