@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.
- package/dist/studio.css +98 -98
- package/dist/studio.js +12577 -12183
- package/dist/studio.js.map +146 -144
- package/dist/workers/editor.worker.js +79 -79
- package/dist/workers/json.worker.js +109 -109
- package/dist/workers/ts.worker.js +82 -82
- package/package.json +17 -6
- package/src/browse/browse.js +25 -19
- package/src/canvas/canvas-diff.js +24 -16
- package/src/canvas/canvas-helpers.js +24 -19
- package/src/canvas/canvas-live-render.js +94 -39
- package/src/canvas/canvas-render.js +119 -73
- package/src/canvas/canvas-utils.js +38 -15
- package/src/canvas/nested-site-style.js +50 -0
- package/src/editor/component-inline-edit.js +14 -13
- package/src/editor/content-inline-edit.js +22 -10
- package/src/editor/context-menu.js +1 -1
- package/src/editor/convert-to-component.js +12 -10
- package/src/editor/inline-edit.js +66 -28
- package/src/editor/insertion-helper.js +16 -12
- package/src/editor/shortcuts.js +4 -2
- package/src/editor/slash-menu.js +6 -4
- package/src/files/components.js +1 -1
- package/src/files/file-ops.js +37 -16
- package/src/files/files.js +78 -52
- package/src/github/github-auth.js +122 -0
- package/src/github/github-publish.js +115 -0
- package/src/markdown/md-convert.js +172 -107
- package/src/new-project/new-project-modal.js +204 -0
- package/src/panels/activity-bar.js +22 -20
- package/src/panels/ai-panel.js +399 -0
- package/src/panels/block-action-bar.js +5 -5
- package/src/panels/canvas-dnd.js +8 -2
- package/src/panels/data-explorer.js +19 -13
- package/src/panels/dnd.js +144 -92
- package/src/panels/editors.js +55 -35
- package/src/panels/elements-panel.js +33 -19
- package/src/panels/events-panel.js +15 -10
- package/src/panels/git-panel.js +469 -98
- package/src/panels/head-panel.js +121 -81
- package/src/panels/imports-panel.js +88 -64
- package/src/panels/layers-panel.js +64 -43
- package/src/panels/left-panel.js +85 -47
- package/src/panels/overlays.js +1 -0
- package/src/panels/panel-events.js +45 -30
- package/src/panels/preview-render.js +23 -18
- package/src/panels/properties-panel.js +365 -249
- package/src/panels/pseudo-preview.js +2 -2
- package/src/panels/quick-search.js +7 -5
- package/src/panels/right-panel.js +26 -2
- package/src/panels/shared.js +4 -4
- package/src/panels/signals-panel.js +295 -166
- package/src/panels/statusbar.js +4 -4
- package/src/panels/style-inputs.js +67 -35
- package/src/panels/style-panel.js +233 -132
- package/src/panels/style-utils.js +34 -16
- package/src/panels/stylebook-layers-panel.js +12 -10
- package/src/panels/stylebook-panel.js +134 -66
- package/src/panels/toolbar.js +333 -109
- package/src/panels/welcome-screen.js +121 -0
- package/src/platform.js +2 -4
- package/src/platforms/devserver.js +113 -7
- package/src/resize-edges.js +98 -0
- package/src/services/cem-export.js +12 -7
- package/src/services/code-services.js +30 -12
- package/src/settings/content-types-editor.js +7 -7
- package/src/settings/css-vars-editor.js +30 -24
- package/src/settings/defs-editor.js +12 -7
- package/src/settings/general-settings.js +85 -3
- package/src/settings/head-editor.js +30 -24
- package/src/settings/schema-field-ui.js +58 -39
- package/src/site-context.js +41 -31
- package/src/state.js +70 -29
- package/src/store.js +21 -26
- package/src/studio.js +103 -81
- package/src/tabs/tab.js +67 -43
- package/src/tabs/transact.js +23 -13
- package/src/ui/button-group.js +24 -24
- package/src/ui/color-selector.js +28 -23
- package/src/ui/field-row.js +3 -3
- package/src/ui/icons.js +2 -2
- package/src/ui/media-picker.js +7 -7
- package/src/ui/spectrum.js +5 -1
- package/src/ui/unit-selector.js +18 -16
- package/src/ui/value-selector.js +21 -15
- package/src/ui/widgets.js +22 -19
- package/src/utils/canvas-media.js +5 -4
- package/src/utils/edit-display.js +31 -20
- package/src/utils/google-fonts.js +11 -11
- package/src/utils/inherited-style.js +9 -8
- package/src/utils/studio-utils.js +7 -7
- package/src/view.js +58 -1
- package/src/workspace/workspace.js +10 -7
|
@@ -9,8 +9,8 @@ import cssMeta from "../../data/css-meta.json";
|
|
|
9
9
|
let cssInitialMap = new Map();
|
|
10
10
|
|
|
11
11
|
/** Initialise cssInitialMap from webdata — call once during bootstrap. */
|
|
12
|
-
export function initCssData(/** @type {
|
|
13
|
-
cssInitialMap = new Map(/** @type {
|
|
12
|
+
export function initCssData(/** @type {{ cssProps: string[][] }} */ webdata) {
|
|
13
|
+
cssInitialMap = new Map(/** @type {[string, string][]} */ (webdata.cssProps));
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** Get the CSS initial-value map (populated by initCssData). */
|
|
@@ -20,28 +20,33 @@ export function getCssInitialMap() {
|
|
|
20
20
|
|
|
21
21
|
// ─── Condition helpers ──────────────────────────────────────────────────────
|
|
22
22
|
|
|
23
|
-
/** @param {
|
|
23
|
+
/** @param {{ prop: string; values: string[] }} cond @param {Record<string, unknown>} styles */
|
|
24
24
|
export function conditionPasses(cond, styles) {
|
|
25
|
-
const val = styles[cond.prop] ?? "";
|
|
25
|
+
const val = /** @type {string} */ (styles[cond.prop] ?? "");
|
|
26
26
|
if (cond.values.length === 0) return val !== "" && val !== "initial";
|
|
27
27
|
return cond.values.includes(val);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* @param {{ $show?: { prop: string; values: string[] }[] }} entry @param {Record<string, unknown>}
|
|
32
|
+
* styles
|
|
33
|
+
*/
|
|
31
34
|
export function allConditionsPass(entry, styles) {
|
|
32
|
-
return (entry.$show ?? []).every((/** @type {
|
|
35
|
+
return (entry.$show ?? []).every((/** @type {{ prop: string; values: string[] }} */ c) =>
|
|
36
|
+
conditionPasses(c, styles),
|
|
37
|
+
);
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
// ─── Auto-open sections ─────────────────────────────────────────────────────
|
|
36
41
|
|
|
37
|
-
/** @param {
|
|
42
|
+
/** @param {JxMutableNode} node @param {Record<string, boolean>} currentSections */
|
|
38
43
|
export function autoOpenSections(node, currentSections) {
|
|
39
44
|
const style = node.style || {};
|
|
40
45
|
const result = { ...currentSections };
|
|
41
46
|
for (const prop of Object.keys(style)) {
|
|
42
47
|
if (typeof style[prop] === "object") continue;
|
|
43
|
-
const entry = /** @type {Record<string,
|
|
44
|
-
const section = entry?.$section ?? "other";
|
|
48
|
+
const entry = /** @type {Record<string, Record<string, unknown>>} */ (cssMeta.$defs)[prop];
|
|
49
|
+
const section = /** @type {string} */ (entry?.$section) ?? "other";
|
|
45
50
|
if (!result[section]) result[section] = true;
|
|
46
51
|
}
|
|
47
52
|
return result;
|
|
@@ -50,21 +55,34 @@ export function autoOpenSections(node, currentSections) {
|
|
|
50
55
|
// ─── Shorthand expand/compress ──────────────────────────────────────────────
|
|
51
56
|
|
|
52
57
|
/** Get longhands for a shorthand property from css-meta */
|
|
53
|
-
export function getLonghands(/** @type {
|
|
54
|
-
const entry = /** @type {Record<string,
|
|
58
|
+
export function getLonghands(/** @type {string} */ shorthandProp) {
|
|
59
|
+
const entry = /** @type {Record<string, Record<string, unknown>>} */ (cssMeta.$defs)[
|
|
60
|
+
shorthandProp
|
|
61
|
+
];
|
|
55
62
|
if (entry?.$longhands) {
|
|
56
|
-
return entry.$longhands
|
|
63
|
+
return /** @type {string[]} */ (entry.$longhands)
|
|
57
64
|
.map((/** @type {string} */ name) => ({
|
|
58
65
|
name,
|
|
59
|
-
entry: /** @type {Record<string,
|
|
66
|
+
entry: /** @type {Record<string, Record<string, unknown>>} */ (cssMeta.$defs)[name] || {
|
|
67
|
+
$order: 0,
|
|
68
|
+
},
|
|
60
69
|
}))
|
|
61
|
-
.sort(
|
|
70
|
+
.sort(
|
|
71
|
+
(
|
|
72
|
+
/** @type {{ entry: Record<string, unknown> }} */ a,
|
|
73
|
+
/** @type {{ entry: Record<string, unknown> }} */ b,
|
|
74
|
+
) => /** @type {number} */ (a.entry.$order) - /** @type {number} */ (b.entry.$order),
|
|
75
|
+
);
|
|
62
76
|
}
|
|
63
77
|
const result = [];
|
|
64
|
-
for (const [name, e] of /** @type {[string,
|
|
78
|
+
for (const [name, e] of /** @type {[string, Record<string, unknown>][]} */ (
|
|
79
|
+
Object.entries(cssMeta.$defs)
|
|
80
|
+
)) {
|
|
65
81
|
if (e.$shorthand === shorthandProp) result.push({ name, entry: e });
|
|
66
82
|
}
|
|
67
|
-
result.sort(
|
|
83
|
+
result.sort(
|
|
84
|
+
(a, b) => /** @type {number} */ (a.entry.$order) - /** @type {number} */ (b.entry.$order),
|
|
85
|
+
);
|
|
68
86
|
return result;
|
|
69
87
|
}
|
|
70
88
|
|
|
@@ -5,8 +5,10 @@ import { classMap } from "lit-html/directives/class-map.js";
|
|
|
5
5
|
import { activeTab } from "../workspace/workspace.js";
|
|
6
6
|
import { componentRegistry } from "../files/components.js";
|
|
7
7
|
|
|
8
|
+
/** @typedef {import("./stylebook-panel.js").StylebookEntry} StylebookEntry */
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
|
-
* @param {
|
|
11
|
+
* @param {JxStyle} rootStyle
|
|
10
12
|
* @param {string} tag
|
|
11
13
|
*/
|
|
12
14
|
function hasTagStyle(rootStyle, tag) {
|
|
@@ -21,7 +23,7 @@ function hasTagStyle(rootStyle, tag) {
|
|
|
21
23
|
* media?: string | null,
|
|
22
24
|
* opts?: { panCanvas?: boolean },
|
|
23
25
|
* ) => void;
|
|
24
|
-
* stylebookMeta:
|
|
26
|
+
* stylebookMeta: { $sections: { label: string; elements: StylebookEntry[] }[] };
|
|
25
27
|
* }} ctx
|
|
26
28
|
* @returns {import("lit-html").TemplateResult}
|
|
27
29
|
*/
|
|
@@ -33,22 +35,22 @@ export function renderStylebookLayersTemplate(ctx) {
|
|
|
33
35
|
|
|
34
36
|
if (tab?.session.ui.stylebookTab === "elements") {
|
|
35
37
|
/**
|
|
36
|
-
* @param {
|
|
38
|
+
* @param {StylebookEntry} entry
|
|
37
39
|
* @param {number} depth
|
|
38
40
|
* @param {string} parentPath
|
|
39
|
-
* @returns {
|
|
41
|
+
* @returns {import("lit-html").TemplateResult}
|
|
40
42
|
*/
|
|
41
43
|
const renderEntryRow = (entry, depth = 0, parentPath = "") => {
|
|
42
44
|
const tag = entry.tag;
|
|
43
45
|
const fullPath = parentPath ? `${parentPath} ${tag}` : tag;
|
|
44
46
|
const uniqueChildren = entry.children
|
|
45
|
-
? [...new Map(entry.children.map((/** @type {
|
|
47
|
+
? [...new Map(entry.children.map((/** @type {StylebookEntry} */ c) => [c.tag, c])).values()]
|
|
46
48
|
: [];
|
|
47
49
|
return html`
|
|
48
50
|
<div
|
|
49
51
|
class=${classMap({ "layer-row": true, selected: tag === selectedLeaf })}
|
|
50
52
|
style="padding-left:${8 + depth * 16}px"
|
|
51
|
-
@click=${(/** @type {
|
|
53
|
+
@click=${(/** @type {MouseEvent} */ e) => {
|
|
52
54
|
e.stopPropagation();
|
|
53
55
|
ctx.selectStylebookTag(fullPath, undefined, { panCanvas: true });
|
|
54
56
|
}}
|
|
@@ -65,21 +67,21 @@ export function renderStylebookLayersTemplate(ctx) {
|
|
|
65
67
|
></span>`
|
|
66
68
|
: nothing}
|
|
67
69
|
</div>
|
|
68
|
-
${uniqueChildren.map((/** @type {
|
|
70
|
+
${uniqueChildren.map((/** @type {StylebookEntry} */ child) =>
|
|
69
71
|
renderEntryRow(child, depth + 1, fullPath),
|
|
70
72
|
)}
|
|
71
73
|
`;
|
|
72
74
|
};
|
|
73
75
|
|
|
74
|
-
/** @type {
|
|
76
|
+
/** @type {import("lit-html").TemplateResult[]} */
|
|
75
77
|
const elementRows = [];
|
|
76
78
|
for (const section of ctx.stylebookMeta.$sections) {
|
|
77
|
-
for (const entry of
|
|
79
|
+
for (const entry of section.elements) {
|
|
78
80
|
elementRows.push(renderEntryRow(entry, 0));
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
const compRows = componentRegistry.map(
|
|
82
|
-
/** @param {
|
|
84
|
+
/** @param {import("../files/components.js").ComponentEntry} comp */ (comp) => html`
|
|
83
85
|
<div
|
|
84
86
|
class=${classMap({ "layer-row": true, selected: comp.tagName === selectedTag })}
|
|
85
87
|
@click=${() => ctx.selectStylebookTag(comp.tagName, undefined, { panCanvas: true })}
|
|
@@ -29,30 +29,76 @@ import stylebookMeta from "../../data/stylebook-meta.json";
|
|
|
29
29
|
|
|
30
30
|
export { stylebookMeta };
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {{
|
|
34
|
+
* tag: string;
|
|
35
|
+
* text?: string;
|
|
36
|
+
* attributes?: Record<string, string>;
|
|
37
|
+
* style?: string;
|
|
38
|
+
* children?: StylebookEntry[];
|
|
39
|
+
* }} StylebookEntry
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {{
|
|
44
|
+
* mediaName: string | null;
|
|
45
|
+
* element: HTMLElement | null;
|
|
46
|
+
* canvas: HTMLElement;
|
|
47
|
+
* overlay: HTMLElement;
|
|
48
|
+
* overlayClk: HTMLElement;
|
|
49
|
+
* viewport: HTMLElement | null;
|
|
50
|
+
* scrollContainer: HTMLElement | null;
|
|
51
|
+
* dropLine: HTMLElement | null;
|
|
52
|
+
* _width: number | null;
|
|
53
|
+
* _lastHoverTag?: string | null;
|
|
54
|
+
* }} StylebookPanel
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {{
|
|
59
|
+
* canvasPanelTemplate: Function;
|
|
60
|
+
* applyTransform: Function;
|
|
61
|
+
* observeCenterUntilStable: Function;
|
|
62
|
+
* renderZoomIndicator: Function;
|
|
63
|
+
* updateActivePanelHeaders: Function;
|
|
64
|
+
* overlayBoxDescriptor: Function;
|
|
65
|
+
* effectiveZoom: Function;
|
|
66
|
+
* }} StylebookCtx
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {{
|
|
71
|
+
* source?: string;
|
|
72
|
+
* tagName: string;
|
|
73
|
+
* path?: string;
|
|
74
|
+
* props?: Array<{ name: string; default?: string }>;
|
|
75
|
+
* }} ComponentEntry
|
|
76
|
+
*/
|
|
77
|
+
|
|
32
78
|
/**
|
|
33
79
|
* Resolve a nested tag path in a style object. e.g., "table th" → style["table"]["th"]
|
|
34
80
|
*
|
|
35
|
-
* @param {Record<string,
|
|
81
|
+
* @param {Record<string, unknown>} style
|
|
36
82
|
* @param {string} tagPath
|
|
37
|
-
* @returns {Record<string,
|
|
83
|
+
* @returns {Record<string, unknown> | null}
|
|
38
84
|
*/
|
|
39
85
|
function _resolveNestedStyle(style, tagPath) {
|
|
40
86
|
const parts = tagPath.split(" ");
|
|
41
87
|
let obj = style;
|
|
42
88
|
for (const part of parts) {
|
|
43
89
|
if (!obj || typeof obj !== "object") return null;
|
|
44
|
-
obj = obj[part];
|
|
90
|
+
obj = /** @type {Record<string, unknown>} */ (obj[part]);
|
|
45
91
|
}
|
|
46
|
-
return obj && typeof obj === "object" ? /** @type {Record<string,
|
|
92
|
+
return obj && typeof obj === "object" ? /** @type {Record<string, unknown>} */ (obj) : null;
|
|
47
93
|
}
|
|
48
94
|
|
|
49
|
-
/** @type {
|
|
95
|
+
/** @type {StylebookCtx | null} */
|
|
50
96
|
let _ctx = null;
|
|
51
97
|
|
|
52
98
|
/** Lookup: tag → entry from stylebookMeta (built once) */
|
|
53
99
|
const _entryByTag = new Map();
|
|
54
100
|
for (const section of stylebookMeta.$sections) {
|
|
55
|
-
for (const entry of /** @type {
|
|
101
|
+
for (const entry of /** @type {StylebookEntry[]} */ (section.elements)) {
|
|
56
102
|
_entryByTag.set(entry.tag, entry);
|
|
57
103
|
}
|
|
58
104
|
}
|
|
@@ -60,15 +106,7 @@ for (const section of stylebookMeta.$sections) {
|
|
|
60
106
|
/**
|
|
61
107
|
* Render the stylebook/settings mode into the canvas.
|
|
62
108
|
*
|
|
63
|
-
* @param {
|
|
64
|
-
* canvasPanelTemplate: Function;
|
|
65
|
-
* applyTransform: Function;
|
|
66
|
-
* observeCenterUntilStable: Function;
|
|
67
|
-
* renderZoomIndicator: Function;
|
|
68
|
-
* updateActivePanelHeaders: Function;
|
|
69
|
-
* overlayBoxDescriptor: Function;
|
|
70
|
-
* effectiveZoom: Function;
|
|
71
|
-
* }} ctx
|
|
109
|
+
* @param {StylebookCtx} ctx
|
|
72
110
|
*/
|
|
73
111
|
export function renderStylebookMode(ctx) {
|
|
74
112
|
_ctx = ctx;
|
|
@@ -85,8 +123,8 @@ export function renderStylebookMode(ctx) {
|
|
|
85
123
|
);
|
|
86
124
|
const hasMedia = sizeBreakpoints.length > 0;
|
|
87
125
|
|
|
88
|
-
const onFilterInput = (/** @type {
|
|
89
|
-
updateUi("stylebookFilter", e.target.value);
|
|
126
|
+
const onFilterInput = (/** @type {Event} */ e) => {
|
|
127
|
+
updateUi("stylebookFilter", /** @type {HTMLInputElement} */ (e.target).value);
|
|
90
128
|
};
|
|
91
129
|
|
|
92
130
|
const onCustomizedToggle = () => {
|
|
@@ -116,9 +154,9 @@ export function renderStylebookMode(ctx) {
|
|
|
116
154
|
</div>
|
|
117
155
|
`;
|
|
118
156
|
|
|
119
|
-
/** @type {
|
|
157
|
+
/** @type {HTMLElement} */ (canvasWrap).style.overflow = "hidden";
|
|
120
158
|
|
|
121
|
-
/** @type {
|
|
159
|
+
/** @type {{ name: string; displayName: string; width: number; activeSet: Set<string> }[]} */
|
|
122
160
|
const allPanelDefs = [];
|
|
123
161
|
if (hasMedia) {
|
|
124
162
|
allPanelDefs.push({
|
|
@@ -137,7 +175,10 @@ export function renderStylebookMode(ctx) {
|
|
|
137
175
|
}
|
|
138
176
|
}
|
|
139
177
|
|
|
140
|
-
const renderIntoPanel = (
|
|
178
|
+
const renderIntoPanel = (
|
|
179
|
+
/** @type {StylebookPanel} */ panel,
|
|
180
|
+
/** @type {Set<string>} */ activeBreakpoints,
|
|
181
|
+
) => {
|
|
141
182
|
panel.canvas.classList.add("sb-canvas");
|
|
142
183
|
renderStylebookElementsIntoCanvas(
|
|
143
184
|
panel.canvas,
|
|
@@ -147,12 +188,18 @@ export function renderStylebookMode(ctx) {
|
|
|
147
188
|
activeBreakpoints,
|
|
148
189
|
);
|
|
149
190
|
for (const child of panel.canvas.querySelectorAll("*")) {
|
|
150
|
-
child.style.pointerEvents = "none";
|
|
191
|
+
/** @type {HTMLElement} */ (child).style.pointerEvents = "none";
|
|
151
192
|
}
|
|
152
193
|
registerStylebookPanelEvents(panel);
|
|
153
194
|
};
|
|
154
195
|
|
|
155
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* @type {{
|
|
198
|
+
* tpl: import("lit-html").TemplateResult;
|
|
199
|
+
* panel: StylebookPanel;
|
|
200
|
+
* activeSet: Set<string>;
|
|
201
|
+
* }[]}
|
|
202
|
+
*/
|
|
156
203
|
let panelEntries;
|
|
157
204
|
if (!hasMedia) {
|
|
158
205
|
const effectiveMedia = getEffectiveMedia(tab?.doc.document?.$media);
|
|
@@ -186,11 +233,11 @@ export function renderStylebookMode(ctx) {
|
|
|
186
233
|
${panelEntries.map((e) => e.tpl)}
|
|
187
234
|
</div>
|
|
188
235
|
`,
|
|
189
|
-
/** @type {
|
|
236
|
+
/** @type {HTMLElement} */ (canvasWrap),
|
|
190
237
|
);
|
|
191
238
|
|
|
192
239
|
for (const { panel, activeSet } of panelEntries) {
|
|
193
|
-
canvasPanels.push(panel);
|
|
240
|
+
canvasPanels.push(/** @type {import("./canvas-dnd.js").CanvasPanel} */ (panel));
|
|
194
241
|
renderIntoPanel(panel, activeSet);
|
|
195
242
|
}
|
|
196
243
|
if (hasMedia) {
|
|
@@ -242,7 +289,9 @@ export function refreshStylebookStyles() {
|
|
|
242
289
|
for (const [prop, val] of Object.entries(tagStyle)) {
|
|
243
290
|
if (typeof val === "string" || typeof val === "number") {
|
|
244
291
|
try {
|
|
245
|
-
/** @type {
|
|
292
|
+
/** @type {Record<string, string | number>} */ (
|
|
293
|
+
/** @type {unknown} */ (htmlEl.style)
|
|
294
|
+
)[prop] = val;
|
|
246
295
|
} catch {}
|
|
247
296
|
}
|
|
248
297
|
}
|
|
@@ -253,10 +302,14 @@ export function refreshStylebookStyles() {
|
|
|
253
302
|
const mediaName = key.slice(1);
|
|
254
303
|
if (mediaName === "--") continue;
|
|
255
304
|
if (activeBreakpoints.has(mediaName)) {
|
|
256
|
-
for (const [prop, v] of Object.entries(
|
|
305
|
+
for (const [prop, v] of Object.entries(
|
|
306
|
+
/** @type {Record<string, unknown>} */ (val),
|
|
307
|
+
)) {
|
|
257
308
|
if (typeof v === "string" || typeof v === "number") {
|
|
258
309
|
try {
|
|
259
|
-
/** @type {
|
|
310
|
+
/** @type {Record<string, string | number>} */ (
|
|
311
|
+
/** @type {unknown} */ (htmlEl.style)
|
|
312
|
+
)[prop] = v;
|
|
260
313
|
} catch {}
|
|
261
314
|
}
|
|
262
315
|
}
|
|
@@ -271,12 +324,17 @@ export function refreshStylebookStyles() {
|
|
|
271
324
|
const mediaName = key.slice(1);
|
|
272
325
|
if (mediaName === "--") continue;
|
|
273
326
|
if (activeBreakpoints.has(mediaName)) {
|
|
274
|
-
const mediaTagStyle = _resolveNestedStyle(
|
|
327
|
+
const mediaTagStyle = _resolveNestedStyle(
|
|
328
|
+
/** @type {Record<string, unknown>} */ (val),
|
|
329
|
+
tag,
|
|
330
|
+
);
|
|
275
331
|
if (mediaTagStyle && typeof mediaTagStyle === "object") {
|
|
276
332
|
for (const [prop, v] of Object.entries(mediaTagStyle)) {
|
|
277
333
|
if (typeof v === "string" || typeof v === "number") {
|
|
278
334
|
try {
|
|
279
|
-
/** @type {
|
|
335
|
+
/** @type {Record<string, string | number>} */ (
|
|
336
|
+
/** @type {unknown} */ (htmlEl.style)
|
|
337
|
+
)[prop] = v;
|
|
280
338
|
} catch {}
|
|
281
339
|
}
|
|
282
340
|
}
|
|
@@ -322,7 +380,7 @@ export function renderStylebookOverlays() {
|
|
|
322
380
|
const selectedTag = activeTab.value?.session.ui.stylebookSelection;
|
|
323
381
|
|
|
324
382
|
for (const panel of canvasPanels) {
|
|
325
|
-
const hoverTag = /** @type {
|
|
383
|
+
const hoverTag = /** @type {StylebookPanel} */ (panel)._lastHoverTag;
|
|
326
384
|
/**
|
|
327
385
|
* @type {{
|
|
328
386
|
* cls: string;
|
|
@@ -373,9 +431,9 @@ export function renderStylebookOverlays() {
|
|
|
373
431
|
/**
|
|
374
432
|
* Build a DOM element tree from a stylebook-meta.json entry.
|
|
375
433
|
*
|
|
376
|
-
* @param {
|
|
377
|
-
* @param {
|
|
378
|
-
* @param {
|
|
434
|
+
* @param {StylebookEntry} entry
|
|
435
|
+
* @param {Record<string, unknown>} rootStyle
|
|
436
|
+
* @param {Set<string> | null} activeBreakpoints
|
|
379
437
|
* @param {string | null} [parentTag]
|
|
380
438
|
*/
|
|
381
439
|
export function buildStylebookElement(entry, rootStyle, activeBreakpoints, parentTag = null) {
|
|
@@ -397,7 +455,8 @@ export function buildStylebookElement(entry, rootStyle, activeBreakpoints, paren
|
|
|
397
455
|
for (const [prop, val] of Object.entries(tagStyle)) {
|
|
398
456
|
if (typeof val === "string" || typeof val === "number") {
|
|
399
457
|
try {
|
|
400
|
-
/** @type {
|
|
458
|
+
/** @type {Record<string, string | number>} */ (/** @type {unknown} */ (el.style))[prop] =
|
|
459
|
+
val;
|
|
401
460
|
} catch {}
|
|
402
461
|
}
|
|
403
462
|
}
|
|
@@ -408,10 +467,12 @@ export function buildStylebookElement(entry, rootStyle, activeBreakpoints, paren
|
|
|
408
467
|
const mediaName = key.slice(1);
|
|
409
468
|
if (mediaName === "--") continue;
|
|
410
469
|
if (activeBreakpoints.has(mediaName)) {
|
|
411
|
-
for (const [prop, v] of Object.entries(/** @type {
|
|
470
|
+
for (const [prop, v] of Object.entries(/** @type {Record<string, unknown>} */ (val))) {
|
|
412
471
|
if (typeof v === "string" || typeof v === "number") {
|
|
413
472
|
try {
|
|
414
|
-
/** @type {
|
|
473
|
+
/** @type {Record<string, string | number>} */ (/** @type {unknown} */ (el.style))[
|
|
474
|
+
prop
|
|
475
|
+
] = v;
|
|
415
476
|
} catch {}
|
|
416
477
|
}
|
|
417
478
|
}
|
|
@@ -427,12 +488,17 @@ export function buildStylebookElement(entry, rootStyle, activeBreakpoints, paren
|
|
|
427
488
|
const mediaName = key.slice(1);
|
|
428
489
|
if (mediaName === "--") continue;
|
|
429
490
|
if (activeBreakpoints.has(mediaName)) {
|
|
430
|
-
const mediaTagStyle = _resolveNestedStyle(
|
|
491
|
+
const mediaTagStyle = _resolveNestedStyle(
|
|
492
|
+
/** @type {Record<string, unknown>} */ (val),
|
|
493
|
+
tagPath,
|
|
494
|
+
);
|
|
431
495
|
if (mediaTagStyle && typeof mediaTagStyle === "object") {
|
|
432
496
|
for (const [prop, v] of Object.entries(mediaTagStyle)) {
|
|
433
497
|
if (typeof v === "string" || typeof v === "number") {
|
|
434
498
|
try {
|
|
435
|
-
/** @type {
|
|
499
|
+
/** @type {Record<string, string | number>} */ (/** @type {unknown} */ (el.style))[
|
|
500
|
+
prop
|
|
501
|
+
] = v;
|
|
436
502
|
} catch {}
|
|
437
503
|
}
|
|
438
504
|
}
|
|
@@ -451,7 +517,7 @@ export function buildStylebookElement(entry, rootStyle, activeBreakpoints, paren
|
|
|
451
517
|
/**
|
|
452
518
|
* Render a live component preview by registering its custom element and instantiating it.
|
|
453
519
|
*
|
|
454
|
-
* @param {
|
|
520
|
+
* @param {ComponentEntry} comp
|
|
455
521
|
* @returns {Promise<HTMLElement>}
|
|
456
522
|
*/
|
|
457
523
|
export async function renderComponentPreview(comp) {
|
|
@@ -477,7 +543,7 @@ export async function renderComponentPreview(comp) {
|
|
|
477
543
|
}
|
|
478
544
|
}
|
|
479
545
|
return el;
|
|
480
|
-
} catch (/** @type {
|
|
546
|
+
} catch (/** @type {unknown} */ e) {
|
|
481
547
|
console.warn("Component preview failed:", comp.tagName, e);
|
|
482
548
|
return _componentFallback(comp.tagName);
|
|
483
549
|
}
|
|
@@ -493,26 +559,26 @@ function _componentFallback(tagName) {
|
|
|
493
559
|
}
|
|
494
560
|
|
|
495
561
|
/**
|
|
496
|
-
* @param {
|
|
497
|
-
* @param {
|
|
562
|
+
* @param {Record<string, unknown>} rootStyle
|
|
563
|
+
* @param {string} tag
|
|
498
564
|
*/
|
|
499
565
|
function hasTagStyle(rootStyle, tag) {
|
|
500
566
|
const s = _resolveNestedStyle(rootStyle, tag);
|
|
501
567
|
if (s && typeof s === "object" && Object.keys(s).length > 0) return true;
|
|
502
568
|
for (const [key, val] of Object.entries(rootStyle)) {
|
|
503
569
|
if (!key.startsWith("@") || typeof val !== "object") continue;
|
|
504
|
-
const ms = _resolveNestedStyle(/** @type {
|
|
570
|
+
const ms = _resolveNestedStyle(/** @type {Record<string, unknown>} */ (val), tag);
|
|
505
571
|
if (ms && typeof ms === "object" && Object.keys(ms).length > 0) return true;
|
|
506
572
|
}
|
|
507
573
|
return false;
|
|
508
574
|
}
|
|
509
575
|
|
|
510
576
|
/**
|
|
511
|
-
* @param {
|
|
512
|
-
* @param {
|
|
513
|
-
* @param {
|
|
514
|
-
* @param {
|
|
515
|
-
* @param {
|
|
577
|
+
* @param {HTMLElement} canvasEl
|
|
578
|
+
* @param {Record<string, unknown>} rootStyle
|
|
579
|
+
* @param {string} filter
|
|
580
|
+
* @param {boolean | undefined} customizedOnly
|
|
581
|
+
* @param {Set<string> | null} activeBreakpoints
|
|
516
582
|
*/
|
|
517
583
|
export function renderStylebookElementsIntoCanvas(
|
|
518
584
|
canvasEl,
|
|
@@ -531,19 +597,19 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
531
597
|
const sectionTemplates = [];
|
|
532
598
|
|
|
533
599
|
for (const section of stylebookMeta.$sections) {
|
|
534
|
-
let entries = /** @type {
|
|
600
|
+
let entries = /** @type {StylebookEntry[]} */ (section.elements);
|
|
535
601
|
if (filter) {
|
|
536
602
|
entries = entries.filter(
|
|
537
|
-
(/** @type {
|
|
603
|
+
(/** @type {StylebookEntry} */ e) =>
|
|
538
604
|
e.tag.includes(filter) || section.label.toLowerCase().includes(filter),
|
|
539
605
|
);
|
|
540
606
|
}
|
|
541
607
|
if (customizedOnly) {
|
|
542
|
-
entries = entries.filter((/** @type {
|
|
608
|
+
entries = entries.filter((/** @type {StylebookEntry} */ e) => hasTagStyle(rootStyle, e.tag));
|
|
543
609
|
}
|
|
544
610
|
if (entries.length === 0) continue;
|
|
545
611
|
|
|
546
|
-
const cardTemplates = entries.map((/** @type {
|
|
612
|
+
const cardTemplates = entries.map((/** @type {StylebookEntry} */ entry) => {
|
|
547
613
|
const el = buildStylebookElement(entry, rootStyle, activeBreakpoints);
|
|
548
614
|
return html`
|
|
549
615
|
<div
|
|
@@ -588,11 +654,13 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
588
654
|
if (componentRegistry.length > 0) {
|
|
589
655
|
let comps = componentRegistry;
|
|
590
656
|
if (filter)
|
|
591
|
-
comps = comps.filter((/** @type {
|
|
657
|
+
comps = comps.filter((/** @type {ComponentEntry} */ c) =>
|
|
658
|
+
c.tagName.toLowerCase().includes(filter),
|
|
659
|
+
);
|
|
592
660
|
if (customizedOnly)
|
|
593
|
-
comps = comps.filter((/** @type {
|
|
661
|
+
comps = comps.filter((/** @type {ComponentEntry} */ c) => hasTagStyle(rootStyle, c.tagName));
|
|
594
662
|
if (comps.length > 0) {
|
|
595
|
-
const compCards = comps.map((/** @type {
|
|
663
|
+
const compCards = comps.map((/** @type {ComponentEntry} */ comp) => {
|
|
596
664
|
/** @type {HTMLDivElement | null} */
|
|
597
665
|
let previewEl = null;
|
|
598
666
|
const cardTpl = html`
|
|
@@ -648,22 +716,22 @@ export function renderStylebookElementsIntoCanvas(
|
|
|
648
716
|
/**
|
|
649
717
|
* Click handler for stylebook canvas — selects elements via elToPath/view.stylebookElToTag mapping
|
|
650
718
|
*
|
|
651
|
-
* @param {
|
|
719
|
+
* @param {StylebookPanel} panel
|
|
652
720
|
*/
|
|
653
721
|
function registerStylebookPanelEvents(panel) {
|
|
654
722
|
const { canvas, overlayClk } = panel;
|
|
655
723
|
|
|
656
|
-
overlayClk.addEventListener("click", (/** @type {
|
|
724
|
+
overlayClk.addEventListener("click", (/** @type {MouseEvent} */ e) => {
|
|
657
725
|
const els = canvas.querySelectorAll("*");
|
|
658
|
-
for (const el of els) el.style.pointerEvents = "auto";
|
|
726
|
+
for (const el of els) /** @type {HTMLElement} */ (el).style.pointerEvents = "auto";
|
|
659
727
|
overlayClk.style.display = "none";
|
|
660
728
|
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
661
729
|
overlayClk.style.display = "";
|
|
662
|
-
for (const el of els) el.style.pointerEvents = "none";
|
|
730
|
+
for (const el of els) /** @type {HTMLElement} */ (el).style.pointerEvents = "none";
|
|
663
731
|
|
|
664
732
|
for (const el of elements) {
|
|
665
733
|
if (!canvas.contains(el) || el === canvas) continue;
|
|
666
|
-
let cur = /** @type {
|
|
734
|
+
let cur = /** @type {Element | null} */ (el);
|
|
667
735
|
while (cur && cur !== canvas) {
|
|
668
736
|
const tag = view.stylebookElToTag.get(cur);
|
|
669
737
|
if (tag) {
|
|
@@ -679,18 +747,18 @@ function registerStylebookPanelEvents(panel) {
|
|
|
679
747
|
renderStylebookOverlays();
|
|
680
748
|
});
|
|
681
749
|
|
|
682
|
-
overlayClk.addEventListener("mousemove", (/** @type {
|
|
750
|
+
overlayClk.addEventListener("mousemove", (/** @type {MouseEvent} */ e) => {
|
|
683
751
|
const els = canvas.querySelectorAll("*");
|
|
684
|
-
for (const el of els) el.style.pointerEvents = "auto";
|
|
752
|
+
for (const el of els) /** @type {HTMLElement} */ (el).style.pointerEvents = "auto";
|
|
685
753
|
overlayClk.style.display = "none";
|
|
686
754
|
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
687
755
|
overlayClk.style.display = "";
|
|
688
|
-
for (const el of els) el.style.pointerEvents = "none";
|
|
756
|
+
for (const el of els) /** @type {HTMLElement} */ (el).style.pointerEvents = "none";
|
|
689
757
|
|
|
690
758
|
let hoverTag = null;
|
|
691
759
|
for (const el of elements) {
|
|
692
760
|
if (!canvas.contains(el) || el === canvas) continue;
|
|
693
|
-
let cur = /** @type {
|
|
761
|
+
let cur = /** @type {Element | null} */ (el);
|
|
694
762
|
while (cur && cur !== canvas) {
|
|
695
763
|
const tag = view.stylebookElToTag.get(cur);
|
|
696
764
|
if (tag) {
|
|
@@ -710,9 +778,9 @@ function registerStylebookPanelEvents(panel) {
|
|
|
710
778
|
}
|
|
711
779
|
|
|
712
780
|
/** Find a stylebook element by tag in the canvas */
|
|
713
|
-
function findStylebookEl(/** @type {
|
|
781
|
+
function findStylebookEl(/** @type {HTMLElement} */ canvasEl, /** @type {string} */ tag) {
|
|
714
782
|
for (const child of canvasEl.querySelectorAll("*")) {
|
|
715
|
-
if (view.stylebookElToTag.get(child) === tag) return child;
|
|
783
|
+
if (view.stylebookElToTag.get(child) === tag) return /** @type {HTMLElement} */ (child);
|
|
716
784
|
}
|
|
717
785
|
return null;
|
|
718
786
|
}
|