@jxsuite/studio 0.21.3 → 0.22.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.js +532 -252
- package/dist/studio.js.map +15 -15
- package/package.json +4 -4
- package/src/canvas/canvas-live-render.js +6 -5
- package/src/canvas/canvas-render.js +4 -3
- package/src/editor/context-menu.js +146 -26
- package/src/editor/insertion-helper.js +4 -3
- package/src/markdown/md-convert.js +7 -0
- package/src/panels/head-panel.js +105 -2
- package/src/panels/right-panel.js +142 -90
- package/src/panels/signals-panel.js +246 -129
- package/src/panels/style-panel.js +44 -1
- package/src/services/code-services.js +12 -5
- package/src/settings/head-editor.js +4 -4
- package/src/tabs/transact.js +1 -0
package/dist/studio.js
CHANGED
|
@@ -254721,6 +254721,8 @@ function mutateUpdateAttribute(tab, path, attr, value) {
|
|
|
254721
254721
|
delete node.attributes;
|
|
254722
254722
|
}
|
|
254723
254723
|
function mutateUpdateMediaStyle(tab, path, mediaName, prop, value) {
|
|
254724
|
+
if (!mediaName)
|
|
254725
|
+
return mutateUpdateStyle(tab, path, prop, value);
|
|
254724
254726
|
const node = getNodeAtPath(tab.doc.document, path);
|
|
254725
254727
|
if (!node.style)
|
|
254726
254728
|
node.style = {};
|
|
@@ -263034,6 +263036,12 @@ function collapsePropsToAttrMap(propsObj) {
|
|
|
263034
263036
|
if (key.startsWith(":") && CSS_PSEUDO_NAMES2.has(key.slice(1))) {
|
|
263035
263037
|
mdAttrKey = key.slice(1);
|
|
263036
263038
|
}
|
|
263039
|
+
if (key === "@") {
|
|
263040
|
+
if (value2 && typeof value2 === "object" && !Array.isArray(value2)) {
|
|
263041
|
+
walk2(value2, prefix);
|
|
263042
|
+
}
|
|
263043
|
+
continue;
|
|
263044
|
+
}
|
|
263037
263045
|
if (key.startsWith("@--")) {
|
|
263038
263046
|
mdAttrKey = key.slice(1);
|
|
263039
263047
|
}
|
|
@@ -263060,9 +263068,11 @@ async function codeService(action, payload) {
|
|
|
263060
263068
|
}
|
|
263061
263069
|
var pluginSchemaCache = new Map;
|
|
263062
263070
|
async function fetchPluginSchema(def3, state) {
|
|
263063
|
-
|
|
263071
|
+
const importedPath = def3.$prototype ? projectState?.projectConfig?.imports?.[def3.$prototype] : null;
|
|
263072
|
+
const src = def3.$src || importedPath;
|
|
263073
|
+
if (!src || !def3.$prototype)
|
|
263064
263074
|
return null;
|
|
263065
|
-
const cacheKey = `${
|
|
263075
|
+
const cacheKey = `${src}::${def3.$prototype}`;
|
|
263066
263076
|
if (pluginSchemaCache.has(cacheKey))
|
|
263067
263077
|
return pluginSchemaCache.get(cacheKey);
|
|
263068
263078
|
try {
|
|
@@ -263071,8 +263081,8 @@ async function fetchPluginSchema(def3, state) {
|
|
|
263071
263081
|
pluginSchemaCache.set(cacheKey, null);
|
|
263072
263082
|
return null;
|
|
263073
263083
|
}
|
|
263074
|
-
const base2 = state.documentPath ? `${location.origin}/${state.documentPath}` : undefined;
|
|
263075
|
-
const schema4 = await platform3.fetchPluginSchema(
|
|
263084
|
+
const base2 = !importedPath && state.documentPath ? `${location.origin}/${state.documentPath}` : undefined;
|
|
263085
|
+
const schema4 = await platform3.fetchPluginSchema(src, def3.$prototype, base2);
|
|
263076
263086
|
pluginSchemaCache.set(cacheKey, schema4);
|
|
263077
263087
|
return schema4;
|
|
263078
263088
|
} catch {
|
|
@@ -264427,10 +264437,6 @@ var _serverFnConfig = { skip: false };
|
|
|
264427
264437
|
function setSkipServerFunctions(v) {
|
|
264428
264438
|
_serverFnConfig.skip = v;
|
|
264429
264439
|
}
|
|
264430
|
-
var _contentConfig = { skip: false };
|
|
264431
|
-
function setSkipContentResolution(v) {
|
|
264432
|
-
_contentConfig.skip = v;
|
|
264433
|
-
}
|
|
264434
264440
|
async function buildScope(doc, parentScope = {}, base2 = location.href) {
|
|
264435
264441
|
const raw = {};
|
|
264436
264442
|
for (const [key, val] of Object.entries(parentScope)) {
|
|
@@ -264805,7 +264811,8 @@ function renderMappedArray(def3, state, options) {
|
|
|
264805
264811
|
applyProperties(container, def3, state);
|
|
264806
264812
|
applyStyle2(container, def3.style ?? {}, state["$media"] ?? {}, state);
|
|
264807
264813
|
applyAttributes(container, def3.attributes ?? {}, state);
|
|
264808
|
-
const { items:
|
|
264814
|
+
const { items: _items, of: _of, map: mapDef, filter: filterRef, sort: sortRef } = def3.children;
|
|
264815
|
+
const itemsSrc = _items ?? _of;
|
|
264809
264816
|
effect(() => {
|
|
264810
264817
|
container.innerHTML = "";
|
|
264811
264818
|
let items;
|
|
@@ -265033,39 +265040,6 @@ async function resolvePrototype(def3, state, key, base2) {
|
|
|
265033
265040
|
return new Blob(def3.parts ?? [], { type: def3.type ?? "text/plain" });
|
|
265034
265041
|
case "ReadableStream":
|
|
265035
265042
|
return null;
|
|
265036
|
-
case "ContentCollection":
|
|
265037
|
-
case "ContentEntry": {
|
|
265038
|
-
if (_contentConfig.skip) {
|
|
265039
|
-
return ref(def3.$prototype === "ContentCollection" ? [{ id: "", data: {} }] : null);
|
|
265040
|
-
}
|
|
265041
|
-
const s2 = ref(def3.$prototype === "ContentCollection" ? [] : null);
|
|
265042
|
-
effect(() => {
|
|
265043
|
-
let id = def3.id;
|
|
265044
|
-
if (id && typeof id === "object" && id.$ref?.startsWith("#/$params/")) {
|
|
265045
|
-
const paramName = id.$ref.replace("#/$params/", "");
|
|
265046
|
-
id = state?.$params?.[paramName];
|
|
265047
|
-
} else if (typeof id === "string" && id.includes("${")) {
|
|
265048
|
-
id = evaluateTemplate(id, state);
|
|
265049
|
-
}
|
|
265050
|
-
if (def3.$prototype === "ContentEntry" && !id)
|
|
265051
|
-
return;
|
|
265052
|
-
fetch("/__studio/content", {
|
|
265053
|
-
method: "POST",
|
|
265054
|
-
headers: { "Content-Type": "application/json" },
|
|
265055
|
-
body: JSON.stringify({
|
|
265056
|
-
$prototype: def3.$prototype,
|
|
265057
|
-
contentType: def3.contentType,
|
|
265058
|
-
id,
|
|
265059
|
-
filter: def3.filter,
|
|
265060
|
-
sort: def3.sort,
|
|
265061
|
-
limit: def3.limit
|
|
265062
|
-
})
|
|
265063
|
-
}).then((r) => r.ok ? r.json() : null).then((d2) => {
|
|
265064
|
-
s2.value = d2;
|
|
265065
|
-
}).catch(() => {});
|
|
265066
|
-
});
|
|
265067
|
-
return s2;
|
|
265068
|
-
}
|
|
265069
265043
|
default:
|
|
265070
265044
|
console.warn(`Jx: unknown $prototype "${def3.$prototype}" for "${key}". Did you mean to add '$src'?`);
|
|
265071
265045
|
return ref(null);
|
|
@@ -265149,6 +265123,10 @@ async function resolveClassJson(def3, state, key, base2) {
|
|
|
265149
265123
|
return resolveViaDevProxy(def3, state, key, base2);
|
|
265150
265124
|
}
|
|
265151
265125
|
if (classDef.$implementation) {
|
|
265126
|
+
const schemaStr = JSON.stringify(classDef);
|
|
265127
|
+
if (schemaStr.includes('"#/$context/')) {
|
|
265128
|
+
return resolveViaDevProxy(def3, state, key, base2);
|
|
265129
|
+
}
|
|
265152
265130
|
const schemaUrl = base2 ? new URL(src, base2).href : new URL(src, location.href).href;
|
|
265153
265131
|
const implSrc = new URL(classDef.$implementation, schemaUrl).href;
|
|
265154
265132
|
const exportName = def3.$export ?? classDef.title ?? def3.$prototype;
|
|
@@ -265690,7 +265668,6 @@ async function renderCanvasLive(gen, doc, canvasEl) {
|
|
|
265690
265668
|
_failedElementsDocPath = S.documentPath ?? null;
|
|
265691
265669
|
}
|
|
265692
265670
|
setSkipServerFunctions(canvasMode !== "preview");
|
|
265693
|
-
setSkipContentResolution(canvasMode !== "preview");
|
|
265694
265671
|
let renderDoc = canvasMode === "preview" ? structuredClone(toRaw(doc)) : prepareForEditMode(stripEventHandlers(doc));
|
|
265695
265672
|
let layoutWrapped = false;
|
|
265696
265673
|
activeLayoutPath = null;
|
|
@@ -265741,7 +265718,7 @@ async function renderCanvasLive(gen, doc, canvasEl) {
|
|
|
265741
265718
|
const docPrefix = root2 ? `${root2}/` : "";
|
|
265742
265719
|
const docBase = S.documentPath ? `${location.origin}/${docPrefix}${S.documentPath}` : undefined;
|
|
265743
265720
|
let effectiveElements = getEffectiveElements(renderDoc.$elements);
|
|
265744
|
-
if (S.mode === "content" && componentRegistry.length > 0) {
|
|
265721
|
+
if ((S.mode === "content" || layoutWrapped) && componentRegistry.length > 0) {
|
|
265745
265722
|
const existingRefs = new Set(effectiveElements.map((e) => typeof e === "string" ? e : e?.$ref));
|
|
265746
265723
|
const collectTags = (node2) => {
|
|
265747
265724
|
const tags2 = new Set;
|
|
@@ -265862,6 +265839,8 @@ async function renderCanvasLive(gen, doc, canvasEl) {
|
|
|
265862
265839
|
if (!entry?.tagName)
|
|
265863
265840
|
continue;
|
|
265864
265841
|
const tag3 = entry.tagName.toLowerCase();
|
|
265842
|
+
if (tag3 === "script" && !entry.attributes?.src)
|
|
265843
|
+
continue;
|
|
265865
265844
|
const attrs = { ...entry.attributes };
|
|
265866
265845
|
for (const key of ["href", "src"]) {
|
|
265867
265846
|
const val = attrs[key];
|
|
@@ -266340,6 +266319,24 @@ function renderSignalsTemplate(S, ctx) {
|
|
|
266340
266319
|
const type = e.target.value;
|
|
266341
266320
|
if (!type)
|
|
266342
266321
|
return;
|
|
266322
|
+
if (type.startsWith("import:")) {
|
|
266323
|
+
const protoName = type.slice(7);
|
|
266324
|
+
const src = projectState?.projectConfig?.imports?.[protoName];
|
|
266325
|
+
let n3 = "$" + protoName.charAt(0).toLowerCase() + protoName.slice(1);
|
|
266326
|
+
let i3 = 1;
|
|
266327
|
+
const base2 = n3;
|
|
266328
|
+
while (S.document.state && S.document.state[n3]) {
|
|
266329
|
+
n3 = base2 + i3++;
|
|
266330
|
+
}
|
|
266331
|
+
transactDoc(activeTab.value, (t) => mutateAddDef(t, n3, { $prototype: protoName }));
|
|
266332
|
+
expandedSignal = n3;
|
|
266333
|
+
if (src) {
|
|
266334
|
+
fetchPluginSchema({ $prototype: protoName, $src: src }, S).then(() => ctx.renderLeftPanel());
|
|
266335
|
+
} else {
|
|
266336
|
+
ctx.renderLeftPanel();
|
|
266337
|
+
}
|
|
266338
|
+
return;
|
|
266339
|
+
}
|
|
266343
266340
|
const template = DEF_TEMPLATES[type];
|
|
266344
266341
|
if (!template)
|
|
266345
266342
|
return;
|
|
@@ -266367,6 +266364,7 @@ function renderSignalsTemplate(S, ctx) {
|
|
|
266367
266364
|
<sp-menu-item value="map">Map</sp-menu-item>
|
|
266368
266365
|
<sp-menu-item value="formData">FormData</sp-menu-item>
|
|
266369
266366
|
<sp-menu-item value="external">External Module…</sp-menu-item>
|
|
266367
|
+
${projectState?.projectConfig?.imports ? html3`<sp-menu-divider></sp-menu-divider>${Object.keys(projectState.projectConfig.imports).map((k) => html3`<sp-menu-item value="import:${k}">${k}</sp-menu-item>`)}` : nothing}
|
|
266370
266368
|
<sp-menu-divider></sp-menu-divider>
|
|
266371
266369
|
<sp-menu-item value="function">Function</sp-menu-item>
|
|
266372
266370
|
</sp-picker>
|
|
@@ -266554,9 +266552,6 @@ function renderDataSourceFields(S, name, def3, textareaRow, pickerRow, ctx) {
|
|
|
266554
266552
|
${signalFieldRow("Default", String(def3.default || ""), (v) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: v })))}
|
|
266555
266553
|
`;
|
|
266556
266554
|
}
|
|
266557
|
-
if (proto2 === "ContentEntry" || proto2 === "ContentCollection") {
|
|
266558
|
-
return renderContentPrototypeFields(name, def3, proto2);
|
|
266559
|
-
}
|
|
266560
266555
|
if (proto2 === "Set" || proto2 === "Map" || proto2 === "FormData") {
|
|
266561
266556
|
const fieldName = proto2 === "FormData" ? "fields" : "default";
|
|
266562
266557
|
const fieldLabel = proto2 === "FormData" ? "Fields" : "Default";
|
|
@@ -266569,85 +266564,6 @@ function renderDataSourceFields(S, name, def3, textareaRow, pickerRow, ctx) {
|
|
|
266569
266564
|
}
|
|
266570
266565
|
return renderExternalPrototypeEditorTemplate(S, name, def3, ctx);
|
|
266571
266566
|
}
|
|
266572
|
-
function renderContentPrototypeFields(name, def3, proto2) {
|
|
266573
|
-
const contentTypes = projectState?.projectConfig?.contentTypes;
|
|
266574
|
-
const typeNames = contentTypes ? Object.keys(contentTypes) : [];
|
|
266575
|
-
const currentType = def3.contentType || "";
|
|
266576
|
-
const schema4 = currentType && contentTypes?.[currentType]?.schema || undefined;
|
|
266577
|
-
const contentTypeField = typeNames.length ? html3`
|
|
266578
|
-
<div class="signal-field-row">
|
|
266579
|
-
<label class="signal-field-label">Content Type</label>
|
|
266580
|
-
<sp-picker
|
|
266581
|
-
size="s"
|
|
266582
|
-
value=${currentType}
|
|
266583
|
-
style="width:100%"
|
|
266584
|
-
@change=${(e) => {
|
|
266585
|
-
const v = e.target.value;
|
|
266586
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { contentType: v }));
|
|
266587
|
-
}}
|
|
266588
|
-
>
|
|
266589
|
-
${typeNames.map((t) => html3`<sp-menu-item value=${t}>${t}</sp-menu-item>`)}
|
|
266590
|
-
</sp-picker>
|
|
266591
|
-
</div>
|
|
266592
|
-
` : signalFieldRow("Content Type", currentType, (v) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { contentType: v })));
|
|
266593
|
-
let entryFields = nothing;
|
|
266594
|
-
if (proto2 === "ContentEntry") {
|
|
266595
|
-
const idVal = def3.id;
|
|
266596
|
-
const idStr = idVal && typeof idVal === "object" && idVal.$ref ? idVal.$ref : typeof idVal === "string" ? idVal : "";
|
|
266597
|
-
entryFields = signalFieldRow("ID", idStr, (v) => {
|
|
266598
|
-
const val = v.startsWith("#/") ? { $ref: v } : v;
|
|
266599
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { id: val }));
|
|
266600
|
-
});
|
|
266601
|
-
} else {
|
|
266602
|
-
const filterStr = def3.filter ? JSON.stringify(def3.filter) : "";
|
|
266603
|
-
const sortStr = def3.sort ? `${def3.sort.field || ""} ${def3.sort.order || ""}`.trim() : "";
|
|
266604
|
-
const limitStr = def3.limit != null ? String(def3.limit) : "";
|
|
266605
|
-
entryFields = html3`
|
|
266606
|
-
${signalFieldRow("Filter", filterStr, (v) => {
|
|
266607
|
-
try {
|
|
266608
|
-
const parsed = v ? JSON.parse(v) : undefined;
|
|
266609
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { filter: parsed }));
|
|
266610
|
-
} catch {}
|
|
266611
|
-
})}
|
|
266612
|
-
${signalFieldRow("Sort", sortStr, (v) => {
|
|
266613
|
-
if (!v) {
|
|
266614
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { sort: undefined }));
|
|
266615
|
-
return;
|
|
266616
|
-
}
|
|
266617
|
-
const [field, order2] = v.split(" ");
|
|
266618
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { sort: { field, order: order2 || "asc" } }));
|
|
266619
|
-
})}
|
|
266620
|
-
${signalFieldRow("Limit", limitStr, (v) => {
|
|
266621
|
-
const num = v ? parseInt(v, 10) : undefined;
|
|
266622
|
-
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { limit: num }));
|
|
266623
|
-
})}
|
|
266624
|
-
`;
|
|
266625
|
-
}
|
|
266626
|
-
let schemaFields = nothing;
|
|
266627
|
-
if (schema4?.properties) {
|
|
266628
|
-
const fields = Object.entries(schema4.properties);
|
|
266629
|
-
const required = new Set(schema4.required || []);
|
|
266630
|
-
schemaFields = html3`
|
|
266631
|
-
<div style="margin-top:8px;padding:6px 0;border-top:1px solid var(--border-dim)">
|
|
266632
|
-
<div style="font-size:11px;color:var(--fg-dim);margin-bottom:4px;font-weight:500">
|
|
266633
|
-
Fields (${currentType})
|
|
266634
|
-
</div>
|
|
266635
|
-
${fields.map(([field, fieldDef]) => html3`
|
|
266636
|
-
<div style="font-size:11px;padding:2px 0;display:flex;gap:4px;align-items:center">
|
|
266637
|
-
<code style="color:var(--fg-default)">${field}</code>
|
|
266638
|
-
<span style="color:var(--fg-dim)">${fieldDef.type || ""}</span>
|
|
266639
|
-
${required.has(field) ? html3`<span style="color:var(--color-accent,#f36f32);font-size:9px">req</span>` : nothing}
|
|
266640
|
-
</div>
|
|
266641
|
-
`)}
|
|
266642
|
-
</div>
|
|
266643
|
-
`;
|
|
266644
|
-
}
|
|
266645
|
-
return html3`
|
|
266646
|
-
${contentTypeField}
|
|
266647
|
-
${signalFieldRow("Prototype", proto2, (v) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $prototype: v })))}
|
|
266648
|
-
${entryFields} ${schemaFields}
|
|
266649
|
-
`;
|
|
266650
|
-
}
|
|
266651
266567
|
function renderFunctionFields(S, name, def3, textareaRow, ctx) {
|
|
266652
266568
|
const descriptionField = signalFieldRow("Description", def3.description || "", (v) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { description: v || undefined })));
|
|
266653
266569
|
const bodyField = def3.$src ? html3`
|
|
@@ -266894,15 +266810,86 @@ function renderEmitsEditorTemplate(S, name, def3) {
|
|
|
266894
266810
|
</button>
|
|
266895
266811
|
`;
|
|
266896
266812
|
}
|
|
266897
|
-
function
|
|
266813
|
+
function resolveSchemaEnum(enumDef, parentDef) {
|
|
266814
|
+
if (Array.isArray(enumDef))
|
|
266815
|
+
return enumDef;
|
|
266816
|
+
if (enumDef && typeof enumDef === "object") {
|
|
266817
|
+
const ref3 = enumDef.$ref;
|
|
266818
|
+
if (ref3 === "#/$context/contentTypes") {
|
|
266819
|
+
return Object.keys(projectState?.projectConfig?.contentTypes ?? {});
|
|
266820
|
+
}
|
|
266821
|
+
if (typeof ref3 === "string" && ref3.startsWith("#/$context/contentTypes/{@")) {
|
|
266822
|
+
const match2 = ref3.match(/#\/\$context\/contentTypes\/\{@(\w+)\}\/schema\/properties/);
|
|
266823
|
+
if (match2 && parentDef) {
|
|
266824
|
+
const paramName = match2[1];
|
|
266825
|
+
const typeName = parentDef[paramName];
|
|
266826
|
+
if (typeName) {
|
|
266827
|
+
const ct = projectState?.projectConfig?.contentTypes?.[typeName];
|
|
266828
|
+
const schema4 = ct?.schema;
|
|
266829
|
+
const props = schema4?.properties;
|
|
266830
|
+
if (props)
|
|
266831
|
+
return Object.keys(props);
|
|
266832
|
+
}
|
|
266833
|
+
}
|
|
266834
|
+
return;
|
|
266835
|
+
}
|
|
266836
|
+
}
|
|
266837
|
+
if (enumDef === "$contentTypes") {
|
|
266838
|
+
return Object.keys(projectState?.projectConfig?.contentTypes ?? {});
|
|
266839
|
+
}
|
|
266840
|
+
return;
|
|
266841
|
+
}
|
|
266842
|
+
function renderInlineField(key, schema4, value2, onChange, parentDef) {
|
|
266843
|
+
const enumValues = resolveSchemaEnum(schema4.enum, parentDef);
|
|
266844
|
+
if (enumValues) {
|
|
266845
|
+
return html3`<sp-picker
|
|
266846
|
+
size="s"
|
|
266847
|
+
label=${key}
|
|
266848
|
+
value=${value2 !== undefined ? String(value2) : "__none__"}
|
|
266849
|
+
@change=${(e) => onChange(e.target.value === "__none__" ? undefined : e.target.value)}
|
|
266850
|
+
>
|
|
266851
|
+
<sp-menu-item value="__none__">—</sp-menu-item>
|
|
266852
|
+
${enumValues.map((v) => html3`<sp-menu-item value=${v}>${v}</sp-menu-item>`)}
|
|
266853
|
+
</sp-picker>`;
|
|
266854
|
+
}
|
|
266855
|
+
if (schema4.type === "boolean") {
|
|
266856
|
+
return html3`<sp-switch
|
|
266857
|
+
size="s"
|
|
266858
|
+
?checked=${!!value2}
|
|
266859
|
+
@change=${(e) => onChange(e.target.checked)}
|
|
266860
|
+
>${key}</sp-switch
|
|
266861
|
+
>`;
|
|
266862
|
+
}
|
|
266863
|
+
if (schema4.type === "integer" || schema4.type === "number") {
|
|
266864
|
+
return html3`<sp-number-field
|
|
266865
|
+
size="s"
|
|
266866
|
+
label=${key}
|
|
266867
|
+
.value=${value2 !== undefined ? value2 : nothing}
|
|
266868
|
+
step=${schema4.type === "integer" ? "1" : nothing}
|
|
266869
|
+
@change=${(e) => {
|
|
266870
|
+
const parsed = schema4.type === "integer" ? parseInt(e.target.value, 10) : parseFloat(e.target.value);
|
|
266871
|
+
onChange(isNaN(parsed) ? undefined : parsed);
|
|
266872
|
+
}}
|
|
266873
|
+
></sp-number-field>`;
|
|
266874
|
+
}
|
|
266875
|
+
return html3`<sp-textfield
|
|
266876
|
+
size="s"
|
|
266877
|
+
label=${key}
|
|
266878
|
+
placeholder=${key}
|
|
266879
|
+
.value=${value2 ?? ""}
|
|
266880
|
+
@input=${(e) => onChange(e.target.value || undefined)}
|
|
266881
|
+
></sp-textfield>`;
|
|
266882
|
+
}
|
|
266883
|
+
function renderSchemaFieldsTemplate(schema4, def3, name, _S, ctx = null) {
|
|
266898
266884
|
if (!schema4?.properties)
|
|
266899
266885
|
return nothing;
|
|
266900
266886
|
const required = new Set(schema4.required ?? []);
|
|
266901
|
-
|
|
266887
|
+
const propertyFields = Object.entries(schema4.properties).filter(([prop]) => !STUDIO_RESERVED_KEYS.has(prop)).map(([prop, ps]) => {
|
|
266902
266888
|
const currentValue = def3[prop];
|
|
266903
266889
|
const labelText = prop + (required.has(prop) ? " *" : "");
|
|
266904
266890
|
let control;
|
|
266905
|
-
|
|
266891
|
+
const enumValues = resolveSchemaEnum(ps.enum, def3);
|
|
266892
|
+
if (enumValues) {
|
|
266906
266893
|
control = html3`
|
|
266907
266894
|
<sp-picker
|
|
266908
266895
|
size="s"
|
|
@@ -266912,7 +266899,7 @@ function renderSchemaFieldsTemplate(schema4, def3, name, _S) {
|
|
|
266912
266899
|
}))}
|
|
266913
266900
|
>
|
|
266914
266901
|
${!required.has(prop) ? html3`<sp-menu-item value="__none__">—</sp-menu-item>` : nothing}
|
|
266915
|
-
${
|
|
266902
|
+
${enumValues.map((val) => html3`<sp-menu-item value=${val}>${val}</sp-menu-item>`)}
|
|
266916
266903
|
</sp-picker>
|
|
266917
266904
|
`;
|
|
266918
266905
|
} else if (ps.type === "boolean") {
|
|
@@ -266930,7 +266917,7 @@ function renderSchemaFieldsTemplate(schema4, def3, name, _S) {
|
|
|
266930
266917
|
max=${ifDefined(ps.maximum)}
|
|
266931
266918
|
step=${ps.type === "integer" ? "1" : nothing}
|
|
266932
266919
|
.value=${currentValue !== undefined ? currentValue : nothing}
|
|
266933
|
-
placeholder=${ps.default
|
|
266920
|
+
placeholder=${ps.default != null ? String(ps.default) : nothing}
|
|
266934
266921
|
@change=${(e) => {
|
|
266935
266922
|
clearTimeout(debounce);
|
|
266936
266923
|
debounce = setTimeout(() => {
|
|
@@ -266979,6 +266966,51 @@ function renderSchemaFieldsTemplate(schema4, def3, name, _S) {
|
|
|
266979
266966
|
></sp-textfield>
|
|
266980
266967
|
</div>
|
|
266981
266968
|
`;
|
|
266969
|
+
} else if (ps.type === "array" && ps.items?.type === "object" && ps.items?.properties) {
|
|
266970
|
+
const rows = Array.isArray(currentValue) ? currentValue : [];
|
|
266971
|
+
const itemProps = ps.items.properties;
|
|
266972
|
+
control = html3`
|
|
266973
|
+
<div class="array-object-field">
|
|
266974
|
+
${rows.map((row, idx) => html3`
|
|
266975
|
+
<div
|
|
266976
|
+
class="array-object-row"
|
|
266977
|
+
style="display:flex;gap:4px;align-items:center;margin-bottom:4px"
|
|
266978
|
+
>
|
|
266979
|
+
${Object.entries(itemProps).map(([propKey, propSchema]) => renderInlineField(propKey, propSchema, row[propKey], (val) => {
|
|
266980
|
+
const updated = [...rows];
|
|
266981
|
+
updated[idx] = { ...updated[idx], [propKey]: val };
|
|
266982
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { [prop]: updated }));
|
|
266983
|
+
}, def3))}
|
|
266984
|
+
<sp-action-button
|
|
266985
|
+
quiet
|
|
266986
|
+
size="s"
|
|
266987
|
+
@click=${() => {
|
|
266988
|
+
const updated = rows.filter((_, i2) => i2 !== idx);
|
|
266989
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { [prop]: updated.length ? updated : undefined }));
|
|
266990
|
+
ctx?.renderLeftPanel();
|
|
266991
|
+
}}
|
|
266992
|
+
>
|
|
266993
|
+
<sp-icon-delete slot="icon"></sp-icon-delete>
|
|
266994
|
+
</sp-action-button>
|
|
266995
|
+
</div>
|
|
266996
|
+
`)}
|
|
266997
|
+
<sp-action-button
|
|
266998
|
+
quiet
|
|
266999
|
+
size="s"
|
|
267000
|
+
@click=${(e) => {
|
|
267001
|
+
e.stopPropagation();
|
|
267002
|
+
const newRow = {};
|
|
267003
|
+
for (const [k, v] of Object.entries(itemProps)) {
|
|
267004
|
+
if (v.default !== undefined)
|
|
267005
|
+
newRow[k] = v.default;
|
|
267006
|
+
}
|
|
267007
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { [prop]: [...rows, newRow] }));
|
|
267008
|
+
ctx?.renderLeftPanel();
|
|
267009
|
+
}}
|
|
267010
|
+
>+ Add</sp-action-button
|
|
267011
|
+
>
|
|
267012
|
+
</div>
|
|
267013
|
+
`;
|
|
266982
267014
|
} else if (ps.type === "array" || ps.type === "object") {
|
|
266983
267015
|
let debounce;
|
|
266984
267016
|
control = html3`<sp-textfield
|
|
@@ -267021,17 +267053,20 @@ function renderSchemaFieldsTemplate(schema4, def3, name, _S) {
|
|
|
267021
267053
|
widget: control
|
|
267022
267054
|
});
|
|
267023
267055
|
});
|
|
267056
|
+
return html3`${propertyFields}`;
|
|
267024
267057
|
}
|
|
267025
267058
|
function renderExternalPrototypeEditorTemplate(S, name, def3, ctx) {
|
|
267026
267059
|
let schemaContent = nothing;
|
|
267027
|
-
|
|
267028
|
-
|
|
267060
|
+
const importedPath = def3.$prototype ? projectState?.projectConfig?.imports?.[def3.$prototype] : null;
|
|
267061
|
+
const resolvedSrc = def3.$src || importedPath;
|
|
267062
|
+
if (resolvedSrc && def3.$prototype) {
|
|
267063
|
+
const cacheKey = `${resolvedSrc}::${def3.$prototype}`;
|
|
267029
267064
|
if (pluginSchemaCache.has(cacheKey)) {
|
|
267030
267065
|
const schema4 = pluginSchemaCache.get(cacheKey);
|
|
267031
267066
|
if (schema4) {
|
|
267032
267067
|
schemaContent = html3`
|
|
267033
267068
|
${schema4.description ? html3`<div class="signal-hint" style="padding:4px 0 8px">${schema4.description}</div>` : nothing}
|
|
267034
|
-
${renderSchemaFieldsTemplate(schema4, def3, name, S)}
|
|
267069
|
+
${renderSchemaFieldsTemplate(schema4, def3, name, S, ctx)}
|
|
267035
267070
|
`;
|
|
267036
267071
|
}
|
|
267037
267072
|
} else {
|
|
@@ -267047,14 +267082,18 @@ function renderExternalPrototypeEditorTemplate(S, name, def3, ctx) {
|
|
|
267047
267082
|
}
|
|
267048
267083
|
}
|
|
267049
267084
|
return html3`
|
|
267050
|
-
${
|
|
267085
|
+
${importedPath ? html3`<div class="signal-hint" style="padding:4px 0 2px;font-size:11px;color:var(--fg-dim)">
|
|
267086
|
+
${def3.$prototype}
|
|
267087
|
+
</div>` : html3`
|
|
267088
|
+
${signalFieldRow("Source", def3.$src || "", (v) => {
|
|
267051
267089
|
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $src: v || undefined }));
|
|
267052
267090
|
pluginSchemaCache.delete(`${v}::${def3.$prototype}`);
|
|
267053
267091
|
})}
|
|
267054
|
-
|
|
267092
|
+
${signalFieldRow("Prototype", def3.$prototype || "", (v) => {
|
|
267055
267093
|
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $prototype: v || undefined }));
|
|
267056
267094
|
pluginSchemaCache.delete(`${def3.$src}::${v}`);
|
|
267057
267095
|
})}
|
|
267096
|
+
`}
|
|
267058
267097
|
${def3.$export ? signalFieldRow("Export", def3.$export || "", (v) => transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $export: v || undefined }))) : nothing}
|
|
267059
267098
|
${schemaContent}
|
|
267060
267099
|
`;
|
|
@@ -268516,6 +268555,7 @@ init_workspace2();
|
|
|
268516
268555
|
// src/editor/context-menu.js
|
|
268517
268556
|
init_lit_html();
|
|
268518
268557
|
init_ref();
|
|
268558
|
+
init_html_to_jx();
|
|
268519
268559
|
init_store();
|
|
268520
268560
|
init_workspace2();
|
|
268521
268561
|
|
|
@@ -269016,17 +269056,93 @@ function renderLayersTemplate(ctx) {
|
|
|
269016
269056
|
}
|
|
269017
269057
|
|
|
269018
269058
|
// src/editor/context-menu.js
|
|
269019
|
-
|
|
269059
|
+
var JX_MIME = "web application/jx+json";
|
|
269060
|
+
function nodeToHtml(node2) {
|
|
269061
|
+
if (typeof node2 === "string")
|
|
269062
|
+
return node2;
|
|
269063
|
+
const tag3 = node2.tagName || "div";
|
|
269064
|
+
let attrs = "";
|
|
269065
|
+
if (node2.attributes) {
|
|
269066
|
+
for (const [k, v] of Object.entries(node2.attributes)) {
|
|
269067
|
+
attrs += v === "" ? ` ${k}` : ` ${k}="${v.replace(/"/g, """)}"`;
|
|
269068
|
+
}
|
|
269069
|
+
}
|
|
269070
|
+
if (node2.style) {
|
|
269071
|
+
const css = Object.entries(node2.style).map(([k, v]) => `${k}:${v}`).join(";");
|
|
269072
|
+
if (css)
|
|
269073
|
+
attrs += ` style="${css.replace(/"/g, """)}"`;
|
|
269074
|
+
}
|
|
269075
|
+
let inner = "";
|
|
269076
|
+
if (node2.textContent) {
|
|
269077
|
+
inner = node2.textContent;
|
|
269078
|
+
} else if (node2.children) {
|
|
269079
|
+
inner = node2.children.map((c) => nodeToHtml(c)).join("");
|
|
269080
|
+
}
|
|
269081
|
+
return `<${tag3}${attrs}>${inner}</${tag3}>`;
|
|
269082
|
+
}
|
|
269083
|
+
async function writeToClipboard(json2) {
|
|
269084
|
+
workspace.clipboard = json2;
|
|
269085
|
+
try {
|
|
269086
|
+
await navigator.clipboard.write([
|
|
269087
|
+
new ClipboardItem({
|
|
269088
|
+
[JX_MIME]: new Blob([JSON.stringify(json2)], { type: JX_MIME }),
|
|
269089
|
+
"text/html": new Blob([nodeToHtml(json2)], { type: "text/html" })
|
|
269090
|
+
})
|
|
269091
|
+
]);
|
|
269092
|
+
} catch {
|
|
269093
|
+
try {
|
|
269094
|
+
await navigator.clipboard.writeText(JSON.stringify(json2));
|
|
269095
|
+
} catch {}
|
|
269096
|
+
}
|
|
269097
|
+
}
|
|
269098
|
+
async function readFromClipboard() {
|
|
269099
|
+
try {
|
|
269100
|
+
const items = await navigator.clipboard.read();
|
|
269101
|
+
for (const item of items) {
|
|
269102
|
+
if (item.types.includes(JX_MIME)) {
|
|
269103
|
+
const blob = await item.getType(JX_MIME);
|
|
269104
|
+
const json2 = JSON.parse(await blob.text());
|
|
269105
|
+
return [json2];
|
|
269106
|
+
}
|
|
269107
|
+
if (item.types.includes("text/html")) {
|
|
269108
|
+
const blob = await item.getType("text/html");
|
|
269109
|
+
const htmlStr = await blob.text();
|
|
269110
|
+
const nodes = htmlToJx(htmlStr);
|
|
269111
|
+
const jxNodes = nodes.map((n2) => typeof n2 === "string" ? { tagName: "p", textContent: n2 } : n2);
|
|
269112
|
+
if (jxNodes.length > 0)
|
|
269113
|
+
return jxNodes;
|
|
269114
|
+
}
|
|
269115
|
+
if (item.types.includes("text/plain")) {
|
|
269116
|
+
const blob = await item.getType("text/plain");
|
|
269117
|
+
const text6 = await blob.text();
|
|
269118
|
+
try {
|
|
269119
|
+
const parsed = JSON.parse(text6);
|
|
269120
|
+
if (parsed && parsed.tagName)
|
|
269121
|
+
return [parsed];
|
|
269122
|
+
} catch {}
|
|
269123
|
+
if (text6.trim())
|
|
269124
|
+
return [{ tagName: "p", textContent: text6.trim() }];
|
|
269125
|
+
}
|
|
269126
|
+
}
|
|
269127
|
+
} catch {
|
|
269128
|
+
if (workspace.clipboard) {
|
|
269129
|
+
return [JSON.parse(JSON.stringify(workspace.clipboard))];
|
|
269130
|
+
}
|
|
269131
|
+
}
|
|
269132
|
+
return null;
|
|
269133
|
+
}
|
|
269134
|
+
async function copyNode() {
|
|
269020
269135
|
const tab = activeTab.value;
|
|
269021
269136
|
if (!tab?.session.selection)
|
|
269022
269137
|
return;
|
|
269023
269138
|
const node2 = getNodeAtPath(tab.doc.document, tab.session.selection);
|
|
269024
269139
|
if (!node2)
|
|
269025
269140
|
return;
|
|
269026
|
-
|
|
269141
|
+
const json2 = JSON.parse(JSON.stringify(node2));
|
|
269142
|
+
await writeToClipboard(json2);
|
|
269027
269143
|
statusMessage("Copied");
|
|
269028
269144
|
}
|
|
269029
|
-
function cutNode() {
|
|
269145
|
+
async function cutNode() {
|
|
269030
269146
|
const tab = activeTab.value;
|
|
269031
269147
|
if (!tab?.session.selection || tab.session.selection.length < 2)
|
|
269032
269148
|
return;
|
|
@@ -269034,17 +269150,18 @@ function cutNode() {
|
|
|
269034
269150
|
const node2 = getNodeAtPath(tab.doc.document, sel);
|
|
269035
269151
|
if (!node2)
|
|
269036
269152
|
return;
|
|
269037
|
-
|
|
269153
|
+
const json2 = JSON.parse(JSON.stringify(node2));
|
|
269154
|
+
await writeToClipboard(json2);
|
|
269038
269155
|
transactDoc(tab, (t) => mutateRemoveNode(t, sel));
|
|
269039
269156
|
statusMessage("Cut");
|
|
269040
269157
|
}
|
|
269041
|
-
function pasteNode() {
|
|
269042
|
-
if (!workspace.clipboard)
|
|
269043
|
-
return;
|
|
269158
|
+
async function pasteNode() {
|
|
269044
269159
|
const tab = activeTab.value;
|
|
269045
269160
|
if (!tab)
|
|
269046
269161
|
return;
|
|
269047
|
-
const
|
|
269162
|
+
const nodes = await readFromClipboard();
|
|
269163
|
+
if (!nodes || nodes.length === 0)
|
|
269164
|
+
return;
|
|
269048
269165
|
const pPath = tab.session.selection || [];
|
|
269049
269166
|
const parent = getNodeAtPath(tab.doc.document, pPath);
|
|
269050
269167
|
if (!parent)
|
|
@@ -269052,10 +269169,18 @@ function pasteNode() {
|
|
|
269052
269169
|
if (tab.session.selection && tab.session.selection.length >= 2) {
|
|
269053
269170
|
const pp = parentElementPath(tab.session.selection);
|
|
269054
269171
|
const idx = childIndex(tab.session.selection);
|
|
269055
|
-
transactDoc(tab, (t) =>
|
|
269172
|
+
transactDoc(tab, (t) => {
|
|
269173
|
+
for (let i2 = 0;i2 < nodes.length; i2++) {
|
|
269174
|
+
mutateInsertNode(t, pp, idx + 1 + i2, nodes[i2]);
|
|
269175
|
+
}
|
|
269176
|
+
});
|
|
269056
269177
|
} else {
|
|
269057
269178
|
const idx = parent.children ? parent.children.length : 0;
|
|
269058
|
-
transactDoc(tab, (t) =>
|
|
269179
|
+
transactDoc(tab, (t) => {
|
|
269180
|
+
for (let i2 = 0;i2 < nodes.length; i2++) {
|
|
269181
|
+
mutateInsertNode(t, pPath, idx + i2, nodes[i2]);
|
|
269182
|
+
}
|
|
269183
|
+
});
|
|
269059
269184
|
}
|
|
269060
269185
|
statusMessage("Pasted");
|
|
269061
269186
|
}
|
|
@@ -269159,26 +269284,39 @@ function showContextMenu(e, path2, opts = {}) {
|
|
|
269159
269284
|
danger: true
|
|
269160
269285
|
});
|
|
269161
269286
|
}
|
|
269162
|
-
if (
|
|
269163
|
-
const clip = workspace.clipboard;
|
|
269287
|
+
if (path2.length >= 2) {
|
|
269164
269288
|
items.push({ label: "—" });
|
|
269165
269289
|
items.push({
|
|
269166
269290
|
label: "Paste inside",
|
|
269167
|
-
action: () => {
|
|
269291
|
+
action: async () => {
|
|
269292
|
+
const nodes = await readFromClipboard();
|
|
269293
|
+
if (!nodes || nodes.length === 0)
|
|
269294
|
+
return;
|
|
269168
269295
|
const idx = node2.children ? node2.children.length : 0;
|
|
269169
|
-
transactDoc(activeTab.value, (t) =>
|
|
269296
|
+
transactDoc(activeTab.value, (t) => {
|
|
269297
|
+
for (let i2 = 0;i2 < nodes.length; i2++) {
|
|
269298
|
+
mutateInsertNode(t, path2, idx + i2, nodes[i2]);
|
|
269299
|
+
}
|
|
269300
|
+
});
|
|
269301
|
+
statusMessage("Pasted");
|
|
269302
|
+
}
|
|
269303
|
+
});
|
|
269304
|
+
items.push({
|
|
269305
|
+
label: "Paste after",
|
|
269306
|
+
action: async () => {
|
|
269307
|
+
const nodes = await readFromClipboard();
|
|
269308
|
+
if (!nodes || nodes.length === 0)
|
|
269309
|
+
return;
|
|
269310
|
+
const pp = parentElementPath(path2);
|
|
269311
|
+
const idx = childIndex(path2);
|
|
269312
|
+
transactDoc(activeTab.value, (t) => {
|
|
269313
|
+
for (let i2 = 0;i2 < nodes.length; i2++) {
|
|
269314
|
+
mutateInsertNode(t, pp, idx + 1 + i2, nodes[i2]);
|
|
269315
|
+
}
|
|
269316
|
+
});
|
|
269317
|
+
statusMessage("Pasted");
|
|
269170
269318
|
}
|
|
269171
269319
|
});
|
|
269172
|
-
if (path2.length >= 2) {
|
|
269173
|
-
items.push({
|
|
269174
|
-
label: "Paste after",
|
|
269175
|
-
action: () => {
|
|
269176
|
-
const pp = parentElementPath(path2);
|
|
269177
|
-
const idx = childIndex(path2);
|
|
269178
|
-
transactDoc(activeTab.value, (t) => mutateInsertNode(t, pp, idx + 1, structuredClone(clip)));
|
|
269179
|
-
}
|
|
269180
|
-
});
|
|
269181
|
-
}
|
|
269182
269320
|
}
|
|
269183
269321
|
let { clientX: x, clientY: y } = e;
|
|
269184
269322
|
_ctxHandle = renderPopover(html3`<sp-popover
|
|
@@ -269266,7 +269404,8 @@ function onMouseMove(e) {
|
|
|
269266
269404
|
if (!_ctx8 || !_helper)
|
|
269267
269405
|
return;
|
|
269268
269406
|
const { getCanvasMode } = _ctx8;
|
|
269269
|
-
|
|
269407
|
+
const mode = getCanvasMode();
|
|
269408
|
+
if (mode !== "design" && mode !== "edit") {
|
|
269270
269409
|
hide2();
|
|
269271
269410
|
return;
|
|
269272
269411
|
}
|
|
@@ -270414,12 +270553,12 @@ function applyCanvasMediaOverrides(canvasEl, activeBreakpoints) {
|
|
|
270414
270553
|
if (!tab)
|
|
270415
270554
|
return;
|
|
270416
270555
|
const docMedia = getEffectiveMedia(tab.doc.document.$media || {});
|
|
270417
|
-
const
|
|
270556
|
+
const activeConditions = new Set;
|
|
270418
270557
|
for (const name of activeBreakpoints) {
|
|
270419
270558
|
if (docMedia[name])
|
|
270420
|
-
|
|
270559
|
+
activeConditions.add(docMedia[name]);
|
|
270421
270560
|
}
|
|
270422
|
-
const overrides = collectMediaOverrides(document.styleSheets,
|
|
270561
|
+
const overrides = collectMediaOverrides(document.styleSheets, activeConditions);
|
|
270423
270562
|
applyOverridesToCanvas(canvasEl, overrides);
|
|
270424
270563
|
}
|
|
270425
270564
|
function renderOverlays() {
|
|
@@ -271639,6 +271778,21 @@ function cleanupGoogleFontPreconnects(head) {
|
|
|
271639
271778
|
}
|
|
271640
271779
|
|
|
271641
271780
|
// src/panels/head-panel.js
|
|
271781
|
+
init_platform3();
|
|
271782
|
+
var layoutEntries = null;
|
|
271783
|
+
async function loadLayoutEntries() {
|
|
271784
|
+
try {
|
|
271785
|
+
const platform3 = getPlatform();
|
|
271786
|
+
const listing = await platform3.listDirectory("layouts");
|
|
271787
|
+
layoutEntries = listing.filter((f) => f.type === "file" && f.name.endsWith(".json")).map((f) => ({
|
|
271788
|
+
name: f.name.replace(/\.json$/, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
271789
|
+
path: `./layouts/${f.name}`
|
|
271790
|
+
}));
|
|
271791
|
+
} catch {
|
|
271792
|
+
layoutEntries = [];
|
|
271793
|
+
}
|
|
271794
|
+
renderOnly("leftPanel");
|
|
271795
|
+
}
|
|
271642
271796
|
var PAGE_FIELDS = [
|
|
271643
271797
|
{ label: "Description", attr: "name", key: "description" },
|
|
271644
271798
|
{ label: "Viewport", attr: "name", key: "viewport" }
|
|
@@ -271776,9 +271930,63 @@ function renderHeadTemplate({ document: doc, applyMutation, renderLeftPanel }) {
|
|
|
271776
271930
|
const tab = activeTab.value;
|
|
271777
271931
|
const isContent = tab?.doc.mode === "content";
|
|
271778
271932
|
const frontmatterSection = isContent ? renderFrontmatterSection() : nothing;
|
|
271933
|
+
const isPage = tab?.documentPath && projectState?.isSiteProject && (tab.documentPath.startsWith("pages/") || tab.documentPath.startsWith("./pages/"));
|
|
271934
|
+
let layoutSection = nothing;
|
|
271935
|
+
if (isPage) {
|
|
271936
|
+
if (layoutEntries === null) {
|
|
271937
|
+
loadLayoutEntries();
|
|
271938
|
+
} else {
|
|
271939
|
+
const currentLayout = doc.$layout;
|
|
271940
|
+
const defaultLayout = projectState?.projectConfig?.defaults?.layout;
|
|
271941
|
+
const displayValue = currentLayout === false ? "__none__" : currentLayout ? currentLayout : "__default__";
|
|
271942
|
+
const defaultLabel = defaultLayout ? defaultLayout.replace(/^\.\/layouts\//, "").replace(/\.json$/, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) : "";
|
|
271943
|
+
layoutSection = html3`
|
|
271944
|
+
<div class="imports-section">
|
|
271945
|
+
<div class="imports-section-header">
|
|
271946
|
+
<span class="imports-section-title">Layout</span>
|
|
271947
|
+
</div>
|
|
271948
|
+
<div class="head-section-body">
|
|
271949
|
+
${renderFieldRow({
|
|
271950
|
+
prop: "layout",
|
|
271951
|
+
label: "Layout",
|
|
271952
|
+
hasValue: currentLayout !== undefined,
|
|
271953
|
+
onClear: () => applyMutation((d2) => {
|
|
271954
|
+
delete d2.$layout;
|
|
271955
|
+
}),
|
|
271956
|
+
widget: html3`
|
|
271957
|
+
<sp-picker
|
|
271958
|
+
size="s"
|
|
271959
|
+
value=${displayValue}
|
|
271960
|
+
@change=${(e) => {
|
|
271961
|
+
const val = e.target.value;
|
|
271962
|
+
applyMutation((d2) => {
|
|
271963
|
+
if (val === "__default__")
|
|
271964
|
+
delete d2.$layout;
|
|
271965
|
+
else if (val === "__none__")
|
|
271966
|
+
d2.$layout = false;
|
|
271967
|
+
else
|
|
271968
|
+
d2.$layout = val;
|
|
271969
|
+
});
|
|
271970
|
+
invalidateLayoutCache();
|
|
271971
|
+
}}
|
|
271972
|
+
>
|
|
271973
|
+
<sp-menu-item value="__default__"
|
|
271974
|
+
>Default${defaultLabel ? ` (${defaultLabel})` : ""}</sp-menu-item
|
|
271975
|
+
>
|
|
271976
|
+
<sp-menu-item value="__none__">None</sp-menu-item>
|
|
271977
|
+
<sp-menu-divider></sp-menu-divider>
|
|
271978
|
+
${layoutEntries.map((l) => html3`<sp-menu-item value=${l.path}>${l.name}</sp-menu-item>`)}
|
|
271979
|
+
</sp-picker>
|
|
271980
|
+
`
|
|
271981
|
+
})}
|
|
271982
|
+
</div>
|
|
271983
|
+
</div>
|
|
271984
|
+
`;
|
|
271985
|
+
}
|
|
271986
|
+
}
|
|
271779
271987
|
return html3`
|
|
271780
271988
|
<div class="imports-panel">
|
|
271781
|
-
${frontmatterSection}
|
|
271989
|
+
${frontmatterSection} ${layoutSection}
|
|
271782
271990
|
|
|
271783
271991
|
<!-- Page section -->
|
|
271784
271992
|
<div class="imports-section">
|
|
@@ -299628,7 +299836,7 @@ function renderHeadEditor(container) {
|
|
|
299628
299836
|
} else if (tag5 === "script") {
|
|
299629
299837
|
attrs.src = "";
|
|
299630
299838
|
} else if (tag5 === "style") {
|
|
299631
|
-
entry.
|
|
299839
|
+
entry.textContent = "";
|
|
299632
299840
|
}
|
|
299633
299841
|
headEntries.push(entry);
|
|
299634
299842
|
save();
|
|
@@ -299642,7 +299850,7 @@ function renderHeadEditor(container) {
|
|
|
299642
299850
|
const updateEntry = (idx, key, val) => {
|
|
299643
299851
|
const entry = headEntries[idx];
|
|
299644
299852
|
if (key === "content" && (entry.tagName === "script" || entry.tagName === "style")) {
|
|
299645
|
-
entry.
|
|
299853
|
+
entry.textContent = val;
|
|
299646
299854
|
} else {
|
|
299647
299855
|
if (!entry.attributes)
|
|
299648
299856
|
entry.attributes = {};
|
|
@@ -299752,7 +299960,7 @@ function renderEntryFields(entry, idx, updateEntry) {
|
|
|
299752
299960
|
<label class="settings-field-label">Script body</label>
|
|
299753
299961
|
<textarea
|
|
299754
299962
|
class="head-code-editor"
|
|
299755
|
-
.value=${entry.
|
|
299963
|
+
.value=${entry.textContent || ""}
|
|
299756
299964
|
@input=${onFieldChange("content")}
|
|
299757
299965
|
rows="6"
|
|
299758
299966
|
spellcheck="false"
|
|
@@ -299766,7 +299974,7 @@ function renderEntryFields(entry, idx, updateEntry) {
|
|
|
299766
299974
|
<label class="settings-field-label">Style body</label>
|
|
299767
299975
|
<textarea
|
|
299768
299976
|
class="head-code-editor"
|
|
299769
|
-
.value=${entry.
|
|
299977
|
+
.value=${entry.textContent || ""}
|
|
299770
299978
|
@input=${onFieldChange("content")}
|
|
299771
299979
|
rows="8"
|
|
299772
299980
|
spellcheck="false"
|
|
@@ -304057,6 +304265,47 @@ function styleSidebarTemplate(node2, activeMediaTab, activeSelector, effectiveSt
|
|
|
304057
304265
|
}
|
|
304058
304266
|
return false;
|
|
304059
304267
|
});
|
|
304268
|
+
const isOpen2 = isFiltering ? true : tab.session.ui.styleSections[sec.key] ?? false;
|
|
304269
|
+
if (!isOpen2) {
|
|
304270
|
+
return html3`
|
|
304271
|
+
<sp-accordion-item
|
|
304272
|
+
label=${sec.label}
|
|
304273
|
+
.open=${false}
|
|
304274
|
+
@sp-accordion-item-toggle=${(e20) => {
|
|
304275
|
+
activeTab.value.session.ui.styleSections = {
|
|
304276
|
+
...activeTab.value.session.ui.styleSections,
|
|
304277
|
+
[sec.key]: e20.target.open
|
|
304278
|
+
};
|
|
304279
|
+
}}
|
|
304280
|
+
>
|
|
304281
|
+
${sectionActiveProps.length > 0 ? html3`
|
|
304282
|
+
<span slot="heading" style="display:flex;align-items:center;gap:6px">
|
|
304283
|
+
${sec.label}
|
|
304284
|
+
<span
|
|
304285
|
+
class="set-dot set-dot--section"
|
|
304286
|
+
title="Clear all ${sec.label.toLowerCase()} properties"
|
|
304287
|
+
@click=${(e20) => {
|
|
304288
|
+
e20.stopPropagation();
|
|
304289
|
+
e20.preventDefault();
|
|
304290
|
+
transactDoc(activeTab.value, (t15) => {
|
|
304291
|
+
for (const { prop, entry } of sectionActiveProps) {
|
|
304292
|
+
if (activeStyle[prop] !== undefined)
|
|
304293
|
+
commitMutate(t15, prop, undefined);
|
|
304294
|
+
if (inferInputType(entry) === "shorthand") {
|
|
304295
|
+
for (const l of getLonghands(prop)) {
|
|
304296
|
+
if (activeStyle[l.name] !== undefined)
|
|
304297
|
+
commitMutate(t15, l.name, undefined);
|
|
304298
|
+
}
|
|
304299
|
+
}
|
|
304300
|
+
}
|
|
304301
|
+
});
|
|
304302
|
+
}}
|
|
304303
|
+
></span>
|
|
304304
|
+
</span>
|
|
304305
|
+
` : nothing}
|
|
304306
|
+
</sp-accordion-item>
|
|
304307
|
+
`;
|
|
304308
|
+
}
|
|
304060
304309
|
const rows = [];
|
|
304061
304310
|
for (const { prop, entry } of entries2) {
|
|
304062
304311
|
const val = activeStyle[prop];
|
|
@@ -304094,7 +304343,6 @@ function styleSidebarTemplate(node2, activeMediaTab, activeSelector, effectiveSt
|
|
|
304094
304343
|
}
|
|
304095
304344
|
if (isFiltering && rows.length === 0)
|
|
304096
304345
|
return nothing;
|
|
304097
|
-
const isOpen2 = isFiltering ? true : tab.session.ui.styleSections[sec.key] ?? false;
|
|
304098
304346
|
return html3`
|
|
304099
304347
|
<sp-accordion-item
|
|
304100
304348
|
label=${sec.label}
|
|
@@ -305153,17 +305401,17 @@ function mediaBreakpointRowTemplate(name, query3) {
|
|
|
305153
305401
|
</div>
|
|
305154
305402
|
`;
|
|
305155
305403
|
}
|
|
305156
|
-
var
|
|
305157
|
-
async function
|
|
305404
|
+
var layoutEntries2 = null;
|
|
305405
|
+
async function loadLayoutEntries2() {
|
|
305158
305406
|
try {
|
|
305159
305407
|
const platform4 = getPlatform();
|
|
305160
305408
|
const listing = await platform4.listDirectory("layouts");
|
|
305161
|
-
|
|
305409
|
+
layoutEntries2 = listing.filter((f) => f.type === "file" && f.name.endsWith(".json")).map((f) => ({
|
|
305162
305410
|
name: f.name.replace(/\.json$/, ""),
|
|
305163
305411
|
path: `./layouts/${f.name}`
|
|
305164
305412
|
}));
|
|
305165
305413
|
} catch {
|
|
305166
|
-
|
|
305414
|
+
layoutEntries2 = [];
|
|
305167
305415
|
}
|
|
305168
305416
|
renderOnly("rightPanel");
|
|
305169
305417
|
}
|
|
@@ -305176,8 +305424,8 @@ function renderPageSection(node2) {
|
|
|
305176
305424
|
const tab = activeTab.value;
|
|
305177
305425
|
if (!isPageDocument(tab.documentPath))
|
|
305178
305426
|
return nothing;
|
|
305179
|
-
if (
|
|
305180
|
-
|
|
305427
|
+
if (layoutEntries2 === null) {
|
|
305428
|
+
loadLayoutEntries2();
|
|
305181
305429
|
return nothing;
|
|
305182
305430
|
}
|
|
305183
305431
|
const currentLayout = node2.$layout;
|
|
@@ -305219,7 +305467,7 @@ function renderPageSection(node2) {
|
|
|
305219
305467
|
>
|
|
305220
305468
|
<sp-menu-item value="__none__">None</sp-menu-item>
|
|
305221
305469
|
<sp-menu-divider></sp-menu-divider>
|
|
305222
|
-
${
|
|
305470
|
+
${layoutEntries2.map((l) => html3`<sp-menu-item value=${l.path}>${l.name}</sp-menu-item>`)}
|
|
305223
305471
|
</sp-picker>
|
|
305224
305472
|
</div>
|
|
305225
305473
|
${effectivePath ? html3`<div style="font-size:10px;color:var(--fg-dim);padding:2px 0;font-style:italic">
|
|
@@ -306640,8 +306888,20 @@ var _scope5 = null;
|
|
|
306640
306888
|
var _rendering = false;
|
|
306641
306889
|
var _scheduled2 = false;
|
|
306642
306890
|
var _hasFocus = false;
|
|
306643
|
-
function
|
|
306644
|
-
|
|
306891
|
+
function _isTextInput(el) {
|
|
306892
|
+
if (!el)
|
|
306893
|
+
return false;
|
|
306894
|
+
const tag5 = el.tagName.toLowerCase();
|
|
306895
|
+
if (tag5 === "input" || tag5 === "textarea")
|
|
306896
|
+
return true;
|
|
306897
|
+
if (tag5 === "sp-textfield" || tag5 === "sp-number-field" || tag5 === "sp-search")
|
|
306898
|
+
return true;
|
|
306899
|
+
if (el.shadowRoot?.activeElement)
|
|
306900
|
+
return _isTextInput(el.shadowRoot.activeElement);
|
|
306901
|
+
return false;
|
|
306902
|
+
}
|
|
306903
|
+
function _onFocusIn(e21) {
|
|
306904
|
+
_hasFocus = _isTextInput(e21.target);
|
|
306645
306905
|
}
|
|
306646
306906
|
function _onFocusOut() {
|
|
306647
306907
|
_hasFocus = false;
|
|
@@ -306685,6 +306945,24 @@ function render6() {
|
|
|
306685
306945
|
queueMicrotask(_flush2);
|
|
306686
306946
|
}
|
|
306687
306947
|
}
|
|
306948
|
+
var _propsContainer = null;
|
|
306949
|
+
var _eventsContainer = null;
|
|
306950
|
+
var _styleContainer = null;
|
|
306951
|
+
var _assistantContainer = null;
|
|
306952
|
+
var _lastTab = null;
|
|
306953
|
+
function _ensureContainers() {
|
|
306954
|
+
if (_propsContainer)
|
|
306955
|
+
return;
|
|
306956
|
+
_propsContainer = document.createElement("div");
|
|
306957
|
+
_propsContainer.className = "panel-body";
|
|
306958
|
+
_eventsContainer = document.createElement("div");
|
|
306959
|
+
_eventsContainer.className = "panel-body";
|
|
306960
|
+
_styleContainer = document.createElement("div");
|
|
306961
|
+
_styleContainer.className = "panel-body";
|
|
306962
|
+
_assistantContainer = document.createElement("div");
|
|
306963
|
+
_assistantContainer.className = "panel-body";
|
|
306964
|
+
_assistantContainer.style.cssText = "display:flex;flex-direction:column;overflow:hidden";
|
|
306965
|
+
}
|
|
306688
306966
|
function _flush2() {
|
|
306689
306967
|
_scheduled2 = false;
|
|
306690
306968
|
if (!_ctx13)
|
|
@@ -306693,86 +306971,88 @@ function _flush2() {
|
|
|
306693
306971
|
return;
|
|
306694
306972
|
_rendering = true;
|
|
306695
306973
|
try {
|
|
306696
|
-
|
|
306697
|
-
|
|
306698
|
-
|
|
306699
|
-
try {
|
|
306974
|
+
const ctx = _ctx13;
|
|
306975
|
+
const aTab = activeTab.value;
|
|
306976
|
+
if (!aTab) {
|
|
306700
306977
|
rightPanel.textContent = "";
|
|
306701
|
-
|
|
306702
|
-
|
|
306703
|
-
|
|
306704
|
-
|
|
306978
|
+
return;
|
|
306979
|
+
}
|
|
306980
|
+
const S = {
|
|
306981
|
+
ui: aTab.session.ui,
|
|
306982
|
+
document: aTab.doc.document,
|
|
306983
|
+
mode: aTab.doc.mode,
|
|
306984
|
+
selection: aTab.session.selection
|
|
306985
|
+
};
|
|
306986
|
+
const tab = S.ui.rightTab;
|
|
306987
|
+
const panelTabs = [
|
|
306988
|
+
{ value: "properties", icon: "sp-icon-properties", label: "Properties" },
|
|
306989
|
+
{ value: "events", icon: "sp-icon-event", label: "Events" },
|
|
306990
|
+
{ value: "style", icon: "sp-icon-brush", label: "Style" },
|
|
306991
|
+
{ value: "assistant", icon: "sp-icon-chat", label: "Assistant" }
|
|
306992
|
+
];
|
|
306993
|
+
const tabsT = html3`
|
|
306994
|
+
<div class="panel-tabs">
|
|
306995
|
+
<sp-tabs
|
|
306996
|
+
selected=${tab}
|
|
306997
|
+
quiet
|
|
306998
|
+
@change=${(e21) => {
|
|
306999
|
+
const sel = e21.target.selected;
|
|
307000
|
+
if (sel && sel !== tab) {
|
|
307001
|
+
updateUi("rightTab", sel);
|
|
307002
|
+
render6();
|
|
307003
|
+
}
|
|
307004
|
+
}}
|
|
307005
|
+
>
|
|
307006
|
+
${panelTabs.map((t16) => html3`
|
|
307007
|
+
<sp-tab value=${t16.value} title=${t16.label} aria-label=${t16.label}>
|
|
307008
|
+
${tabIcon(t16.icon, "xs")}
|
|
307009
|
+
</sp-tab>
|
|
307010
|
+
`)}
|
|
307011
|
+
</sp-tabs>
|
|
307012
|
+
</div>
|
|
307013
|
+
`;
|
|
307014
|
+
_ensureContainers();
|
|
307015
|
+
const containers = [
|
|
307016
|
+
_propsContainer,
|
|
307017
|
+
_eventsContainer,
|
|
307018
|
+
_styleContainer,
|
|
307019
|
+
_assistantContainer
|
|
307020
|
+
];
|
|
307021
|
+
const tabKeys = ["properties", "events", "style", "assistant"];
|
|
307022
|
+
for (let i8 = 0;i8 < containers.length; i8++) {
|
|
307023
|
+
if (tabKeys[i8] === tab) {
|
|
307024
|
+
containers[i8].style.display = tabKeys[i8] === "assistant" ? "flex" : "";
|
|
307025
|
+
} else {
|
|
307026
|
+
containers[i8].style.display = "none";
|
|
307027
|
+
}
|
|
307028
|
+
}
|
|
307029
|
+
render2(tabsT, rightPanel);
|
|
307030
|
+
for (const c7 of containers) {
|
|
307031
|
+
if (!c7.parentNode)
|
|
307032
|
+
rightPanel.appendChild(c7);
|
|
306705
307033
|
}
|
|
307034
|
+
if (tab === "properties") {
|
|
307035
|
+
render2(renderPropertiesPanelTemplate({ navigateToComponent: ctx.navigateToComponent }), _propsContainer);
|
|
307036
|
+
} else if (tab === "events") {
|
|
307037
|
+
render2(eventsSidebarTemplate({ isCustomElementDoc: () => isCustomElementDoc(S) }), _eventsContainer);
|
|
307038
|
+
} else if (tab === "style") {
|
|
307039
|
+
try {
|
|
307040
|
+
render2(renderStylePanelTemplate({ getCanvasMode: ctx.getCanvasMode }), _styleContainer);
|
|
307041
|
+
} catch (e21) {
|
|
307042
|
+
console.error("[renderStylePanelTemplate]", e21);
|
|
307043
|
+
}
|
|
307044
|
+
} else if (tab === "assistant") {
|
|
307045
|
+
render2(renderAiPanelTemplate(), _assistantContainer);
|
|
307046
|
+
}
|
|
307047
|
+
_lastTab = tab;
|
|
307048
|
+
} catch (e21) {
|
|
307049
|
+
console.error("right-panel render error:", e21);
|
|
306706
307050
|
} finally {
|
|
306707
307051
|
_rendering = false;
|
|
306708
307052
|
}
|
|
306709
307053
|
requestAnimationFrame(() => mountQuikChat());
|
|
306710
307054
|
_ctx13.updateForcedPseudoPreview();
|
|
306711
307055
|
}
|
|
306712
|
-
function rightPanelTemplate() {
|
|
306713
|
-
const ctx = _ctx13;
|
|
306714
|
-
const aTab = activeTab.value;
|
|
306715
|
-
if (!aTab)
|
|
306716
|
-
return nothing;
|
|
306717
|
-
const S = {
|
|
306718
|
-
ui: aTab.session.ui,
|
|
306719
|
-
document: aTab.doc.document,
|
|
306720
|
-
mode: aTab.doc.mode,
|
|
306721
|
-
selection: aTab.session.selection
|
|
306722
|
-
};
|
|
306723
|
-
const tab = S.ui.rightTab;
|
|
306724
|
-
const panelTabs = [
|
|
306725
|
-
{ value: "properties", icon: "sp-icon-properties", label: "Properties" },
|
|
306726
|
-
{ value: "events", icon: "sp-icon-event", label: "Events" },
|
|
306727
|
-
{ value: "style", icon: "sp-icon-brush", label: "Style" },
|
|
306728
|
-
{ value: "assistant", icon: "sp-icon-chat", label: "Assistant" }
|
|
306729
|
-
];
|
|
306730
|
-
const tabsT = html3`
|
|
306731
|
-
<div class="panel-tabs">
|
|
306732
|
-
<sp-tabs
|
|
306733
|
-
selected=${tab}
|
|
306734
|
-
quiet
|
|
306735
|
-
@change=${(e21) => {
|
|
306736
|
-
const sel = e21.target.selected;
|
|
306737
|
-
if (sel && sel !== tab) {
|
|
306738
|
-
updateUi("rightTab", sel);
|
|
306739
|
-
}
|
|
306740
|
-
}}
|
|
306741
|
-
>
|
|
306742
|
-
${panelTabs.map((t16) => html3`
|
|
306743
|
-
<sp-tab value=${t16.value} title=${t16.label} aria-label=${t16.label}>
|
|
306744
|
-
${tabIcon(t16.icon, "xs")}
|
|
306745
|
-
</sp-tab>
|
|
306746
|
-
`)}
|
|
306747
|
-
</sp-tabs>
|
|
306748
|
-
</div>
|
|
306749
|
-
`;
|
|
306750
|
-
let bodyT = nothing;
|
|
306751
|
-
if (tab === "properties") {
|
|
306752
|
-
bodyT = renderPropertiesPanelTemplate({ navigateToComponent: ctx.navigateToComponent });
|
|
306753
|
-
} else if (tab === "events") {
|
|
306754
|
-
bodyT = eventsSidebarTemplate({
|
|
306755
|
-
isCustomElementDoc: () => isCustomElementDoc(S)
|
|
306756
|
-
});
|
|
306757
|
-
} else if (tab === "style") {
|
|
306758
|
-
try {
|
|
306759
|
-
bodyT = renderStylePanelTemplate({ getCanvasMode: ctx.getCanvasMode });
|
|
306760
|
-
} catch (e21) {
|
|
306761
|
-
console.error("[renderStylePanelTemplate]", e21);
|
|
306762
|
-
}
|
|
306763
|
-
} else if (tab === "assistant") {
|
|
306764
|
-
bodyT = renderAiPanelTemplate();
|
|
306765
|
-
}
|
|
306766
|
-
return html3`
|
|
306767
|
-
${tabsT}
|
|
306768
|
-
<div
|
|
306769
|
-
class="panel-body"
|
|
306770
|
-
style=${tab === "assistant" ? "display:flex;flex-direction:column;overflow:hidden" : ""}
|
|
306771
|
-
>
|
|
306772
|
-
${bodyT}
|
|
306773
|
-
</div>
|
|
306774
|
-
`;
|
|
306775
|
-
}
|
|
306776
307056
|
|
|
306777
307057
|
// src/panels/left-panel.js
|
|
306778
307058
|
init_lit_html();
|
|
@@ -307749,5 +308029,5 @@ effect(() => {
|
|
|
307749
308029
|
scheduleAutosave();
|
|
307750
308030
|
});
|
|
307751
308031
|
|
|
307752
|
-
//# debugId=
|
|
308032
|
+
//# debugId=44524F8AC477F4E864756E2164756E21
|
|
307753
308033
|
//# sourceMappingURL=studio.js.map
|