@jxsuite/studio 1.1.0 → 1.2.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 +139 -17
- package/dist/iframe-entry.js.map +7 -6
- package/dist/studio.js +22601 -22425
- package/dist/studio.js.map +52 -52
- package/package.json +8 -8
- package/src/canvas/iframe-entry.ts +17 -1
- package/src/canvas/iframe-host.ts +62 -1
- package/src/canvas/iframe-protocol.ts +13 -0
- package/src/canvas/iframe-render.ts +35 -14
- package/src/canvas/site-style-css.ts +121 -0
- package/src/panels/style-panel.ts +52 -22
- package/src/panels/tab-bar.ts +39 -4
- package/src/settings/css-vars-editor.ts +122 -4
- package/src/studio.ts +7 -0
- package/src/tabs/tab.ts +7 -0
- package/src/utils/canvas-media.ts +23 -0
package/dist/iframe-entry.js
CHANGED
|
@@ -2626,11 +2626,21 @@ function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
|
|
|
2626
2626
|
if (key === "@--") {
|
|
2627
2627
|
continue;
|
|
2628
2628
|
}
|
|
2629
|
-
const
|
|
2629
|
+
const query = key.startsWith("@--") ? mediaQueries[key.slice(1)] ?? key.slice(1) : key.startsWith("@(") ? key.slice(1) : null;
|
|
2630
|
+
const atRule = query === null ? key : `@media ${query}`;
|
|
2630
2631
|
const scope = `[data-jx="${uid}"]`;
|
|
2631
|
-
|
|
2632
|
+
const scheme = query === null ? null : pureSchemeOf(query);
|
|
2633
|
+
if (scheme) {
|
|
2634
|
+
const { auto, forced } = schemeSelectors(scope, scheme);
|
|
2635
|
+
css += `${atRule} { ${auto} { ${toCSSText(rules)} } }
|
|
2632
2636
|
`;
|
|
2633
|
-
|
|
2637
|
+
emitMediaNested(atRule, auto, rules);
|
|
2638
|
+
emitNested(forced, rules);
|
|
2639
|
+
} else {
|
|
2640
|
+
css += `${atRule} { ${scope} { ${toCSSText(rules)} } }
|
|
2641
|
+
`;
|
|
2642
|
+
emitMediaNested(atRule, scope, rules);
|
|
2643
|
+
}
|
|
2634
2644
|
}
|
|
2635
2645
|
const tag = document.createElement("style");
|
|
2636
2646
|
tag.textContent = css;
|
|
@@ -3318,6 +3328,23 @@ function camelToKebab(s) {
|
|
|
3318
3328
|
function toCSSText(rules) {
|
|
3319
3329
|
return Object.entries(rules).filter(([k, v]) => !isNestedSelector(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${camelToKebab(p)}: ${transposeCanvasUnits(String(v))}`).join("; ");
|
|
3320
3330
|
}
|
|
3331
|
+
var COLOR_SCHEME_ATTR = "data-color-scheme";
|
|
3332
|
+
function pureSchemeOf(query) {
|
|
3333
|
+
const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
|
|
3334
|
+
return m?.[1] ?? null;
|
|
3335
|
+
}
|
|
3336
|
+
function schemeSelectors(selector, scheme) {
|
|
3337
|
+
if (selector === ":root" || selector === "html") {
|
|
3338
|
+
return {
|
|
3339
|
+
auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
|
|
3340
|
+
forced: `${selector}:where([${COLOR_SCHEME_ATTR}="${scheme}"])`
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
return {
|
|
3344
|
+
auto: `:where(:root:not([${COLOR_SCHEME_ATTR}])) ${selector}`,
|
|
3345
|
+
forced: `:where(:root[${COLOR_SCHEME_ATTR}="${scheme}"]) ${selector}`
|
|
3346
|
+
};
|
|
3347
|
+
}
|
|
3321
3348
|
var _rootMedia = {};
|
|
3322
3349
|
var _elementDefs = new Map;
|
|
3323
3350
|
function setRootMedia(map) {
|
|
@@ -3573,6 +3600,86 @@ function parseJxPath(serialized) {
|
|
|
3573
3600
|
return JSON.parse(serialized);
|
|
3574
3601
|
}
|
|
3575
3602
|
|
|
3603
|
+
// src/canvas/site-style-css.ts
|
|
3604
|
+
var SITE_STYLE_ID = "jx-site-style";
|
|
3605
|
+
function toDecls(props, transpose) {
|
|
3606
|
+
return Object.entries(props).map(([key, value]) => `${camelToKebab(key)}: ${transpose(String(value))}`).join("; ");
|
|
3607
|
+
}
|
|
3608
|
+
function buildSiteStyleCSS(siteStyle, mediaQueries, transpose) {
|
|
3609
|
+
const rules = [];
|
|
3610
|
+
const rootProps = {};
|
|
3611
|
+
const bodyProps = {};
|
|
3612
|
+
const condBlocks = [];
|
|
3613
|
+
for (const [key, value] of Object.entries(siteStyle)) {
|
|
3614
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
3615
|
+
if (key.startsWith("@")) {
|
|
3616
|
+
condBlocks.push([key, value]);
|
|
3617
|
+
}
|
|
3618
|
+
continue;
|
|
3619
|
+
}
|
|
3620
|
+
if (key.startsWith(":") || key.startsWith(".") || key.startsWith("[") || key.startsWith("@")) {
|
|
3621
|
+
continue;
|
|
3622
|
+
}
|
|
3623
|
+
if (key.startsWith("--")) {
|
|
3624
|
+
rootProps[key] = value;
|
|
3625
|
+
} else {
|
|
3626
|
+
bodyProps[key] = value;
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
const rootCSS = toDecls(rootProps, transpose);
|
|
3630
|
+
if (rootCSS) {
|
|
3631
|
+
rules.push(`:root { ${rootCSS} }`);
|
|
3632
|
+
}
|
|
3633
|
+
const bodyCSS = toDecls(bodyProps, transpose);
|
|
3634
|
+
if (bodyCSS) {
|
|
3635
|
+
rules.push(`body { ${bodyCSS} }`);
|
|
3636
|
+
}
|
|
3637
|
+
for (const [atKey, block] of condBlocks) {
|
|
3638
|
+
const query = atKey.startsWith("@--") ? mediaQueries[atKey.slice(1)] ?? atKey.slice(1) : atKey.startsWith("@(") ? atKey.slice(1) : null;
|
|
3639
|
+
if (query === null) {
|
|
3640
|
+
continue;
|
|
3641
|
+
}
|
|
3642
|
+
const scheme = pureSchemeOf(query);
|
|
3643
|
+
const emit = (selector, props) => {
|
|
3644
|
+
if (!props) {
|
|
3645
|
+
return;
|
|
3646
|
+
}
|
|
3647
|
+
if (scheme) {
|
|
3648
|
+
const { auto, forced } = schemeSelectors(selector, scheme);
|
|
3649
|
+
rules.push(`@media ${query} { ${auto} { ${props} } }`, `${forced} { ${props} }`);
|
|
3650
|
+
} else {
|
|
3651
|
+
rules.push(`@media ${query} { ${selector} { ${props} } }`);
|
|
3652
|
+
}
|
|
3653
|
+
};
|
|
3654
|
+
const condRoot = {};
|
|
3655
|
+
const condBody = {};
|
|
3656
|
+
const condSubs = [];
|
|
3657
|
+
for (const [k, v] of Object.entries(block)) {
|
|
3658
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
3659
|
+
if (!k.startsWith("@")) {
|
|
3660
|
+
condSubs.push([k, v]);
|
|
3661
|
+
}
|
|
3662
|
+
continue;
|
|
3663
|
+
}
|
|
3664
|
+
if (k.startsWith("--")) {
|
|
3665
|
+
condRoot[k] = v;
|
|
3666
|
+
} else {
|
|
3667
|
+
condBody[k] = v;
|
|
3668
|
+
}
|
|
3669
|
+
}
|
|
3670
|
+
emit(":root", toDecls(condRoot, transpose));
|
|
3671
|
+
emit("body", toDecls(condBody, transpose));
|
|
3672
|
+
for (const [sel, sub] of condSubs) {
|
|
3673
|
+
emit(sel, toDecls(sub, transpose));
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
if (Object.values(mediaQueries).some((q) => pureSchemeOf(q) !== null)) {
|
|
3677
|
+
rules.push(":root { color-scheme: light dark }");
|
|
3678
|
+
}
|
|
3679
|
+
return rules.join(`
|
|
3680
|
+
`);
|
|
3681
|
+
}
|
|
3682
|
+
|
|
3576
3683
|
// src/canvas/iframe-render.ts
|
|
3577
3684
|
async function registerElements2(doc, docBase) {
|
|
3578
3685
|
const elements = doc.$elements;
|
|
@@ -3772,21 +3879,27 @@ function syncStylebookCss(doc, mode) {
|
|
|
3772
3879
|
style.textContent = STYLEBOOK_CSS;
|
|
3773
3880
|
doc.head.append(style);
|
|
3774
3881
|
}
|
|
3775
|
-
function applySiteStyle(siteStyle) {
|
|
3882
|
+
function applySiteStyle(siteStyle, mediaQueries = {}) {
|
|
3883
|
+
const existing = document.head.querySelector(`#${SITE_STYLE_ID}`);
|
|
3776
3884
|
if (!siteStyle || typeof siteStyle !== "object") {
|
|
3885
|
+
existing?.remove();
|
|
3777
3886
|
return;
|
|
3778
3887
|
}
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3888
|
+
const css = buildSiteStyleCSS(siteStyle, mediaQueries, transposeCanvasUnits);
|
|
3889
|
+
if (existing) {
|
|
3890
|
+
existing.textContent = css;
|
|
3891
|
+
return;
|
|
3892
|
+
}
|
|
3893
|
+
const tag = document.createElement("style");
|
|
3894
|
+
tag.id = SITE_STYLE_ID;
|
|
3895
|
+
tag.textContent = css;
|
|
3896
|
+
document.head.append(tag);
|
|
3897
|
+
}
|
|
3898
|
+
function applyPreviewColorScheme(doc, scheme) {
|
|
3899
|
+
if (scheme) {
|
|
3900
|
+
doc.documentElement.dataset.colorScheme = scheme;
|
|
3901
|
+
} else {
|
|
3902
|
+
delete doc.documentElement.dataset.colorScheme;
|
|
3790
3903
|
}
|
|
3791
3904
|
}
|
|
3792
3905
|
function injectHead(doc) {
|
|
@@ -3868,7 +3981,7 @@ async function renderResolvedDocument(opts) {
|
|
|
3868
3981
|
setCanvasViewportTranspose(true);
|
|
3869
3982
|
setCanvasDelinkAnchors(opts.mode !== "preview");
|
|
3870
3983
|
setStampPropBindings(opts.mode === "design" || opts.mode === "edit");
|
|
3871
|
-
applySiteStyle(opts.siteStyle);
|
|
3984
|
+
applySiteStyle(opts.siteStyle, opts.doc.$media ?? {});
|
|
3872
3985
|
injectHead(opts.doc);
|
|
3873
3986
|
syncEditModeCss(opts.container.ownerDocument, opts.mode);
|
|
3874
3987
|
syncStylebookCss(opts.container.ownerDocument, opts.mode);
|
|
@@ -6718,9 +6831,18 @@ function startCanvasIframe(opts) {
|
|
|
6718
6831
|
clearIframeDrag();
|
|
6719
6832
|
return;
|
|
6720
6833
|
}
|
|
6834
|
+
if (msg.kind === "setColorScheme") {
|
|
6835
|
+
applyPreviewColorScheme(container.ownerDocument, msg.scheme);
|
|
6836
|
+
return;
|
|
6837
|
+
}
|
|
6838
|
+
if (msg.kind === "siteStyleUpdate") {
|
|
6839
|
+
applySiteStyle(msg.siteStyle, msg.media);
|
|
6840
|
+
return;
|
|
6841
|
+
}
|
|
6721
6842
|
if (msg.kind !== "render" || msg.gen < latestGen) {
|
|
6722
6843
|
return;
|
|
6723
6844
|
}
|
|
6845
|
+
applyPreviewColorScheme(container.ownerDocument, msg.colorScheme ?? null);
|
|
6724
6846
|
if (isEditing()) {
|
|
6725
6847
|
stopEditing();
|
|
6726
6848
|
}
|
|
@@ -6816,5 +6938,5 @@ export {
|
|
|
6816
6938
|
bootCanvasIframe
|
|
6817
6939
|
};
|
|
6818
6940
|
|
|
6819
|
-
//# debugId=
|
|
6941
|
+
//# debugId=4938332B50832C2764756E2164756E21
|
|
6820
6942
|
//# sourceMappingURL=iframe-entry.js.map
|