@jxsuite/studio 0.13.0 → 0.14.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 CHANGED
@@ -1435,8 +1435,8 @@ var init_reactivity = __esm(() => {
1435
1435
  // src/tabs/tab.js
1436
1436
  function createDefaultUi() {
1437
1437
  return {
1438
- leftTab: "layers",
1439
1438
  rightTab: "properties",
1439
+ canvasMode: "design",
1440
1440
  zoom: 1,
1441
1441
  activeMedia: null,
1442
1442
  activeSelector: null,
@@ -1460,7 +1460,14 @@ function createDefaultUi() {
1460
1460
  pendingInlineEdit: null
1461
1461
  };
1462
1462
  }
1463
- function createTab({ id, documentPath = null, fileHandle = null, document: document2, frontmatter }) {
1463
+ function createTab({
1464
+ id,
1465
+ documentPath = null,
1466
+ fileHandle = null,
1467
+ document: document2,
1468
+ frontmatter,
1469
+ sourceFormat = null
1470
+ }) {
1464
1471
  const scope = effectScope();
1465
1472
  const tab = scope.run(() => ({
1466
1473
  id,
@@ -1469,8 +1476,9 @@ function createTab({ id, documentPath = null, fileHandle = null, document: docum
1469
1476
  scope,
1470
1477
  doc: reactive({
1471
1478
  document: document2,
1479
+ sourceFormat,
1472
1480
  content: { frontmatter: frontmatter || {} },
1473
- mode: documentPath?.endsWith(".md") ? "content" : "component",
1481
+ mode: sourceFormat === "md" ? "content" : documentPath?.endsWith(".md") ? "content" : "component",
1474
1482
  handlersSource: null,
1475
1483
  dirty: false
1476
1484
  }),
@@ -1497,6 +1505,14 @@ var init_tab = __esm(() => {
1497
1505
  });
1498
1506
 
1499
1507
  // src/workspace/workspace.js
1508
+ var exports_workspace = {};
1509
+ __export(exports_workspace, {
1510
+ workspace: () => workspace,
1511
+ openTab: () => openTab,
1512
+ closeTab: () => closeTab,
1513
+ activeTab: () => activeTab,
1514
+ activateTab: () => activateTab
1515
+ });
1500
1516
  function openTab(opts) {
1501
1517
  const tab = createTab(opts);
1502
1518
  workspace.tabs.set(tab.id, tab);
@@ -1625,124 +1641,9 @@ function nodeLabel(node) {
1625
1641
  }
1626
1642
  return tag + suffix;
1627
1643
  }
1628
- function createState(doc) {
1629
- const initial = { document: doc, selection: null };
1630
- return {
1631
- document: doc,
1632
- selection: null,
1633
- hover: null,
1634
- history: [initial],
1635
- historyIndex: 0,
1636
- dirty: false,
1637
- fileHandle: null,
1638
- documentPath: null,
1639
- documentStack: [],
1640
- handlersSource: null,
1641
- mode: "component",
1642
- content: { frontmatter: {} },
1643
- ui: {
1644
- leftTab: "layers",
1645
- rightTab: "properties",
1646
- zoom: 1,
1647
- activeMedia: null,
1648
- activeSelector: null,
1649
- featureToggles: {},
1650
- styleSections: {},
1651
- inspectorSections: {},
1652
- styleShorthands: {},
1653
- styleFilter: "",
1654
- styleFilterActive: false,
1655
- editingFunction: null,
1656
- stylebookSelection: null,
1657
- stylebookTab: "elements",
1658
- stylebookFilter: "",
1659
- stylebookCustomizedOnly: false,
1660
- settingsTab: "stylebook",
1661
- gitStatus: null,
1662
- gitBranches: null,
1663
- gitCommitMessage: "",
1664
- gitLoading: false,
1665
- gitError: null,
1666
- pendingInlineEdit: null
1667
- },
1668
- canvas: {
1669
- status: "idle",
1670
- scope: null,
1671
- error: null
1672
- }
1673
- };
1674
- }
1675
- function toFlat(doc, session) {
1676
- return { ...doc, ...session };
1677
- }
1678
- function fromFlat(S) {
1679
- const {
1680
- document: document2,
1681
- dirty,
1682
- fileHandle,
1683
- documentPath,
1684
- documentStack,
1685
- handlersSource,
1686
- mode,
1687
- content,
1688
- history,
1689
- historyIndex,
1690
- selection,
1691
- hover,
1692
- ui,
1693
- canvas
1694
- } = S;
1695
- return {
1696
- doc: {
1697
- document: document2,
1698
- dirty,
1699
- fileHandle,
1700
- documentPath,
1701
- documentStack,
1702
- handlersSource,
1703
- mode,
1704
- content,
1705
- history,
1706
- historyIndex
1707
- },
1708
- session: { selection, hover, ui, canvas }
1709
- };
1710
- }
1711
1644
  function setProjectState(ps) {
1712
1645
  projectState = ps;
1713
1646
  }
1714
- function hoverNode(state, path) {
1715
- return { ...state, hover: path };
1716
- }
1717
- function pushDocument(state, doc, documentPath) {
1718
- const frame = {
1719
- document: state.document,
1720
- selection: state.selection,
1721
- fileHandle: state.fileHandle,
1722
- documentPath: state.documentPath,
1723
- dirty: state.dirty,
1724
- history: state.history,
1725
- historyIndex: state.historyIndex,
1726
- mode: state.mode
1727
- };
1728
- const newState = createState(doc);
1729
- newState.documentStack = [...state.documentStack || [], frame];
1730
- newState.documentPath = documentPath;
1731
- newState.ui = { ...state.ui, leftTab: "layers", activeMedia: null, activeSelector: null };
1732
- return newState;
1733
- }
1734
- function popDocument(state) {
1735
- if (!state.documentStack || state.documentStack.length === 0)
1736
- return state;
1737
- const stack = [...state.documentStack];
1738
- const frame = stack.pop();
1739
- return {
1740
- ...state,
1741
- ...frame,
1742
- documentStack: stack,
1743
- ui: { ...state.ui, leftTab: "layers" }
1744
- };
1745
- }
1746
1647
  var projectState = null;
1747
1648
 
1748
1649
  // src/store.js
@@ -1814,36 +1715,6 @@ function renderOnly(...names) {
1814
1715
  }
1815
1716
  }
1816
1717
  }
1817
- function setUpdateFn(fn) {
1818
- _updateFn = fn;
1819
- }
1820
- function setGetStateFn(fn) {
1821
- _getStateFn = fn;
1822
- }
1823
- function getState() {
1824
- const tab = activeTab.value;
1825
- if (tab) {
1826
- return {
1827
- document: tab.doc.document,
1828
- mode: tab.doc.mode,
1829
- dirty: tab.doc.dirty,
1830
- handlersSource: tab.doc.handlersSource,
1831
- content: tab.doc.content,
1832
- documentPath: tab.documentPath,
1833
- fileHandle: tab.fileHandle,
1834
- selection: tab.session.selection,
1835
- hover: tab.session.hover,
1836
- clipboard: tab.session.clipboard,
1837
- ui: tab.session.ui,
1838
- canvas: tab.session.canvas,
1839
- documentStack: tab.session.documentStack
1840
- };
1841
- }
1842
- return _getStateFn();
1843
- }
1844
- function setUpdateSessionFn(fn) {
1845
- _updateSessionFn = fn;
1846
- }
1847
1718
  function updateSession(patch) {
1848
1719
  const tab = activeTab.value;
1849
1720
  if (tab) {
@@ -1865,14 +1736,12 @@ function updateSession(patch) {
1865
1736
  }
1866
1737
  }
1867
1738
  }
1868
- _updateSessionFn(patch);
1869
1739
  }
1870
1740
  function updateUi(field, value) {
1871
1741
  const tab = activeTab.value;
1872
1742
  if (tab) {
1873
1743
  tab.session.ui[field] = value;
1874
1744
  }
1875
- _updateSessionFn({ ui: { [field]: value } });
1876
1745
  }
1877
1746
  function updateCanvas(patch) {
1878
1747
  const tab = activeTab.value;
@@ -1881,27 +1750,8 @@ function updateCanvas(patch) {
1881
1750
  tab.session.canvas[k] = v;
1882
1751
  }
1883
1752
  }
1884
- _updateSessionFn({ canvas: patch });
1885
- }
1886
- function addUpdateMiddleware(fn) {
1887
- _updateMiddleware.push(fn);
1888
- }
1889
- function runUpdateMiddleware(state) {
1890
- for (const mw of _updateMiddleware)
1891
- mw(state);
1892
1753
  }
1893
- function addPostRenderHook(fn) {
1894
- _postRenderHooks.push(fn);
1895
- }
1896
- function runPostRenderHooks(prevDoc, prevSel) {
1897
- for (const hook of _postRenderHooks)
1898
- hook(prevDoc, prevSel);
1899
- }
1900
- var canvasWrap, activityBar, leftPanel, rightPanel, toolbarEl, statusbarEl, elToPath, canvasPanels, VOID_ELEMENTS, COMMON_SELECTORS, _styleDebounceTimers, _renderers, _updateFn = () => {
1901
- throw new Error("update() called before setUpdateFn() — bootstrap not complete");
1902
- }, _getStateFn = () => null, _updateSessionFn = () => {
1903
- throw new Error("updateSession() called before setUpdateSessionFn() — bootstrap not complete");
1904
- }, _updateMiddleware, _postRenderHooks;
1754
+ var canvasWrap, activityBar, leftPanel, rightPanel, toolbarEl, statusbarEl, elToPath, canvasPanels, VOID_ELEMENTS, COMMON_SELECTORS, _styleDebounceTimers, _renderers;
1905
1755
  var init_store = __esm(() => {
1906
1756
  init_workspace();
1907
1757
  canvasWrap = document.querySelector("#canvas-wrap");
@@ -1943,8 +1793,6 @@ var init_store = __esm(() => {
1943
1793
  ];
1944
1794
  _styleDebounceTimers = new Map;
1945
1795
  _renderers = new Map;
1946
- _updateMiddleware = [];
1947
- _postRenderHooks = [];
1948
1796
  });
1949
1797
 
1950
1798
  // ../../node_modules/bind-event-listener/dist/bind.js
@@ -42770,6 +42618,7 @@ var view = {
42770
42618
  showAddBreakpointForm: false,
42771
42619
  addBreakpointPreview: "",
42772
42620
  layoutSelection: null,
42621
+ leftTab: "layers",
42773
42622
  autosaveTimer: null
42774
42623
  };
42775
42624
  // data/elements-meta.json
@@ -46364,22 +46213,19 @@ function mountStatusbar() {
46364
46213
  tab.doc.document;
46365
46214
  tab.doc.mode;
46366
46215
  tab.session.selection;
46367
- renderStatusbar({
46368
- mode: tab.doc.mode,
46369
- document: tab.doc.document,
46370
- selection: tab.session.selection
46371
- });
46216
+ renderStatusbar();
46372
46217
  });
46373
46218
  });
46374
46219
  }
46375
- function renderStatusbar(S) {
46220
+ function renderStatusbar() {
46221
+ const tab = activeTab.value;
46376
46222
  const parts = [];
46377
- if (S.mode === "content")
46223
+ if (tab?.doc.mode === "content")
46378
46224
  parts.push("Content Mode");
46379
- if (S.selection) {
46380
- const node = getNodeAtPath(S.document, S.selection);
46225
+ if (tab?.session.selection) {
46226
+ const node = getNodeAtPath(tab.doc.document, tab.session.selection);
46381
46227
  parts.push(`Selected: ${nodeLabel(node)}`);
46382
- parts.push(`Path: ${S.selection.join(" > ") || "root"}`);
46228
+ parts.push(`Path: ${tab.session.selection.join(" > ") || "root"}`);
46383
46229
  }
46384
46230
  if (statusMsg)
46385
46231
  parts.push(statusMsg);
@@ -47041,8 +46887,7 @@ function enterComponentInlineEdit(el, path) {
47041
46887
  if (view.componentInlineEdit && view.componentInlineEdit.el === el) {
47042
46888
  return;
47043
46889
  }
47044
- const S = getState();
47045
- const node = getNodeAtPath(S.document, path);
46890
+ const node = getNodeAtPath(activeTab.value?.doc.document, path);
47046
46891
  if (!node)
47047
46892
  return;
47048
46893
  const tc = node.textContent;
@@ -47443,8 +47288,7 @@ function enterInlineEdit(el, path) {
47443
47288
  }
47444
47289
  startEditing(el, path, {
47445
47290
  onCommit(commitPath, children, textContent) {
47446
- const S = getState();
47447
- const node = getNodeAtPath(S.document, commitPath);
47291
+ const node = getNodeAtPath(activeTab.value?.doc.document, commitPath);
47448
47292
  if (children) {
47449
47293
  if (node && JSON.stringify(node.children) === JSON.stringify(children))
47450
47294
  return;
@@ -47968,9 +47812,7 @@ function applyTransform() {
47968
47812
  return;
47969
47813
  const zoom = _ctx4.getZoom();
47970
47814
  view.panzoomWrap.style.transform = `translate(${view.panX}px, ${view.panY}px) scale(${zoom})`;
47971
- const label = document.querySelector(".zoom-indicator-label");
47972
- if (label)
47973
- label.textContent = `${Math.round(zoom * 100)}%`;
47815
+ renderZoomIndicator();
47974
47816
  renderOnly("overlays");
47975
47817
  if (_ctx4.getCanvasMode() === "settings")
47976
47818
  _ctx4.renderStylebookOverlays();
@@ -175185,6 +175027,23 @@ async function renderCanvasLive(gen, doc, canvasEl) {
175185
175027
  } else {
175186
175028
  canvasEl.removeAttribute("data-content-mode");
175187
175029
  }
175030
+ const platform3 = globalThis.__jxPlatform;
175031
+ if (platform3?.resolveAssetUrl && docBase) {
175032
+ const mediaEls = el.querySelectorAll("img[src], video[src], source[src], video[poster]");
175033
+ for (const node of mediaEls) {
175034
+ for (const attr of ["src", "poster"]) {
175035
+ const val = node.getAttribute(attr);
175036
+ if (val && !val.startsWith("data:") && !val.startsWith("blob:") && !val.startsWith("http")) {
175037
+ try {
175038
+ const resolved = new URL(val, docBase).pathname.replace(/^\//, "");
175039
+ const dataUrl = await platform3.resolveAssetUrl(resolved);
175040
+ if (dataUrl)
175041
+ node.setAttribute(attr, dataUrl);
175042
+ } catch {}
175043
+ }
175044
+ }
175045
+ }
175046
+ }
175188
175047
  canvasEl.appendChild(el);
175189
175048
  if (canvasMode === "design" || canvasMode === "edit") {
175190
175049
  requestAnimationFrame(() => {
@@ -175207,6 +175066,7 @@ async function renderCanvasLive(gen, doc, canvasEl) {
175207
175066
 
175208
175067
  // src/panels/preview-render.js
175209
175068
  init_store();
175069
+ init_workspace();
175210
175070
 
175211
175071
  // src/panels/signals-panel.js
175212
175072
  init_workspace();
@@ -176126,7 +175986,7 @@ function renderCanvasNode(node, path, parent, activeBreakpoints, featureToggles)
176126
175986
  if (typeof node.textContent === "string") {
176127
175987
  el.textContent = node.textContent;
176128
175988
  } else if (typeof node.textContent === "object" && node.textContent?.$ref) {
176129
- const resolved = resolveDefaultForCanvas(node.textContent, getState().document.state);
175989
+ const resolved = resolveDefaultForCanvas(node.textContent, activeTab.value?.doc.document?.state);
176130
175990
  el.textContent = resolved;
176131
175991
  el.style.opacity = "0.7";
176132
175992
  el.style.fontStyle = "italic";
@@ -176141,7 +176001,7 @@ function renderCanvasNode(node, path, parent, activeBreakpoints, featureToggles)
176141
176001
  for (const [attr, val] of Object.entries(node.attributes)) {
176142
176002
  try {
176143
176003
  if (typeof val === "object" && val?.$ref) {
176144
- const resolved = resolveDefaultForCanvas(val, getState().document.state);
176004
+ const resolved = resolveDefaultForCanvas(val, activeTab.value?.doc.document?.state);
176145
176005
  el.setAttribute(attr, resolved);
176146
176006
  } else {
176147
176007
  el.setAttribute(attr, val);
@@ -176177,6 +176037,7 @@ function renderCanvasNode(node, path, parent, activeBreakpoints, featureToggles)
176177
176037
 
176178
176038
  // src/panels/canvas-dnd.js
176179
176039
  init_store();
176040
+ init_workspace();
176180
176041
  // ../../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js
176181
176042
  function _objectWithoutPropertiesLoose(r, e) {
176182
176043
  if (r == null)
@@ -177647,8 +177508,7 @@ registerBlockType( name, settings );`
177647
177508
  var _ctx6 = null;
177648
177509
  function renderStylebookMode(ctx) {
177649
177510
  _ctx6 = ctx;
177650
- const S = getState();
177651
- const settingsTab = S.ui.settingsTab || "stylebook";
177511
+ const settingsTab = activeTab.value?.session.ui.settingsTab || "stylebook";
177652
177512
  const settingsChromeBarTpl = html`
177653
177513
  <div
177654
177514
  class="sb-chrome settings-top-chrome"
@@ -177682,10 +177542,11 @@ function renderStylebookMode(ctx) {
177682
177542
  return;
177683
177543
  }
177684
177544
  view.stylebookElToTag = new WeakMap;
177685
- const rootStyle = getEffectiveStyle(S.document.style);
177686
- const filter = (S.ui.stylebookFilter || "").toLowerCase();
177687
- const customizedOnly = S.ui.stylebookCustomizedOnly;
177688
- const { sizeBreakpoints, baseWidth } = parseMediaEntries(getEffectiveMedia(S.document.$media));
177545
+ const tab = activeTab.value;
177546
+ const rootStyle = getEffectiveStyle(tab?.doc.document?.style);
177547
+ const filter = (tab?.session.ui.stylebookFilter || "").toLowerCase();
177548
+ const customizedOnly = tab?.session.ui.stylebookCustomizedOnly;
177549
+ const { sizeBreakpoints, baseWidth } = parseMediaEntries(getEffectiveMedia(tab?.doc.document?.$media));
177689
177550
  const hasMedia = sizeBreakpoints.length > 0;
177690
177551
  const onTabClick = (t) => {
177691
177552
  updateUi("stylebookTab", t);
@@ -177694,7 +177555,7 @@ function renderStylebookMode(ctx) {
177694
177555
  updateUi("stylebookFilter", e.target.value);
177695
177556
  };
177696
177557
  const onCustomizedToggle = () => {
177697
- updateUi("stylebookCustomizedOnly", !S.ui.stylebookCustomizedOnly);
177558
+ updateUi("stylebookCustomizedOnly", !tab?.session.ui.stylebookCustomizedOnly);
177698
177559
  };
177699
177560
  const chromeBarTpl = html`
177700
177561
  ${settingsChromeBarTpl}
@@ -177704,7 +177565,7 @@ function renderStylebookMode(ctx) {
177704
177565
  >
177705
177566
  <sp-tabs
177706
177567
  size="s"
177707
- selected=${S.ui.stylebookTab || "elements"}
177568
+ selected=${tab?.session.ui.stylebookTab || "elements"}
177708
177569
  @change=${(e) => {
177709
177570
  onTabClick(e.target.selected);
177710
177571
  }}
@@ -177713,16 +177574,16 @@ function renderStylebookMode(ctx) {
177713
177574
  <sp-tab label=${t.charAt(0).toUpperCase() + t.slice(1)} value=${t}></sp-tab>
177714
177575
  `)}
177715
177576
  </sp-tabs>
177716
- ${S.ui.stylebookTab === "elements" ? html`
177577
+ ${tab?.session.ui.stylebookTab === "elements" ? html`
177717
177578
  <input
177718
177579
  class="field-input"
177719
177580
  style="flex:1;max-width:200px;margin-left:8px"
177720
177581
  placeholder="Filter…"
177721
- .value=${S.ui.stylebookFilter}
177582
+ .value=${tab?.session.ui.stylebookFilter}
177722
177583
  @input=${onFilterInput2}
177723
177584
  />
177724
177585
  <button
177725
- class="tb-toggle${S.ui.stylebookCustomizedOnly ? " active" : ""}"
177586
+ class="tb-toggle${tab?.session.ui.stylebookCustomizedOnly ? " active" : ""}"
177726
177587
  style="margin-left:4px"
177727
177588
  @click=${onCustomizedToggle}
177728
177589
  >
@@ -177751,7 +177612,7 @@ function renderStylebookMode(ctx) {
177751
177612
  }
177752
177613
  const renderIntoPanel = (panel, activeBreakpoints) => {
177753
177614
  panel.canvas.classList.add("sb-canvas");
177754
- if (S.ui.stylebookTab === "elements") {
177615
+ if (tab?.session.ui.stylebookTab === "elements") {
177755
177616
  renderStylebookElementsIntoCanvas(panel.canvas, rootStyle, filter, customizedOnly, activeBreakpoints);
177756
177617
  for (const child of panel.canvas.querySelectorAll("*")) {
177757
177618
  child.style.pointerEvents = "none";
@@ -177764,7 +177625,7 @@ function renderStylebookMode(ctx) {
177764
177625
  };
177765
177626
  let panelEntries;
177766
177627
  if (!hasMedia) {
177767
- const effectiveMedia = getEffectiveMedia(S.document.$media);
177628
+ const effectiveMedia = getEffectiveMedia(tab?.doc.document?.$media);
177768
177629
  const hasBaseWidth = effectiveMedia && effectiveMedia["--"];
177769
177630
  const label = hasBaseWidth ? `${mediaDisplayName("--")} (${baseWidth}px)` : null;
177770
177631
  const entry = ctx.canvasPanelTemplate(hasBaseWidth ? "base" : null, label, !hasBaseWidth, hasBaseWidth ? baseWidth : undefined);
@@ -177817,8 +177678,7 @@ function renderStylebookOverlays() {
177817
177678
  return;
177818
177679
  if (canvasPanels.length === 0)
177819
177680
  return;
177820
- const S = getState();
177821
- const selectedTag = S.ui.stylebookSelection;
177681
+ const selectedTag = activeTab.value?.session.ui.stylebookSelection;
177822
177682
  for (const panel of canvasPanels) {
177823
177683
  const hoverTag = panel._lastHoverTag;
177824
177684
  const boxes = [];
@@ -178507,6 +178367,7 @@ function registerLayersDnD() {
178507
178367
  const rowPath = row.dataset.path.split("/").map((s) => /^\d+$/.test(s) ? parseInt(s) : s);
178508
178368
  const rowDepth = parseInt(row.dataset.dndDepth) || 0;
178509
178369
  const isVoid = row.hasAttribute("data-dnd-void");
178370
+ const isExpanded = row.hasAttribute("data-dnd-expanded");
178510
178371
  const cleanup = combine(draggable({
178511
178372
  element: row,
178512
178373
  canDrag({ element: _el, input }) {
@@ -178521,9 +178382,15 @@ function registerLayersDnD() {
178521
178382
  onDragStart() {
178522
178383
  row.classList.add("dragging");
178523
178384
  view.layerDragSourceHeight = row.offsetHeight;
178385
+ if (isExpanded) {
178386
+ hideDescendantRows(row, container);
178387
+ }
178524
178388
  },
178525
178389
  onDrop() {
178526
178390
  row.classList.remove("dragging");
178391
+ if (isExpanded) {
178392
+ renderOnly("leftPanel");
178393
+ }
178527
178394
  }
178528
178395
  }), dropTargetForElements({
178529
178396
  element: row,
@@ -178539,6 +178406,7 @@ function registerLayersDnD() {
178539
178406
  element,
178540
178407
  currentLevel: rowDepth,
178541
178408
  indentPerLevel: 16,
178409
+ mode: isExpanded ? "expanded" : "standard",
178542
178410
  block: isVoid ? ["make-child"] : []
178543
178411
  });
178544
178412
  },
@@ -178568,7 +178436,17 @@ function registerLayersDnD() {
178568
178436
  return;
178569
178437
  const srcData = source.data;
178570
178438
  const targetPath = target.data.path;
178439
+ const srcRow = srcData.type === "tree-node" && source.element;
178440
+ const wasExpanded = srcRow && srcRow.hasAttribute("data-dnd-expanded");
178571
178441
  applyDropInstruction(instruction, srcData, targetPath);
178442
+ if (wasExpanded) {
178443
+ const tab = activeTab.value;
178444
+ const newPath = tab?.session.selection;
178445
+ if (newPath) {
178446
+ const collapsed = view._layersCollapsed || (view._layersCollapsed = new Set);
178447
+ collapsed.add(newPath.join("/"));
178448
+ }
178449
+ }
178572
178450
  }
178573
178451
  });
178574
178452
  view.dndCleanups.push(monitorCleanup);
@@ -178634,6 +178512,15 @@ function registerElementsDnD() {
178634
178512
  });
178635
178513
  });
178636
178514
  }
178515
+ function hideDescendantRows(parentRow, container) {
178516
+ const prefix = parentRow.dataset.path + "/";
178517
+ const rows = container.querySelectorAll(".layers-tree .layer-row");
178518
+ for (const r of rows) {
178519
+ if (r.dataset.path?.startsWith(prefix)) {
178520
+ r.style.display = "none";
178521
+ }
178522
+ }
178523
+ }
178637
178524
  function showLayerDropGap(rowEl, data, container) {
178638
178525
  const instruction = extractInstruction(data);
178639
178526
  if (view._currentDropTargetRow && view._currentDropTargetRow !== rowEl) {
@@ -178674,7 +178561,7 @@ function clearLayerDropGap(container) {
178674
178561
  r.style.transform = "";
178675
178562
  }
178676
178563
  function applyDropInstruction(instruction, srcData, targetPath) {
178677
- const S = getState();
178564
+ const document2 = activeTab.value?.doc.document;
178678
178565
  if (srcData.type === "tree-node") {
178679
178566
  const fromPath = srcData.path;
178680
178567
  const targetParent = parentElementPath(targetPath);
@@ -178687,7 +178574,7 @@ function applyDropInstruction(instruction, srcData, targetPath) {
178687
178574
  transactDoc(activeTab.value, (t) => mutateMoveNode(t, fromPath, targetParent, targetIdx + 1));
178688
178575
  break;
178689
178576
  case "make-child": {
178690
- const target = getNodeAtPath(S.document, targetPath);
178577
+ const target = getNodeAtPath(document2, targetPath);
178691
178578
  const len = target?.children?.length || 0;
178692
178579
  transactDoc(activeTab.value, (t) => mutateMoveNode(t, fromPath, targetPath, len));
178693
178580
  break;
@@ -178704,7 +178591,7 @@ function applyDropInstruction(instruction, srcData, targetPath) {
178704
178591
  transactDoc(activeTab.value, (t) => mutateInsertNode(t, targetParent, targetIdx + 1, structuredClone(srcData.fragment)));
178705
178592
  break;
178706
178593
  case "make-child": {
178707
- const target = getNodeAtPath(S.document, targetPath);
178594
+ const target = getNodeAtPath(document2, targetPath);
178708
178595
  const len = target?.children?.length || 0;
178709
178596
  transactDoc(activeTab.value, (t) => mutateInsertNode(t, targetPath, len, structuredClone(srcData.fragment)));
178710
178597
  break;
@@ -178714,8 +178601,8 @@ function applyDropInstruction(instruction, srcData, targetPath) {
178714
178601
  if (tag3 && tag3.includes("-")) {
178715
178602
  const comp = componentRegistry.find((c) => c.tagName === tag3);
178716
178603
  if (comp) {
178717
- const currentS = getState();
178718
- const elements = currentS.document.$elements || [];
178604
+ const tab = activeTab.value;
178605
+ const elements = tab?.doc.document?.$elements || [];
178719
178606
  if (comp.source === "npm") {
178720
178607
  const specifier = comp.modulePath ? `${comp.package}/${comp.modulePath}` : comp.package;
178721
178608
  const alreadyImported = elements.some((e) => e === specifier || e === comp.package);
@@ -178729,7 +178616,7 @@ function applyDropInstruction(instruction, srcData, targetPath) {
178729
178616
  } else {
178730
178617
  const alreadyImported = elements.some((e) => e.$ref && (e.$ref === `./${comp.path}` || e.$ref.endsWith(comp.path.split("/").pop())));
178731
178618
  if (!alreadyImported) {
178732
- const relPath = computeRelativePath(currentS.documentPath, comp.path);
178619
+ const relPath = computeRelativePath(tab?.documentPath, comp.path);
178733
178620
  transact(activeTab.value, (doc) => {
178734
178621
  if (!doc.$elements)
178735
178622
  doc.$elements = [];
@@ -178773,12 +178660,12 @@ function registerPanelDnD(panel) {
178773
178660
  }
178774
178661
  });
178775
178662
  view.canvasDndCleanups.push(monitorCleanup);
178776
- const S = getState();
178663
+ const document2 = activeTab.value?.doc.document;
178777
178664
  for (const el of allEls) {
178778
178665
  const elPath = elToPath.get(el);
178779
178666
  if (!elPath)
178780
178667
  continue;
178781
- const node = getNodeAtPath(S.document, elPath);
178668
+ const node = getNodeAtPath(document2, elPath);
178782
178669
  const tag3 = (node?.tagName || "div").toLowerCase();
178783
178670
  const hasElementChildren = node?.children?.some((c) => c != null && typeof c === "object");
178784
178671
  const isLeaf2 = VOID_ELEMENTS.has(tag3) || !hasElementChildren;
@@ -178898,41 +178785,46 @@ init_store();
178898
178785
  init_workspace();
178899
178786
  init_components();
178900
178787
  var clipboard = null;
178901
- function copyNode(S) {
178902
- if (!S.selection)
178788
+ function copyNode() {
178789
+ const tab = activeTab.value;
178790
+ if (!tab?.session.selection)
178903
178791
  return;
178904
- const node = getNodeAtPath(S.document, S.selection);
178792
+ const node = getNodeAtPath(tab.doc.document, tab.session.selection);
178905
178793
  if (!node)
178906
178794
  return;
178907
178795
  clipboard = structuredClone(node);
178908
178796
  statusMessage("Copied");
178909
178797
  }
178910
- function cutNode(S) {
178911
- if (!S.selection || S.selection.length < 2)
178798
+ function cutNode() {
178799
+ const tab = activeTab.value;
178800
+ if (!tab?.session.selection || tab.session.selection.length < 2)
178912
178801
  return;
178913
- const sel = S.selection;
178914
- const node = getNodeAtPath(S.document, sel);
178802
+ const sel = tab.session.selection;
178803
+ const node = getNodeAtPath(tab.doc.document, sel);
178915
178804
  if (!node)
178916
178805
  return;
178917
178806
  clipboard = structuredClone(node);
178918
- transactDoc(activeTab.value, (t) => mutateRemoveNode(t, sel));
178807
+ transactDoc(tab, (t) => mutateRemoveNode(t, sel));
178919
178808
  statusMessage("Cut");
178920
178809
  }
178921
- function pasteNode(S) {
178810
+ function pasteNode() {
178922
178811
  if (!clipboard)
178923
178812
  return;
178813
+ const tab = activeTab.value;
178814
+ if (!tab)
178815
+ return;
178924
178816
  const clip = clipboard;
178925
- const pPath = S.selection || [];
178926
- const parent = getNodeAtPath(S.document, pPath);
178817
+ const pPath = tab.session.selection || [];
178818
+ const parent = getNodeAtPath(tab.doc.document, pPath);
178927
178819
  if (!parent)
178928
178820
  return;
178929
- if (S.selection && S.selection.length >= 2) {
178930
- const pp = parentElementPath(S.selection);
178931
- const idx = childIndex(S.selection);
178932
- transactDoc(activeTab.value, (t) => mutateInsertNode(t, pp, idx + 1, structuredClone(clip)));
178821
+ if (tab.session.selection && tab.session.selection.length >= 2) {
178822
+ const pp = parentElementPath(tab.session.selection);
178823
+ const idx = childIndex(tab.session.selection);
178824
+ transactDoc(tab, (t) => mutateInsertNode(t, pp, idx + 1, structuredClone(clip)));
178933
178825
  } else {
178934
178826
  const idx = parent.children ? parent.children.length : 0;
178935
- transactDoc(activeTab.value, (t) => mutateInsertNode(t, pPath, idx, structuredClone(clip)));
178827
+ transactDoc(tab, (t) => mutateInsertNode(t, pPath, idx, structuredClone(clip)));
178936
178828
  }
178937
178829
  statusMessage("Pasted");
178938
178830
  }
@@ -178946,17 +178838,18 @@ document.addEventListener("click", () => {
178946
178838
  function dismissContextMenu() {
178947
178839
  ctxMenu.removeAttribute("open");
178948
178840
  }
178949
- function showContextMenu(e, path, S, opts = {}) {
178841
+ function showContextMenu(e, path, opts = {}) {
178950
178842
  e.preventDefault();
178951
178843
  ctxMenu.removeAttribute("open");
178952
- const node = getNodeAtPath(S.document, path);
178844
+ const tab = activeTab.value;
178845
+ const node = getNodeAtPath(tab?.doc.document, path);
178953
178846
  if (!node)
178954
178847
  return;
178955
- activeTab.value.session.selection = path;
178848
+ tab.session.selection = path;
178956
178849
  const items = [];
178957
- items.push({ label: "Copy", action: () => copyNode(S) });
178850
+ items.push({ label: "Copy", action: () => copyNode() });
178958
178851
  if (path.length >= 2) {
178959
- items.push({ label: "Cut", action: () => cutNode(S) });
178852
+ items.push({ label: "Cut", action: () => cutNode() });
178960
178853
  items.push({
178961
178854
  label: "Duplicate",
178962
178855
  action: () => transactDoc(activeTab.value, (t) => mutateDuplicateNode(t, path))
@@ -179253,7 +179146,7 @@ function registerPanelEvents(panel) {
179253
179146
  if (isEditing()) {
179254
179147
  stopEditing();
179255
179148
  }
179256
- const S = _ctx8.getState();
179149
+ const tab = activeTab.value;
179257
179150
  const canvasMode = _ctx8.getCanvasMode();
179258
179151
  const elements = withPanelPointerEvents(() => document.elementsFromPoint(e.clientX, e.clientY));
179259
179152
  for (const el of elements) {
@@ -179267,16 +179160,15 @@ function registerPanelEvents(panel) {
179267
179160
  view.layoutSelection = null;
179268
179161
  const originalPath = elToPath.get(el);
179269
179162
  if (originalPath) {
179270
- let path = bubbleInlinePath(S.document, originalPath);
179163
+ let path = bubbleInlinePath(tab?.doc.document, originalPath);
179271
179164
  const newMedia = mediaName === "base" ? null : mediaName ?? null;
179272
- const withMedia = { ...S, ui: { ...S.ui, activeMedia: newMedia } };
179273
179165
  const resolvedEl = path === originalPath ? el : findCanvasElement(path, canvas) || el;
179274
- if (pathsEqual(path, S.selection) && isEditableBlock(resolvedEl) && (canvasMode === "edit" || S.mode === "content")) {
179275
- _ctx8.setState(withMedia);
179166
+ if (pathsEqual(path, tab?.session.selection) && isEditableBlock(resolvedEl) && (canvasMode === "edit" || tab?.doc.mode === "content")) {
179167
+ activeTab.value.session.ui.activeMedia = newMedia;
179276
179168
  _ctx8.enterInlineEdit(resolvedEl, path);
179277
179169
  return;
179278
179170
  }
179279
- if (canvasMode === "design" && S.mode !== "content") {
179171
+ if (canvasMode === "design" && tab?.doc.mode !== "content") {
179280
179172
  updateUi("pendingInlineEdit", { path, mediaName });
179281
179173
  activeTab.value.session.ui.activeMedia = newMedia;
179282
179174
  activeTab.value.session.selection = path;
@@ -179300,13 +179192,13 @@ function registerPanelEvents(panel) {
179300
179192
  const canvasMode = _ctx8.getCanvasMode();
179301
179193
  if (canvasMode !== "edit" && canvasMode !== "design")
179302
179194
  return;
179303
- const S = _ctx8.getState();
179195
+ const tab = activeTab.value;
179304
179196
  const elements = withPanelPointerEvents(() => document.elementsFromPoint(e.clientX, e.clientY));
179305
179197
  for (const el of elements) {
179306
179198
  if (canvas.contains(el) && el !== canvas) {
179307
179199
  const originalPath = elToPath.get(el);
179308
179200
  if (originalPath) {
179309
- const path = bubbleInlinePath(S.document, originalPath);
179201
+ const path = bubbleInlinePath(tab?.doc.document, originalPath);
179310
179202
  const resolvedEl = path === originalPath ? el : findCanvasElement(path, canvas) || el;
179311
179203
  if (isEditableBlock(resolvedEl)) {
179312
179204
  const newMedia = mediaName === "base" ? null : mediaName ?? null;
@@ -179326,14 +179218,14 @@ function registerPanelEvents(panel) {
179326
179218
  if (e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom)
179327
179219
  return;
179328
179220
  }
179329
- const S = _ctx8.getState();
179221
+ const tab = activeTab.value;
179330
179222
  const elements = withPanelPointerEvents(() => document.elementsFromPoint(e.clientX, e.clientY));
179331
179223
  for (const el of elements) {
179332
179224
  if (canvas.contains(el) && el !== canvas) {
179333
179225
  let path = elToPath.get(el);
179334
179226
  if (path) {
179335
- path = bubbleInlinePath(S.document, path);
179336
- showContextMenu(e, path, S, { onEditComponent: _ctx8.navigateToComponent });
179227
+ path = bubbleInlinePath(tab?.doc.document, path);
179228
+ showContextMenu(e, path, { onEditComponent: _ctx8.navigateToComponent });
179337
179229
  return;
179338
179230
  }
179339
179231
  }
@@ -179347,31 +179239,29 @@ function registerPanelEvents(panel) {
179347
179239
  if (e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom)
179348
179240
  return;
179349
179241
  }
179350
- let S = _ctx8.getState();
179242
+ const tab = activeTab.value;
179351
179243
  const el = withPanelPointerEvents(() => document.elementFromPoint(e.clientX, e.clientY));
179352
179244
  if (el && canvas.contains(el) && el !== canvas) {
179353
179245
  let path = elToPath.get(el);
179354
179246
  if (path) {
179355
- path = bubbleInlinePath(S.document, path);
179356
- if (!pathsEqual(path, S.hover)) {
179357
- _ctx8.setState(hoverNode(S, path));
179247
+ path = bubbleInlinePath(tab?.doc.document, path);
179248
+ if (!pathsEqual(path, tab?.session.hover)) {
179249
+ activeTab.value.session.hover = path;
179358
179250
  renderOnly("overlays");
179359
179251
  }
179360
179252
  }
179361
- } else if (S.hover) {
179362
- _ctx8.setState(hoverNode(S, null));
179253
+ } else if (tab?.session.hover) {
179254
+ activeTab.value.session.hover = null;
179363
179255
  renderOnly("overlays");
179364
179256
  }
179365
179257
  }, opts);
179366
179258
  overlayClk.addEventListener("mouseleave", () => {
179367
- const S = _ctx8.getState();
179368
- if (S.hover) {
179369
- _ctx8.setState(hoverNode(S, null));
179259
+ if (activeTab.value?.session.hover) {
179260
+ activeTab.value.session.hover = null;
179370
179261
  renderOnly("overlays");
179371
179262
  }
179372
179263
  }, opts);
179373
179264
  mount2({
179374
- getState: _ctx8.getState,
179375
179265
  getCanvasMode: _ctx8.getCanvasMode,
179376
179266
  withPanelPointerEvents,
179377
179267
  effectiveZoom,
@@ -179482,6 +179372,7 @@ function computeDocumentDiff(originalDoc, currentDoc) {
179482
179372
 
179483
179373
  // src/panels/pseudo-preview.js
179484
179374
  init_store();
179375
+ init_workspace();
179485
179376
  var pseudoStyleHost = document.createElement("div");
179486
179377
  pseudoStyleHost.style.display = "contents";
179487
179378
  (document.querySelector("sp-theme") || document.body).appendChild(pseudoStyleHost);
@@ -179494,21 +179385,21 @@ function updateForcedPseudoPreview() {
179494
179385
  view.forcedAttrEl.removeAttribute("data-studio-forced");
179495
179386
  view.forcedAttrEl = null;
179496
179387
  }
179497
- const S = getState();
179498
- const sel = S.ui?.activeSelector;
179499
- if (!sel || !sel.startsWith(":") || !S.selection)
179388
+ const tab = activeTab.value;
179389
+ const sel = tab?.session.ui?.activeSelector;
179390
+ if (!sel || !sel.startsWith(":") || !tab?.session.selection)
179500
179391
  return;
179501
179392
  const panel = getActivePanel();
179502
179393
  if (!panel)
179503
179394
  return;
179504
- const el = findCanvasElement(S.selection, panel.canvas);
179395
+ const el = findCanvasElement(tab.session.selection, panel.canvas);
179505
179396
  if (!el)
179506
179397
  return;
179507
- const node = getNodeAtPath(S.document, S.selection);
179398
+ const node = getNodeAtPath(tab.doc.document, tab.session.selection);
179508
179399
  if (!node?.style)
179509
179400
  return;
179510
- const activeTab2 = S.ui.activeMedia;
179511
- const ctx = activeTab2 ? node.style[`@${activeTab2}`] || {} : node.style;
179401
+ const activeMedia = tab.session.ui.activeMedia;
179402
+ const ctx = activeMedia ? node.style[`@${activeMedia}`] || {} : node.style;
179512
179403
  const rules = ctx[sel];
179513
179404
  if (!rules || typeof rules !== "object")
179514
179405
  return;
@@ -180013,18 +179904,17 @@ function invalidateBrowseCache() {
180013
179904
  init_store();
180014
179905
  init_workspace();
180015
179906
  function getFunctionBody(editing) {
180016
- const S = getState();
179907
+ const document2 = activeTab.value?.doc.document;
180017
179908
  if (editing.type === "def") {
180018
- return S.document.state?.[editing.defName]?.body || "";
179909
+ return document2?.state?.[editing.defName]?.body || "";
180019
179910
  } else if (editing.type === "event") {
180020
- const node = getNodeAtPath(S.document, editing.path);
179911
+ const node = getNodeAtPath(document2, editing.path);
180021
179912
  return node?.[editing.eventKey]?.body || "";
180022
179913
  }
180023
179914
  return "";
180024
179915
  }
180025
179916
  function renderFunctionEditor() {
180026
- const S = getState();
180027
- const editing = S.ui.editingFunction;
179917
+ const editing = activeTab.value?.session.ui.editingFunction;
180028
179918
  if (view.functionEditor && view.functionEditor._editingTarget === JSON.stringify(editing)) {
180029
179919
  const body2 = getFunctionBody(editing);
180030
179920
  const currentVal = view.functionEditor.getValue();
@@ -180061,7 +179951,7 @@ function renderFunctionEditor() {
180061
179951
  })}
180062
179952
  ></div>`, canvasWrap);
180063
179953
  const body = getFunctionBody(editing);
180064
- const args = getFunctionArgs(editing, S);
179954
+ const args = getFunctionArgs(editing, activeTab.value?.doc.document);
180065
179955
  view.functionEditor = editor.create(editorContainer, {
180066
179956
  value: body,
180067
179957
  language: "javascript",
@@ -180097,13 +179987,13 @@ function renderFunctionEditor() {
180097
179987
  clearTimeout(syncDebounce);
180098
179988
  syncDebounce = setTimeout(() => {
180099
179989
  const newBody = view.functionEditor.getValue();
180100
- if (editing.type === "def") {
180101
- transactDoc(activeTab.value, (t) => mutateUpdateDef(t, editing.defName, { body: newBody }));
180102
- } else if (editing.type === "event") {
180103
- const S2 = getState();
180104
- const node = getNodeAtPath(S2.document, editing.path);
180105
- const current = node?.[editing.eventKey] || {};
180106
- transactDoc(activeTab.value, (t) => mutateUpdateProperty(t, editing.path, editing.eventKey, {
179990
+ const ed = editing;
179991
+ if (ed.type === "def") {
179992
+ transactDoc(activeTab.value, (t) => mutateUpdateDef(t, ed.defName, { body: newBody }));
179993
+ } else if (ed.type === "event") {
179994
+ const node = getNodeAtPath(activeTab.value?.doc.document, ed.path);
179995
+ const current = node?.[ed.eventKey] || {};
179996
+ transactDoc(activeTab.value, (t) => mutateUpdateProperty(t, ed.path, ed.eventKey, {
180107
179997
  ...current,
180108
179998
  $prototype: "Function",
180109
179999
  body: newBody
@@ -180131,8 +180021,7 @@ function registerFunctionCompletions() {
180131
180021
  languages.registerCompletionItemProvider("javascript", {
180132
180022
  triggerCharacters: ["."],
180133
180023
  provideCompletionItems(model, position) {
180134
- const S = getState();
180135
- const defs = S?.document?.state || {};
180024
+ const defs = activeTab.value?.doc.document?.state || {};
180136
180025
  const word = model.getWordUntilPosition(position);
180137
180026
  const range2 = {
180138
180027
  startLineNumber: position.lineNumber,
@@ -180573,8 +180462,9 @@ function renderCanvasIntoPanel(panel, activeBreakpoints, featureToggles, docOver
180573
180462
  statusMessage("Runtime render OK", 1500);
180574
180463
  if (gitDiffState && docOverride) {
180575
180464
  const isOriginal = docOverride === (gitDiffState.originalDoc || gitDiffState.original);
180576
- const origDoc = isOriginal ? docOverride : gitDiffState.currentDoc || tab?.doc.document;
180577
- const currDoc = isOriginal ? gitDiffState.currentDoc || tab?.doc.document : docOverride;
180465
+ const _tab = activeTab.value;
180466
+ const origDoc = isOriginal ? docOverride : gitDiffState.currentDoc || _tab?.doc.document;
180467
+ const currDoc = isOriginal ? gitDiffState.currentDoc || _tab?.doc.document : docOverride;
180578
180468
  const { byPath: diffMap } = computeDocumentDiff(origDoc, currDoc);
180579
180469
  const { elToPath: elToPath2 } = scope;
180580
180470
  if (elToPath2 instanceof WeakMap) {
@@ -180589,6 +180479,17 @@ function renderCanvasIntoPanel(panel, activeBreakpoints, featureToggles, docOver
180589
180479
  registerPanelEvents(panel);
180590
180480
  renderOverlays();
180591
180481
  updateForcedPseudoPreview();
180482
+ const currentTab = activeTab.value;
180483
+ if (currentTab?.session.ui?.pendingInlineEdit) {
180484
+ const { path, mediaName: mn } = currentTab.session.ui.pendingInlineEdit;
180485
+ currentTab.session.ui.pendingInlineEdit = null;
180486
+ const targetPanel = canvasPanels.find((p) => p.mediaName === mn) || canvasPanels[0];
180487
+ if (targetPanel) {
180488
+ const el = findCanvasElement(path, targetPanel.canvas);
180489
+ if (el)
180490
+ enterComponentInlineEdit(el, path);
180491
+ }
180492
+ }
180592
180493
  });
180593
180494
  }
180594
180495
  function applyDiffHighlightToCanvas(canvas, diffMap) {
@@ -184209,9 +184110,9 @@ function collapsePropsToAttrMap(propsObj) {
184209
184110
  }
184210
184111
 
184211
184112
  // src/files/file-ops.js
184212
- init_store();
184213
184113
  init_platform();
184214
- async function openFile({ S: _S, commit, renderToolbar: _renderToolbar }) {
184114
+ init_workspace();
184115
+ async function openFile() {
184215
184116
  try {
184216
184117
  if ("showOpenFilePicker" in window) {
184217
184118
  const [handle2] = await window.showOpenFilePicker({
@@ -184222,17 +184123,20 @@ async function openFile({ S: _S, commit, renderToolbar: _renderToolbar }) {
184222
184123
  });
184223
184124
  const file = await handle2.getFile();
184224
184125
  const text6 = await file.text();
184126
+ const documentPath = await locateDocument(handle2.name);
184225
184127
  if (handle2.name.endsWith(".md")) {
184226
- const newState = await loadMarkdown(text6, handle2);
184227
- commit(newState);
184128
+ const { document: document4, frontmatter: frontmatter2 } = await loadMarkdown(text6);
184129
+ openTab({
184130
+ id: handle2.name,
184131
+ documentPath,
184132
+ fileHandle: handle2,
184133
+ document: document4,
184134
+ frontmatter: frontmatter2,
184135
+ sourceFormat: "md"
184136
+ });
184228
184137
  } else {
184229
- const doc = JSON.parse(text6);
184230
- const newState = createState(doc);
184231
- newState.fileHandle = handle2;
184232
- newState.dirty = false;
184233
- newState.documentPath = await locateDocument(handle2.name);
184234
- await loadCompanionJS(handle2, newState);
184235
- commit(newState);
184138
+ const document4 = JSON.parse(text6);
184139
+ openTab({ id: handle2.name, documentPath, fileHandle: handle2, document: document4 });
184236
184140
  }
184237
184141
  statusMessage(`Opened ${handle2.name}`);
184238
184142
  } else {
@@ -184245,13 +184149,11 @@ async function openFile({ S: _S, commit, renderToolbar: _renderToolbar }) {
184245
184149
  return;
184246
184150
  const text6 = await file.text();
184247
184151
  if (file.name.endsWith(".md")) {
184248
- const newState = await loadMarkdown(text6, null);
184249
- commit(newState);
184152
+ const { document: document4, frontmatter: frontmatter2 } = await loadMarkdown(text6);
184153
+ openTab({ id: file.name, document: document4, frontmatter: frontmatter2, sourceFormat: "md" });
184250
184154
  } else {
184251
- const doc = JSON.parse(text6);
184252
- const newState = createState(doc);
184253
- newState.dirty = false;
184254
- commit(newState);
184155
+ const document4 = JSON.parse(text6);
184156
+ openTab({ id: file.name, document: document4 });
184255
184157
  }
184256
184158
  statusMessage(`Opened ${file.name}`);
184257
184159
  };
@@ -184262,59 +184164,37 @@ async function openFile({ S: _S, commit, renderToolbar: _renderToolbar }) {
184262
184164
  statusMessage(`Error: ${e.message}`);
184263
184165
  }
184264
184166
  }
184265
- async function loadMarkdown(source, fileHandle) {
184167
+ async function loadMarkdown(source) {
184266
184168
  const { transpileJxMarkdown: transpileJxMarkdown2 } = await Promise.resolve().then(() => (init_transpile(), exports_transpile));
184267
184169
  const doc = transpileJxMarkdown2(source);
184268
184170
  const isComponent = doc.tagName && String(doc.tagName).includes("-");
184269
184171
  if (isComponent) {
184270
- const newState2 = createState(doc);
184271
- newState2.sourceFormat = "md";
184272
- newState2.rawMarkdown = source;
184273
- newState2.fileHandle = fileHandle;
184274
- newState2.dirty = false;
184275
- return newState2;
184172
+ return { document: doc, frontmatter: {} };
184276
184173
  }
184277
- const contentDoc = {
184278
- children: doc.children ?? []
184279
- };
184174
+ const contentDoc = { children: doc.children ?? [] };
184280
184175
  const frontmatter2 = {};
184281
184176
  for (const [key, value2] of Object.entries(doc)) {
184282
184177
  if (key !== "children")
184283
184178
  frontmatter2[key] = value2;
184284
184179
  }
184285
- const newState = createState(contentDoc);
184286
- newState.sourceFormat = "md";
184287
- newState.mode = "content";
184288
- newState.content = { frontmatter: frontmatter2 };
184289
- newState.rawMarkdown = source;
184290
- newState.fileHandle = fileHandle;
184291
- newState.dirty = false;
184292
- return newState;
184180
+ return { document: contentDoc, frontmatter: frontmatter2 };
184293
184181
  }
184294
- async function loadCompanionJS(handle2, state) {
184295
- try {
184296
- if (handle2.getParent) {}
184297
- if (state.document.$handlers) {
184298
- state.handlersSource = `// Companion file: ${state.document.$handlers}
184299
- // (Read-only in builder — edit the JS file directly)`;
184300
- }
184301
- } catch {}
184302
- }
184303
- async function saveFile({ S, commit, renderToolbar }) {
184182
+ async function saveFile() {
184183
+ const tab = activeTab.value;
184184
+ if (!tab)
184185
+ return;
184304
184186
  try {
184305
- const output = serializeDocument(S);
184306
- if (S.documentPath) {
184187
+ const output = serializeDocument(tab);
184188
+ if (tab.documentPath) {
184307
184189
  const platform3 = getPlatform();
184308
- await platform3.writeFile(S.documentPath, output);
184309
- commit({ ...S, dirty: false });
184310
- renderToolbar();
184190
+ await platform3.writeFile(tab.documentPath, output);
184191
+ tab.doc.dirty = false;
184311
184192
  statusMessage("Saved");
184312
- } else if (S.fileHandle && "createWritable" in S.fileHandle) {
184313
- const writable = await S.fileHandle.createWritable();
184193
+ } else if (tab.fileHandle && "createWritable" in tab.fileHandle) {
184194
+ const writable = await tab.fileHandle.createWritable();
184314
184195
  await writable.write(output);
184315
184196
  await writable.close();
184316
- commit({ ...S, dirty: false });
184317
- renderToolbar();
184197
+ tab.doc.dirty = false;
184318
184198
  statusMessage("Saved");
184319
184199
  } else {
184320
184200
  statusMessage("No save target — use Export");
@@ -184324,15 +184204,18 @@ async function saveFile({ S, commit, renderToolbar }) {
184324
184204
  statusMessage(`Save error: ${e.message}`);
184325
184205
  }
184326
184206
  }
184327
- async function exportFile({ S, commit, renderToolbar }) {
184207
+ async function exportFile() {
184208
+ const tab = activeTab.value;
184209
+ if (!tab)
184210
+ return;
184328
184211
  try {
184329
- const isContent = S.mode === "content";
184330
- const output = serializeDocument(S);
184212
+ const isContent = tab.doc.mode === "content";
184213
+ const output = serializeDocument(tab);
184331
184214
  const mimeType = isContent ? "text/markdown" : "application/json";
184332
184215
  const ext = isContent ? ".md" : ".json";
184333
184216
  const description = isContent ? "Markdown Content" : "Jx Component";
184334
184217
  if ("showSaveFilePicker" in window) {
184335
- const suggestedName = S.documentPath ? S.documentPath.split("/").pop() : isContent ? "content.md" : "component.json";
184218
+ const suggestedName = tab.documentPath ? tab.documentPath.split("/").pop() : isContent ? "content.md" : "component.json";
184336
184219
  const handle2 = await window.showSaveFilePicker({
184337
184220
  suggestedName,
184338
184221
  types: [{ description, accept: { [mimeType]: [ext] } }]
@@ -184340,8 +184223,7 @@ async function exportFile({ S, commit, renderToolbar }) {
184340
184223
  const writable = await handle2.createWritable();
184341
184224
  await writable.write(output);
184342
184225
  await writable.close();
184343
- commit({ ...S, dirty: false });
184344
- renderToolbar();
184226
+ tab.doc.dirty = false;
184345
184227
  statusMessage(`Exported as ${handle2.name}`);
184346
184228
  } else {
184347
184229
  const blob = new Blob([output], { type: mimeType });
@@ -184351,8 +184233,7 @@ async function exportFile({ S, commit, renderToolbar }) {
184351
184233
  a.download = isContent ? "content.md" : "component.json";
184352
184234
  a.click();
184353
184235
  URL.revokeObjectURL(url);
184354
- commit({ ...S, dirty: false });
184355
- renderToolbar();
184236
+ tab.doc.dirty = false;
184356
184237
  statusMessage("Downloaded");
184357
184238
  }
184358
184239
  } catch (e) {
@@ -184360,14 +184241,14 @@ async function exportFile({ S, commit, renderToolbar }) {
184360
184241
  statusMessage(`Export error: ${e.message}`);
184361
184242
  }
184362
184243
  }
184363
- function serializeDocument(S) {
184364
- if (S.sourceFormat === "md") {
184365
- return jxDocToMd(S.document);
184244
+ function serializeDocument(tab) {
184245
+ if (tab.doc.sourceFormat === "md") {
184246
+ return jxDocToMd(tab.doc.document);
184366
184247
  }
184367
- if (S.mode === "content") {
184368
- const mdast = jxToMd(S.document);
184248
+ if (tab.doc.mode === "content") {
184249
+ const mdast = jxToMd(tab.doc.document);
184369
184250
  const md = unified().use(remarkDirective).use(remarkStringify, { bullet: "-", emphasis: "*", strong: "*" }).stringify(mdast);
184370
- const fm = S.content?.frontmatter;
184251
+ const fm = tab.doc.content?.frontmatter;
184371
184252
  const hasFrontmatter = fm && Object.keys(fm).length > 0;
184372
184253
  return hasFrontmatter ? `---
184373
184254
  ${stringify4(fm).trim()}
@@ -184375,7 +184256,7 @@ ${stringify4(fm).trim()}
184375
184256
 
184376
184257
  ${md}` : md;
184377
184258
  }
184378
- return JSON.stringify(S.document, null, 2);
184259
+ return JSON.stringify(tab.doc.document, null, 2);
184379
184260
  }
184380
184261
 
184381
184262
  // src/files/files.js
@@ -184427,7 +184308,7 @@ async function loadProject() {
184427
184308
  }
184428
184309
  } catch {}
184429
184310
  }
184430
- async function openProject({ S, commit, renderActivityBar, renderLeftPanel }) {
184311
+ async function openProject({ renderActivityBar, renderLeftPanel }) {
184431
184312
  try {
184432
184313
  const platform3 = getPlatform();
184433
184314
  const result = await platform3.openProject();
@@ -184466,7 +184347,7 @@ async function openProject({ S, commit, renderActivityBar, renderLeftPanel }) {
184466
184347
  }
184467
184348
  }
184468
184349
  projectState.projectDirs = foundDirs;
184469
- commit({ ...S, ui: { ...S.ui, leftTab: "files" } });
184350
+ view.leftTab = "files";
184470
184351
  renderActivityBar();
184471
184352
  renderLeftPanel();
184472
184353
  statusMessage(`Opened project: ${projectState.name}`);
@@ -184822,14 +184703,20 @@ async function openFileInTab(path2) {
184822
184703
  return;
184823
184704
  let document4, frontmatter2;
184824
184705
  if (path2.endsWith(".md")) {
184825
- const state = await loadMarkdown(content3, null);
184826
- document4 = state.document;
184827
- frontmatter2 = state.content?.frontmatter;
184706
+ const result = await loadMarkdown(content3);
184707
+ document4 = result.document;
184708
+ frontmatter2 = result.frontmatter;
184828
184709
  } else {
184829
184710
  document4 = JSON.parse(content3);
184830
184711
  }
184831
184712
  const id = path2;
184832
- openTab({ id, documentPath: path2, document: document4, frontmatter: frontmatter2 });
184713
+ openTab({
184714
+ id,
184715
+ documentPath: path2,
184716
+ document: document4,
184717
+ frontmatter: frontmatter2,
184718
+ sourceFormat: path2.endsWith(".md") ? "md" : null
184719
+ });
184833
184720
  projectState.selectedPath = path2;
184834
184721
  statusMessage(`Opened ${path2.split("/").pop()}`);
184835
184722
  } catch (e) {
@@ -187706,7 +187593,7 @@ function renderGitPanel(S, ctx) {
187706
187593
  }
187707
187594
  if (!_pollTimer) {
187708
187595
  _pollTimer = setInterval(() => {
187709
- if (S.ui.leftTab === "git" && !S.ui.gitLoading)
187596
+ if (view.leftTab === "git" && !S.ui.gitLoading)
187710
187597
  refreshGitStatus();
187711
187598
  }, 30000);
187712
187599
  }
@@ -210839,9 +210726,9 @@ class JxValueSelector extends LitElement {
210839
210726
  // src/ui/color-selector.js
210840
210727
  init_lit();
210841
210728
  init_store();
210729
+ init_workspace();
210842
210730
  function getColorVars() {
210843
- const S = getState();
210844
- const style2 = getEffectiveStyle(S?.document?.style);
210731
+ const style2 = getEffectiveStyle(activeTab.value?.doc.document?.style);
210845
210732
  if (!style2)
210846
210733
  return [];
210847
210734
  const vars = [];
@@ -210860,8 +210747,7 @@ function resolveColorForDisplay(val) {
210860
210747
  return "transparent";
210861
210748
  const m3 = val.match(/^var\((--[^)]+)\)$/);
210862
210749
  if (m3) {
210863
- const S = getState();
210864
- const style2 = getEffectiveStyle(S?.document?.style);
210750
+ const style2 = getEffectiveStyle(activeTab.value?.doc.document?.style);
210865
210751
  const resolved = style2?.[m3[1]];
210866
210752
  if (typeof resolved === "string")
210867
210753
  return resolved;
@@ -211262,7 +211148,7 @@ init_store();
211262
211148
  init_workspace();
211263
211149
  function initShortcuts(getContext) {
211264
211150
  canvasWrap.addEventListener("wheel", (e20) => {
211265
- const { S, setS, canvasMode, panX, panY, setPan, applyTransform: applyTransform2 } = getContext();
211151
+ const { canvasMode, panX, panY, setPan, applyTransform: applyTransform2 } = getContext();
211266
211152
  if (canvasMode === "edit")
211267
211153
  return;
211268
211154
  e20.preventDefault();
@@ -211270,12 +211156,12 @@ function initShortcuts(getContext) {
211270
211156
  const rect = canvasWrap.getBoundingClientRect();
211271
211157
  const cursorX = e20.clientX - rect.left;
211272
211158
  const cursorY = e20.clientY - rect.top;
211273
- const oldZoom = S.ui.zoom;
211159
+ const oldZoom = activeTab.value?.session.ui.zoom ?? 1;
211274
211160
  const delta = -e20.deltaY * 0.005;
211275
211161
  const newZoom = Math.min(5, Math.max(0.05, oldZoom * (1 + delta)));
211276
211162
  const ratio = newZoom / oldZoom;
211277
211163
  setPan(cursorX - (cursorX - panX) * ratio, cursorY - (cursorY - panY) * ratio);
211278
- setS({ ...S, ui: { ...S.ui, zoom: newZoom } });
211164
+ activeTab.value.session.ui.zoom = newZoom;
211279
211165
  } else if (e20.shiftKey) {
211280
211166
  setPan(panX - e20.deltaY, panY);
211281
211167
  } else {
@@ -211310,8 +211196,6 @@ function initShortcuts(getContext) {
211310
211196
  window.addEventListener("resize", () => getContext().positionZoomIndicator());
211311
211197
  document.addEventListener("keydown", (e20) => {
211312
211198
  const {
211313
- S,
211314
- setS,
211315
211199
  canvasMode,
211316
211200
  setPan,
211317
211201
  applyTransform: applyTransform2,
@@ -211320,6 +211204,7 @@ function initShortcuts(getContext) {
211320
211204
  openProject: openProject2,
211321
211205
  enterEditOnPath
211322
211206
  } = getContext();
211207
+ const tab = activeTab.value;
211323
211208
  const mod = e20.ctrlKey || e20.metaKey;
211324
211209
  if (e20.target instanceof HTMLElement && e20.target.matches("input, textarea, select, sp-textfield, sp-search, sp-number-field, sp-picker")) {
211325
211210
  if (mod && e20.key === "s") {
@@ -211356,9 +211241,9 @@ function initShortcuts(getContext) {
211356
211241
  case "w":
211357
211242
  e20.preventDefault();
211358
211243
  if (workspace.activeTabId && workspace.tabOrder.length > 1) {
211359
- const tab = workspace.tabs.get(workspace.activeTabId);
211360
- if (tab?.doc.dirty) {
211361
- const name = tab.documentPath?.split("/").pop() || "Untitled";
211244
+ const tab2 = workspace.tabs.get(workspace.activeTabId);
211245
+ if (tab2?.doc.dirty) {
211246
+ const name = tab2.documentPath?.split("/").pop() || "Untitled";
211362
211247
  if (!window.confirm(`"${name}" has unsaved changes. Close without saving?`))
211363
211248
  break;
211364
211249
  }
@@ -211382,28 +211267,28 @@ function initShortcuts(getContext) {
211382
211267
  break;
211383
211268
  case "d":
211384
211269
  e20.preventDefault();
211385
- if (S.selection) {
211386
- const sel = S.selection;
211387
- transactDoc(activeTab.value, (t15) => mutateDuplicateNode(t15, sel));
211270
+ if (tab?.session.selection) {
211271
+ const sel = tab.session.selection;
211272
+ transactDoc(tab, (t15) => mutateDuplicateNode(t15, sel));
211388
211273
  }
211389
211274
  break;
211390
211275
  case "c":
211391
211276
  e20.preventDefault();
211392
- copyNode(S);
211277
+ copyNode();
211393
211278
  break;
211394
211279
  case "x":
211395
211280
  e20.preventDefault();
211396
- cutNode(S);
211281
+ cutNode();
211397
211282
  break;
211398
211283
  case "v":
211399
211284
  e20.preventDefault();
211400
- pasteNode(S);
211285
+ pasteNode();
211401
211286
  break;
211402
211287
  case "0":
211403
211288
  if (canvasMode === "edit")
211404
211289
  break;
211405
211290
  e20.preventDefault();
211406
- setS({ ...S, ui: { ...S.ui, zoom: 1 } });
211291
+ activeTab.value.session.ui.zoom = 1;
211407
211292
  setPan(16, 16);
211408
211293
  applyTransform2();
211409
211294
  break;
@@ -211412,14 +211297,14 @@ function initShortcuts(getContext) {
211412
211297
  if (canvasMode === "edit")
211413
211298
  break;
211414
211299
  e20.preventDefault();
211415
- setS({ ...S, ui: { ...S.ui, zoom: Math.min(5, S.ui.zoom * 1.2) } });
211300
+ activeTab.value.session.ui.zoom = Math.min(5, (tab?.session.ui.zoom ?? 1) * 1.2);
211416
211301
  applyTransform2();
211417
211302
  break;
211418
211303
  case "-":
211419
211304
  if (canvasMode === "edit")
211420
211305
  break;
211421
211306
  e20.preventDefault();
211422
- setS({ ...S, ui: { ...S.ui, zoom: Math.max(0.05, S.ui.zoom / 1.2) } });
211307
+ activeTab.value.session.ui.zoom = Math.max(0.05, (tab?.session.ui.zoom ?? 1) / 1.2);
211423
211308
  applyTransform2();
211424
211309
  break;
211425
211310
  }
@@ -211428,22 +211313,22 @@ function initShortcuts(getContext) {
211428
211313
  switch (e20.key) {
211429
211314
  case "Delete":
211430
211315
  case "Backspace":
211431
- if (S.selection && S.selection.length >= 2) {
211316
+ if (tab?.session.selection && tab.session.selection.length >= 2) {
211432
211317
  e20.preventDefault();
211433
- const sel = S.selection;
211434
- transactDoc(activeTab.value, (t15) => mutateRemoveNode(t15, sel));
211318
+ const sel = tab.session.selection;
211319
+ transactDoc(tab, (t15) => mutateRemoveNode(t15, sel));
211435
211320
  }
211436
211321
  break;
211437
211322
  case "Escape":
211438
211323
  activeTab.value.session.selection = null;
211439
211324
  break;
211440
211325
  case "Enter":
211441
- if (S.selection && S.selection.length >= 2) {
211326
+ if (tab?.session.selection && tab.session.selection.length >= 2) {
211442
211327
  e20.preventDefault();
211443
- const pp = parentElementPath(S.selection);
211444
- const idx = childIndex(S.selection);
211328
+ const pp = parentElementPath(tab.session.selection);
211329
+ const idx = childIndex(tab.session.selection);
211445
211330
  const newPath = [...pp, "children", idx + 1];
211446
- transactDoc(activeTab.value, (t15) => {
211331
+ transactDoc(tab, (t15) => {
211447
211332
  mutateInsertNode(t15, pp, idx + 1, { tagName: "p", textContent: "" });
211448
211333
  t15.session.selection = newPath;
211449
211334
  });
@@ -211452,24 +211337,24 @@ function initShortcuts(getContext) {
211452
211337
  break;
211453
211338
  case "ArrowUp":
211454
211339
  e20.preventDefault();
211455
- navigateSelection(S);
211340
+ navigateSelection(-1);
211456
211341
  break;
211457
211342
  case "ArrowDown":
211458
211343
  e20.preventDefault();
211459
- navigateSelection(S, 1);
211344
+ navigateSelection(1);
211460
211345
  break;
211461
211346
  case "ArrowLeft":
211462
211347
  e20.preventDefault();
211463
- if (S.selection && S.selection.length >= 2) {
211464
- activeTab.value.session.selection = parentElementPath(S.selection);
211348
+ if (tab?.session.selection && tab.session.selection.length >= 2) {
211349
+ activeTab.value.session.selection = parentElementPath(tab.session.selection);
211465
211350
  }
211466
211351
  break;
211467
211352
  case "ArrowRight":
211468
211353
  e20.preventDefault();
211469
- if (S.selection) {
211470
- const node2 = getNodeAtPath(S.document, S.selection);
211354
+ if (tab?.session.selection) {
211355
+ const node2 = getNodeAtPath(tab.doc.document, tab.session.selection);
211471
211356
  if (node2?.children?.length > 0) {
211472
- activeTab.value.session.selection = [...S.selection, "children", 0];
211357
+ activeTab.value.session.selection = [...tab.session.selection, "children", 0];
211473
211358
  }
211474
211359
  }
211475
211360
  break;
@@ -211481,19 +211366,20 @@ function initShortcuts(getContext) {
211481
211366
  }
211482
211367
  }, { passive: false });
211483
211368
  }
211484
- function navigateSelection(S, direction = -1) {
211485
- if (!S.selection) {
211369
+ function navigateSelection(direction = -1) {
211370
+ const tab = activeTab.value;
211371
+ if (!tab?.session.selection) {
211486
211372
  activeTab.value.session.selection = [];
211487
211373
  return;
211488
211374
  }
211489
- if (S.selection.length < 2)
211375
+ if (tab.session.selection.length < 2)
211490
211376
  return;
211491
- const parent = getNodeAtPath(S.document, parentElementPath(S.selection));
211492
- const idx = childIndex(S.selection);
211377
+ const parent = getNodeAtPath(tab.doc.document, parentElementPath(tab.session.selection));
211378
+ const idx = childIndex(tab.session.selection);
211493
211379
  const newIdx = idx + direction;
211494
211380
  if (parent?.children && newIdx >= 0 && newIdx < parent.children.length) {
211495
211381
  activeTab.value.session.selection = [
211496
- ...parentElementPath(S.selection),
211382
+ ...parentElementPath(tab.session.selection),
211497
211383
  "children",
211498
211384
  newIdx
211499
211385
  ];
@@ -211512,7 +211398,6 @@ function mount4() {
211512
211398
  const tab = activeTab.value;
211513
211399
  if (!tab)
211514
211400
  return;
211515
- tab.session.ui.leftTab;
211516
211401
  renderActivityBar();
211517
211402
  });
211518
211403
  });
@@ -211558,7 +211443,7 @@ function renderActivityBar() {
211558
211443
  const tab = activeTab.value;
211559
211444
  if (!tab)
211560
211445
  return;
211561
- const leftTab = tab.session.ui.leftTab;
211446
+ const leftTab = view.leftTab;
211562
211447
  const tabs = [
211563
211448
  { value: "files", icon: "sp-icon-folder", label: "Files" },
211564
211449
  { value: "layers", icon: "sp-icon-layers", label: "Layers" },
@@ -211575,7 +211460,9 @@ function renderActivityBar() {
211575
211460
  direction="vertical"
211576
211461
  quiet
211577
211462
  @change=${(e20) => {
211578
- activeTab.value.session.ui.leftTab = e20.target.selected;
211463
+ view.leftTab = e20.target.selected;
211464
+ renderOnly("leftPanel");
211465
+ renderActivityBar();
211579
211466
  }}
211580
211467
  >
211581
211468
  ${tabs.map((t15) => html`
@@ -211632,9 +211519,9 @@ function mount5(rootEl, ctx) {
211632
211519
  tab.doc.dirty;
211633
211520
  tab.doc.mode;
211634
211521
  tab.session.selection;
211522
+ tab.session.ui.canvasMode;
211635
211523
  tab.session.ui.editingFunction;
211636
211524
  tab.session.ui.featureToggles;
211637
- tab.session.ui.leftTab;
211638
211525
  tab.session.ui.rightTab;
211639
211526
  render7();
211640
211527
  });
@@ -211747,7 +211634,7 @@ function toolbarTemplate() {
211747
211634
  if (m3.key === "settings")
211748
211635
  uiPatch.rightTab = "style";
211749
211636
  if (m3.key === "manage")
211750
- uiPatch.leftTab = "files";
211637
+ view.leftTab = "files";
211751
211638
  updateSession({ ui: uiPatch });
211752
211639
  _ctx11.renderCanvas();
211753
211640
  _ctx11.safeRenderRightPanel();
@@ -212028,6 +211915,7 @@ function computeInheritedStyle(style2, mediaNames, activeTab2, activeSelector =
212028
211915
 
212029
211916
  // src/panels/style-utils.js
212030
211917
  init_store();
211918
+ init_workspace();
212031
211919
  // data/css-meta.json
212032
211920
  var css_meta_default = {
212033
211921
  $schema: "../../packages/schema/schema.json",
@@ -213638,8 +213526,7 @@ function compressBorderSide(vals) {
213638
213526
  return vals.filter((v) => v && v.trim()).join(" ");
213639
213527
  }
213640
213528
  function getFontVars() {
213641
- const S = getState();
213642
- const style2 = S.document?.style;
213529
+ const style2 = activeTab.value?.doc.document?.style;
213643
213530
  if (!style2)
213644
213531
  return [];
213645
213532
  const vars = [];
@@ -213657,14 +213544,14 @@ var TYPO_PREVIEW_PROPS = new Set([
213657
213544
  "textDecoration"
213658
213545
  ]);
213659
213546
  function currentFontFamily() {
213660
- const S = getState();
213661
- const node2 = S.selection ? getNodeAtPath(S.document, S.selection) : null;
213547
+ const tab = activeTab.value;
213548
+ const node2 = tab?.session.selection ? getNodeAtPath(tab.doc.document, tab.session.selection) : null;
213662
213549
  const raw = node2?.style?.fontFamily;
213663
213550
  if (!raw)
213664
213551
  return "";
213665
213552
  const m3 = typeof raw === "string" && raw.match(/^var\((--[^)]+)\)$/);
213666
213553
  if (m3)
213667
- return S.document?.style?.[m3[1]] || "";
213554
+ return tab?.doc.document?.style?.[m3[1]] || "";
213668
213555
  return raw;
213669
213556
  }
213670
213557
 
@@ -213969,9 +213856,8 @@ function renderSelectInput(entry, prop, value2, onChange) {
213969
213856
  return renderKeywordInput(entry.enum || [], prop, value2, onChange);
213970
213857
  }
213971
213858
  function handleFontPresetSelection(preset, onChange) {
213972
- const S = getState();
213973
213859
  const varName = friendlyNameToVar(preset.title, "--font-");
213974
- if (!S.document?.style?.[varName]) {
213860
+ if (!activeTab.value?.doc.document?.style?.[varName]) {
213975
213861
  transactDoc(activeTab.value, (t15) => mutateUpdateStyle(t15, [], varName, preset.value));
213976
213862
  }
213977
213863
  onChange(`var(${varName})`);
@@ -216298,13 +216184,12 @@ init_workspace();
216298
216184
  init_store();
216299
216185
  init_workspace();
216300
216186
  function renderLayersTemplate(ctx) {
216301
- const S = getState();
216187
+ const tab = activeTab.value;
216302
216188
  for (const fn of view.dndCleanups)
216303
216189
  fn();
216304
216190
  view.dndCleanups = [];
216305
- const rows = flattenTree(S.document);
216306
- const _S = S;
216307
- const collapsed = _S._collapsed || (_S._collapsed = new Set);
216191
+ const rows = flattenTree(tab?.doc.document);
216192
+ const collapsed = view._layersCollapsed || (view._layersCollapsed = new Set);
216308
216193
  const layerRows = [];
216309
216194
  for (const { node: node2, path: path2, depth, nodeType } of rows) {
216310
216195
  let hidden = false;
@@ -216317,7 +216202,7 @@ function renderLayersTemplate(ctx) {
216317
216202
  }
216318
216203
  if (hidden)
216319
216204
  continue;
216320
- if (S.mode === "content" && path2.length === 0)
216205
+ if (tab?.doc.mode === "content" && path2.length === 0)
216321
216206
  continue;
216322
216207
  if (nodeType === "text") {
216323
216208
  const textPreview = String(node2).length > 40 ? String(node2).slice(0, 40) + "…" : String(node2);
@@ -216334,12 +216219,12 @@ function renderLayersTemplate(ctx) {
216334
216219
  }
216335
216220
  if (path2.length >= 2 && nodeType === "element") {
216336
216221
  const pPath = parentElementPath(path2);
216337
- const parentNode2 = pPath ? getNodeAtPath(S.document, pPath) : null;
216222
+ const parentNode2 = pPath ? getNodeAtPath(tab?.doc.document, pPath) : null;
216338
216223
  if (parentNode2 && isInlineElement(node2, parentNode2))
216339
216224
  continue;
216340
216225
  }
216341
216226
  const key = pathKey(path2);
216342
- const isSelected = pathsEqual(path2, S.selection);
216227
+ const isSelected = pathsEqual(path2, tab?.session.selection);
216343
216228
  const hasChildren = Array.isArray(node2.children) && node2.children.length > 0;
216344
216229
  const hasMapChildren = node2.children && typeof node2.children === "object" && node2.children.$prototype === "Array";
216345
216230
  const hasCases = node2.$switch && node2.cases && typeof node2.cases === "object" && Object.keys(node2.cases).length > 0;
@@ -216372,10 +216257,10 @@ function renderLayersTemplate(ctx) {
216372
216257
  labelItalic = false;
216373
216258
  }
216374
216259
  const isElement2 = nodeType === "element";
216375
- const isRoot = S.mode === "content" ? path2.length === 0 : path2.length < 2;
216260
+ const isRoot = tab?.doc.mode === "content" ? path2.length === 0 : path2.length < 2;
216376
216261
  const idx = isElement2 ? childIndex(path2) : 0;
216377
216262
  const parentPath = isElement2 && !isRoot ? parentElementPath(path2) : null;
216378
- const parentNode = parentPath ? getNodeAtPath(S.document, parentPath) : null;
216263
+ const parentNode = parentPath ? getNodeAtPath(tab?.doc.document, parentPath) : null;
216379
216264
  const siblingCount = parentNode?.children?.length || 0;
216380
216265
  const canMoveUp = isElement2 && !isRoot && idx > 0;
216381
216266
  const canMoveDown = isElement2 && !isRoot && idx < siblingCount - 1;
@@ -216390,8 +216275,9 @@ function renderLayersTemplate(ctx) {
216390
216275
  data-dnd-row=${isElement2 ? key : nothing}
216391
216276
  data-dnd-depth=${isElement2 ? depth : nothing}
216392
216277
  data-dnd-void=${isElement2 && isVoidEl ? "" : nothing}
216278
+ data-dnd-expanded=${isElement2 && isExpandable && !collapsed.has(key) ? "" : nothing}
216393
216279
  @click=${() => activeTab.value.session.selection = path2}
216394
- @contextmenu=${isElement2 ? (e20) => showContextMenu(e20, path2, getState(), {
216280
+ @contextmenu=${isElement2 ? (e20) => showContextMenu(e20, path2, {
216395
216281
  onEditComponent: ctx.navigateToComponent
216396
216282
  }) : nothing}
216397
216283
  >
@@ -216439,7 +216325,7 @@ function renderLayersTemplate(ctx) {
216439
216325
  e20.stopPropagation();
216440
216326
  e20.currentTarget.blur();
216441
216327
  const prevPath = [...parentPath, idx - 1];
216442
- const prev = getNodeAtPath(getState().document, prevPath);
216328
+ const prev = getNodeAtPath(activeTab.value?.doc.document, prevPath);
216443
216329
  const len = prev?.children?.length || 0;
216444
216330
  transactDoc(activeTab.value, (t15) => mutateMoveNode(t15, path2, prevPath, len));
216445
216331
  }}
@@ -216505,17 +216391,17 @@ function renderLayersTemplate(ctx) {
216505
216391
  }
216506
216392
 
216507
216393
  // src/panels/stylebook-layers-panel.js
216508
- init_store();
216394
+ init_workspace();
216509
216395
  init_components();
216510
216396
  function hasTagStyle2(rootStyle, tag7) {
216511
216397
  const s2 = rootStyle[`& ${tag7}`];
216512
216398
  return s2 && typeof s2 === "object" && Object.keys(s2).length > 0;
216513
216399
  }
216514
216400
  function renderStylebookLayersTemplate(ctx) {
216515
- const S = getState();
216516
- const rootStyle = S.document?.style || {};
216517
- const selectedTag = S.ui.stylebookSelection;
216518
- if (S.ui.stylebookTab === "elements") {
216401
+ const tab = activeTab.value;
216402
+ const rootStyle = tab?.doc.document?.style || {};
216403
+ const selectedTag = tab?.session.ui.stylebookSelection;
216404
+ if (tab?.session.ui.stylebookTab === "elements") {
216519
216405
  const renderEntryRow = (entry, depth = 0) => {
216520
216406
  const tag7 = entry.tag;
216521
216407
  const uniqueChildren = entry.children ? [...new Map(entry.children.map((c6) => [c6.tag, c6])).values()] : [];
@@ -216585,7 +216471,7 @@ init_store();
216585
216471
  init_workspace();
216586
216472
  init_components();
216587
216473
  function renderElementsTemplate(ctx) {
216588
- const S = getState();
216474
+ const tab = activeTab.value;
216589
216475
  const categories = Object.entries(ctx.webdata.elements).map(([category, elements]) => {
216590
216476
  const filtered = view.elementsFilter ? elements.filter((e20) => e20.tag.includes(view.elementsFilter)) : elements;
216591
216477
  if (filtered.length === 0)
@@ -216608,11 +216494,11 @@ function renderElementsTemplate(ctx) {
216608
216494
  class="element-card"
216609
216495
  data-block-tag=${tag7}
216610
216496
  @click=${() => {
216611
- const s2 = getState();
216612
- const parentPath = s2.selection || [];
216613
- const parent = getNodeAtPath(s2.document, parentPath);
216497
+ const t15 = activeTab.value;
216498
+ const parentPath = t15?.session.selection || [];
216499
+ const parent = getNodeAtPath(t15?.doc.document, parentPath);
216614
216500
  const idx = parent?.children ? parent.children.length : 0;
216615
- transactDoc(activeTab.value, (t15) => mutateInsertNode(t15, parentPath, idx, structuredClone(def3)));
216501
+ transactDoc(t15, (tr) => mutateInsertNode(tr, parentPath, idx, structuredClone(def3)));
216616
216502
  }}
216617
216503
  >
216618
216504
  <div class="element-card-preview"></div>
@@ -216623,7 +216509,7 @@ function renderElementsTemplate(ctx) {
216623
216509
  </sp-accordion-item>
216624
216510
  `;
216625
216511
  });
216626
- const effectiveEls = getEffectiveElements(S.document?.$elements);
216512
+ const effectiveEls = getEffectiveElements(tab?.doc.document?.$elements);
216627
216513
  const enabledTags = new Set;
216628
216514
  for (const entry of effectiveEls) {
216629
216515
  if (typeof entry !== "string")
@@ -216657,9 +216543,9 @@ function renderElementsTemplate(ctx) {
216657
216543
  data-component-tag=${comp.tagName}
216658
216544
  title=${comp.source === "npm" ? `${comp.package}: <${comp.tagName}>` : comp.path}
216659
216545
  @click=${() => {
216660
- const s2 = getState();
216661
- const parentPath = s2.selection || [];
216662
- const parent = getNodeAtPath(s2.document, parentPath);
216546
+ const t15 = activeTab.value;
216547
+ const parentPath = t15?.session.selection || [];
216548
+ const parent = getNodeAtPath(t15?.doc.document, parentPath);
216663
216549
  const idx = parent?.children ? parent.children.length : 0;
216664
216550
  const instanceDef = {
216665
216551
  tagName: comp.tagName,
@@ -216668,7 +216554,7 @@ function renderElementsTemplate(ctx) {
216668
216554
  p2.default !== undefined ? p2.default : ""
216669
216555
  ]))
216670
216556
  };
216671
- transactDoc(activeTab.value, (t15) => mutateInsertNode(t15, parentPath, idx, structuredClone(instanceDef)));
216557
+ transactDoc(t15, (tr) => mutateInsertNode(tr, parentPath, idx, structuredClone(instanceDef)));
216672
216558
  }}
216673
216559
  >
216674
216560
  <div class="element-card-preview">
@@ -216714,7 +216600,6 @@ function mount7(ctx) {
216714
216600
  tab.doc.document;
216715
216601
  tab.doc.mode;
216716
216602
  tab.session.selection;
216717
- tab.session.ui.leftTab;
216718
216603
  tab.session.ui.settingsTab;
216719
216604
  render9();
216720
216605
  });
@@ -216763,7 +216648,7 @@ function _render() {
216763
216648
  mode: aTab.doc.mode,
216764
216649
  selection: aTab.session.selection
216765
216650
  };
216766
- const tab = S.ui.leftTab;
216651
+ const tab = view.leftTab;
216767
216652
  let content3;
216768
216653
  if (tab === "layers")
216769
216654
  content3 = ctx.getCanvasMode() === "settings" ? renderStylebookLayersTemplate({
@@ -216925,16 +216810,23 @@ function requestClose(id) {
216925
216810
  }
216926
216811
 
216927
216812
  // src/studio.js
216928
- var S;
216929
- var doc = null;
216930
- var session = null;
216931
216813
  function createFloatingContainer() {
216932
216814
  const el = document.createElement("div");
216933
216815
  el.style.display = "contents";
216934
216816
  (document.querySelector("sp-theme") || document.body).appendChild(el);
216935
216817
  return el;
216936
216818
  }
216937
- var canvasMode = "design";
216819
+ function getCanvasMode() {
216820
+ return activeTab.value?.session.ui.canvasMode ?? "design";
216821
+ }
216822
+ function setCanvasMode(mode) {
216823
+ if (getCanvasMode() === "git-diff" && mode !== "git-diff") {
216824
+ gitDiffState = null;
216825
+ }
216826
+ const tab = activeTab.value;
216827
+ if (tab)
216828
+ tab.session.ui.canvasMode = mode;
216829
+ }
216938
216830
  var gitDiffState = null;
216939
216831
  async function navigateToComponent(componentPath) {
216940
216832
  try {
@@ -216943,9 +216835,27 @@ async function navigateToComponent(componentPath) {
216943
216835
  if (!content3)
216944
216836
  return;
216945
216837
  const parsed = JSON.parse(content3);
216946
- S = pushDocument(S, parsed, componentPath);
216947
- S.dirty = false;
216948
- ({ doc, session } = fromFlat(S));
216838
+ const tab = activeTab.value;
216839
+ if (!tab)
216840
+ return;
216841
+ const frame = {
216842
+ document: tab.doc.document,
216843
+ selection: tab.session.selection,
216844
+ documentPath: tab.documentPath,
216845
+ dirty: tab.doc.dirty,
216846
+ mode: tab.doc.mode
216847
+ };
216848
+ if (!tab.session.documentStack)
216849
+ tab.session.documentStack = [];
216850
+ tab.session.documentStack.push(frame);
216851
+ tab.doc.document = parsed;
216852
+ tab.doc.dirty = false;
216853
+ tab.doc.mode = null;
216854
+ tab.documentPath = componentPath;
216855
+ tab.session.selection = null;
216856
+ view.leftTab = "layers";
216857
+ tab.session.ui.activeMedia = null;
216858
+ tab.session.ui.activeSelector = null;
216949
216859
  render();
216950
216860
  statusMessage(`Editing component: ${parsed.tagName || componentPath}`);
216951
216861
  } catch (e20) {
@@ -216954,24 +216864,33 @@ async function navigateToComponent(componentPath) {
216954
216864
  }
216955
216865
  }
216956
216866
  async function navigateBack() {
216957
- if (!S.documentStack || S.documentStack.length === 0)
216867
+ const tab = activeTab.value;
216868
+ if (!tab?.session.documentStack || tab.session.documentStack.length === 0)
216958
216869
  return;
216959
- if (S.dirty && S.documentPath) {
216870
+ if (tab.doc.dirty && tab.documentPath) {
216960
216871
  try {
216961
216872
  const platform4 = getPlatform();
216962
- await platform4.writeFile(S.documentPath, JSON.stringify(S.document, null, 2));
216873
+ await platform4.writeFile(tab.documentPath, JSON.stringify(tab.doc.document, null, 2));
216963
216874
  } catch (e20) {
216964
216875
  const err = e20;
216965
216876
  statusMessage(`Save error: ${err.message}`);
216966
216877
  }
216967
216878
  }
216968
- S = popDocument(S);
216969
- ({ doc, session } = fromFlat(S));
216879
+ const frame = tab.session.documentStack.pop();
216880
+ if (!frame)
216881
+ return;
216882
+ tab.doc.document = frame.document;
216883
+ tab.doc.dirty = frame.dirty;
216884
+ tab.doc.mode = frame.mode;
216885
+ tab.documentPath = frame.documentPath;
216886
+ tab.session.selection = frame.selection;
216887
+ view.leftTab = "layers";
216970
216888
  render();
216971
216889
  statusMessage("Returned to parent document");
216972
216890
  }
216973
216891
  async function closeFunctionEditor() {
216974
- const editing = S.ui.editingFunction;
216892
+ const tab = activeTab.value;
216893
+ const editing = tab?.session.ui.editingFunction;
216975
216894
  if (!editing)
216976
216895
  return;
216977
216896
  if (view.functionEditor) {
@@ -216979,11 +216898,11 @@ async function closeFunctionEditor() {
216979
216898
  const minResult = await codeService("minify", { code: currentCode });
216980
216899
  const bodyToStore = minResult?.code ?? currentCode;
216981
216900
  if (editing.type === "def") {
216982
- transactDoc(activeTab.value, (t15) => mutateUpdateDef(t15, editing.defName, { body: bodyToStore }));
216901
+ transactDoc(tab, (t15) => mutateUpdateDef(t15, editing.defName, { body: bodyToStore }));
216983
216902
  } else if (editing.type === "event") {
216984
- const node2 = getNodeAtPath(S.document, editing.path);
216903
+ const node2 = getNodeAtPath(tab.doc.document, editing.path);
216985
216904
  const current = node2?.[editing.eventKey] || {};
216986
- transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, editing.path, editing.eventKey, {
216905
+ transactDoc(tab, (t15) => mutateUpdateProperty(t15, editing.path, editing.eventKey, {
216987
216906
  ...current,
216988
216907
  $prototype: "Function",
216989
216908
  body: bodyToStore
@@ -217017,74 +216936,57 @@ var EMPTY_DOC = {
217017
216936
  { tagName: "p", textContent: "Open a Jx file or start editing." }
217018
216937
  ]
217019
216938
  };
217020
- S = createState(structuredClone(EMPTY_DOC));
217021
- ({ doc, session } = fromFlat(S));
217022
- setGetStateFn(() => S);
217023
216939
  openTab({ id: "initial", document: structuredClone(EMPTY_DOC) });
217024
216940
  mount5(toolbarEl, {
217025
216941
  navigateBack: () => navigateBack(),
217026
216942
  closeFunctionEditor: () => closeFunctionEditor(),
217027
216943
  openProject: () => openProject2(),
217028
- openFile: () => openFile2(),
217029
- saveFile: () => saveFile2(),
216944
+ openFile: () => openFile(),
216945
+ saveFile: () => saveFile(),
217030
216946
  parseMediaEntries,
217031
- getCanvasMode: () => canvasMode,
217032
- setCanvasMode: (m3) => {
217033
- if (canvasMode === "git-diff" && m3 !== "git-diff") {
217034
- gitDiffState = null;
217035
- }
217036
- canvasMode = m3;
217037
- },
216947
+ getCanvasMode,
216948
+ setCanvasMode,
217038
216949
  renderCanvas: () => renderCanvas(),
217039
216950
  safeRenderRightPanel: () => safeRenderRightPanel()
217040
216951
  });
217041
216952
  mount8(document.querySelector("#tab-strip"));
217042
216953
  mount3({
217043
- getCanvasMode: () => canvasMode,
216954
+ getCanvasMode,
217044
216955
  isEditing,
217045
216956
  renderBlockActionBar
217046
216957
  });
217047
216958
  initBlockActionBar({
217048
- getCanvasMode: () => canvasMode,
216959
+ getCanvasMode,
217049
216960
  navigateToComponent,
217050
216961
  createFloatingContainer
217051
216962
  });
217052
216963
  initComponentInlineEdit({ findCanvasElement });
217053
- initCanvasHelpers({ getCanvasMode: () => canvasMode, getZoom: () => S.ui.zoom });
216964
+ initCanvasHelpers({
216965
+ getCanvasMode,
216966
+ getZoom: () => activeTab.value?.session.ui.zoom ?? 1
216967
+ });
217054
216968
  initCanvasUtils({
217055
- getCanvasMode: () => canvasMode,
217056
- getZoom: () => S.ui.zoom,
216969
+ getCanvasMode,
216970
+ getZoom: () => activeTab.value?.session.ui.zoom ?? 1,
217057
216971
  setZoomDirect: (zoom) => {
217058
- session = { ...session, ui: { ...session.ui, zoom } };
217059
- S = toFlat(doc, session);
217060
216972
  if (activeTab.value)
217061
216973
  activeTab.value.session.ui.zoom = zoom;
217062
216974
  },
217063
216975
  renderStylebookOverlays
217064
216976
  });
217065
216977
  initPanelEvents({
217066
- getState: () => S,
217067
- setState: (s2) => {
217068
- S = s2;
217069
- ({ doc, session } = fromFlat(S));
217070
- },
217071
- getCanvasMode: () => canvasMode,
216978
+ getCanvasMode,
217072
216979
  enterInlineEdit,
217073
216980
  navigateToComponent
217074
216981
  });
217075
216982
  initCanvasLiveRender({
217076
- getCanvasMode: () => canvasMode
216983
+ getCanvasMode
217077
216984
  });
217078
216985
  initCanvasRender({
217079
- getCanvasMode: () => canvasMode,
217080
- setCanvasMode: (mode) => {
217081
- if (canvasMode === "git-diff" && mode !== "git-diff") {
217082
- gitDiffState = null;
217083
- }
217084
- canvasMode = mode;
217085
- },
217086
- openFileFromTree: openFileFromTree2,
217087
- exportFile: exportFile2,
216986
+ getCanvasMode,
216987
+ setCanvasMode,
216988
+ openFileFromTree,
216989
+ exportFile,
217088
216990
  gitDiffState,
217089
216991
  setGitDiffState: (state3) => {
217090
216992
  gitDiffState = state3;
@@ -217097,6 +216999,7 @@ effect(() => {
217097
216999
  return;
217098
217000
  tab.doc.document;
217099
217001
  tab.doc.mode;
217002
+ tab.session.ui.canvasMode;
217100
217003
  tab.session.ui.editingFunction;
217101
217004
  tab.session.ui.featureToggles;
217102
217005
  tab.session.ui.settingsTab;
@@ -217117,15 +217020,13 @@ effect(() => {
217117
217020
  });
217118
217021
  mount6({
217119
217022
  navigateToComponent,
217120
- getCanvasMode: () => canvasMode,
217023
+ getCanvasMode,
217121
217024
  renderCanvas: () => renderCanvas(),
217122
217025
  updateForcedPseudoPreview
217123
217026
  });
217124
217027
  mount7({
217125
- getCanvasMode: () => canvasMode,
217126
- setCanvasMode: (mode) => {
217127
- canvasMode = mode;
217128
- },
217028
+ getCanvasMode,
217029
+ setCanvasMode,
217129
217030
  renderImportsTemplate,
217130
217031
  renderFilesTemplate: renderFilesTemplate2,
217131
217032
  renderSignalsTemplate,
@@ -217147,76 +217048,19 @@ registerRenderer("leftPanel", () => render9());
217147
217048
  registerRenderer("canvas", () => renderCanvas());
217148
217049
  registerRenderer("rightPanel", () => render8());
217149
217050
  registerRenderer("overlays", () => render4());
217150
- setStatusbarRenderer(() => renderStatusbar(S));
217051
+ setStatusbarRenderer(() => renderStatusbar());
217151
217052
  mountStatusbar();
217152
217053
  mount4();
217153
217054
  canvasWrap.addEventListener("click", (e20) => {
217154
217055
  if (e20.target !== canvasWrap && e20.target !== view.panzoomWrap)
217155
217056
  return;
217156
- if (!S.selection)
217057
+ if (!activeTab.value?.session.selection)
217157
217058
  return;
217158
217059
  activeTab.value.session.selection = null;
217159
217060
  });
217160
217061
  function safeRenderRightPanel() {
217161
217062
  render8();
217162
217063
  }
217163
- setGetStateFn(() => S);
217164
- setUpdateFn(function _update(newState) {
217165
- const prevDoc = S.document;
217166
- const prevSel = S.selection;
217167
- const prevUi = S.ui;
217168
- S = newState;
217169
- ({ doc, session } = fromFlat(S));
217170
- const tab = activeTab.value;
217171
- if (tab) {
217172
- tab.doc.document = S.document;
217173
- tab.doc.dirty = S.dirty;
217174
- tab.doc.mode = S.mode;
217175
- tab.doc.handlersSource = S.handlersSource;
217176
- tab.doc.content.frontmatter = S.content?.frontmatter ?? {};
217177
- tab.session.selection = S.selection;
217178
- tab.session.hover = S.hover;
217179
- tab.session.clipboard = S.clipboard ?? null;
217180
- for (const [k, v] of Object.entries(S.ui || {})) {
217181
- tab.session.ui[k] = v;
217182
- }
217183
- tab.session.canvas.status = S.canvas?.status ?? "idle";
217184
- tab.session.canvas.scope = S.canvas?.scope ?? null;
217185
- tab.session.canvas.error = S.canvas?.error ?? null;
217186
- }
217187
- if (prevUi?.activeMedia !== S.ui?.activeMedia) {
217188
- updateActivePanelHeaders();
217189
- }
217190
- runPostRenderHooks(prevDoc, prevSel);
217191
- runUpdateMiddleware(S);
217192
- });
217193
- setUpdateSessionFn(function _updateSession(patch2) {
217194
- const prev = session;
217195
- session = { ...session, ...patch2 };
217196
- if (patch2.ui) {
217197
- session.ui = { ...prev.ui, ...patch2.ui };
217198
- }
217199
- if (patch2.canvas) {
217200
- session.canvas = { ...prev.canvas, ...patch2.canvas };
217201
- }
217202
- S = toFlat(doc, session);
217203
- if (prev.ui?.activeMedia !== session.ui?.activeMedia) {
217204
- updateActivePanelHeaders();
217205
- }
217206
- const canvasChanged = prev.canvas !== session.canvas;
217207
- if (canvasChanged && session.canvas.status === "ready" && session.ui?.pendingInlineEdit) {
217208
- const { path: path2, mediaName: mn } = session.ui.pendingInlineEdit;
217209
- updateUi("pendingInlineEdit", null);
217210
- const targetPanel = canvasPanels.find((p2) => p2.mediaName === mn) || canvasPanels[0];
217211
- if (targetPanel) {
217212
- const el = findCanvasElement(path2, targetPanel.canvas);
217213
- if (el)
217214
- enterComponentInlineEdit(el, path2);
217215
- }
217216
- }
217217
- runPostRenderHooks(doc.document, prev.selection);
217218
- });
217219
- addPostRenderHook(() => updateForcedPseudoPreview());
217220
217064
  registerFunctionCompletions();
217221
217065
  var _openParam = new URLSearchParams(location.search).get("open");
217222
217066
  if (_openParam) {
@@ -217275,29 +217119,27 @@ if (_openParam) {
217275
217119
  const fileRelPath = _fileParam || siteCtx.fileRelPath || _openParam;
217276
217120
  const content3 = await platform4.readFile(fileRelPath);
217277
217121
  if (content3) {
217278
- let parsedDoc;
217279
- if (fileRelPath.endsWith(".md")) {
217280
- const ns = await loadMarkdown(content3, null);
217281
- S = ns;
217282
- S.documentPath = fileRelPath;
217283
- parsedDoc = S.document;
217122
+ let parsedDoc, frontmatter2;
217123
+ const isMd = fileRelPath.endsWith(".md");
217124
+ if (isMd) {
217125
+ const result = await loadMarkdown(content3);
217126
+ parsedDoc = result.document;
217127
+ frontmatter2 = result.frontmatter;
217284
217128
  } else {
217285
217129
  parsedDoc = JSON.parse(content3);
217286
- S = createState(parsedDoc);
217287
- S.documentPath = fileRelPath;
217288
- }
217289
- S.dirty = false;
217290
- S.ui = { ...S.ui, leftTab: "files" };
217291
- ({ doc, session } = fromFlat(S));
217292
- const tab = activeTab.value;
217293
- if (tab) {
217294
- tab.doc.document = S.document;
217295
- tab.doc.mode = S.mode;
217296
- tab.doc.dirty = false;
217297
- tab.doc.content = S.content || { frontmatter: {} };
217298
- tab.documentPath = fileRelPath;
217299
- tab.session.ui.leftTab = "files";
217300
217130
  }
217131
+ const { closeTab: closeTab2 } = await Promise.resolve().then(() => (init_workspace(), exports_workspace));
217132
+ closeTab2("initial");
217133
+ openTab({
217134
+ id: fileRelPath,
217135
+ documentPath: fileRelPath,
217136
+ document: parsedDoc,
217137
+ frontmatter: frontmatter2,
217138
+ sourceFormat: isMd ? "md" : null
217139
+ });
217140
+ if (isMd && activeTab.value)
217141
+ activeTab.value.doc.mode = "content";
217142
+ view.leftTab = "files";
217301
217143
  render();
217302
217144
  statusMessage(`Opened ${_openParam}`);
217303
217145
  }
@@ -217313,56 +217155,23 @@ if (_openParam) {
217313
217155
  function renderLeftPanel() {
217314
217156
  render9();
217315
217157
  }
217316
- function renderToolbar() {
217317
- render7();
217318
- }
217319
- function fileOpsCtx() {
217320
- return {
217321
- S,
217322
- commit: (ns) => {
217323
- S = ns;
217324
- ({ doc, session } = fromFlat(S));
217325
- render();
217326
- },
217327
- renderToolbar
217328
- };
217329
- }
217330
- function openFile2() {
217331
- return openFile(fileOpsCtx());
217332
- }
217333
- function saveFile2() {
217334
- return saveFile(fileOpsCtx());
217335
- }
217336
- function exportFile2() {
217337
- return exportFile(fileOpsCtx());
217338
- }
217339
217158
  function loadProject2() {
217340
217159
  return loadProject();
217341
217160
  }
217342
217161
  function openProject2() {
217343
217162
  return openProject({
217344
- S,
217345
- commit: (ns) => {
217346
- S = ns;
217347
- ({ doc, session } = fromFlat(S));
217348
- },
217349
217163
  renderActivityBar: () => renderActivityBar(),
217350
217164
  renderLeftPanel
217351
217165
  });
217352
217166
  }
217353
217167
  function renderFilesTemplate2() {
217354
- return renderFilesTemplate({ openProject: openProject2, openFileFromTree: openFileFromTree2, renderLeftPanel });
217168
+ return renderFilesTemplate({ openProject: openProject2, openFileFromTree, renderLeftPanel });
217355
217169
  }
217356
- function openFileFromTree2(path2) {
217170
+ function openFileFromTree(path2) {
217357
217171
  return openFileInTab(path2);
217358
217172
  }
217359
217173
  initShortcuts(() => ({
217360
- S,
217361
- setS: (ns) => {
217362
- S = ns;
217363
- ({ doc, session } = fromFlat(S));
217364
- },
217365
- canvasMode,
217174
+ canvasMode: getCanvasMode(),
217366
217175
  panX: view.panX,
217367
217176
  panY: view.panY,
217368
217177
  setPan: (x, y) => {
@@ -217373,7 +217182,7 @@ initShortcuts(() => ({
217373
217182
  applyTransform,
217374
217183
  positionZoomIndicator,
217375
217184
  componentInlineEdit: view.componentInlineEdit,
217376
- saveFile: saveFile2,
217185
+ saveFile,
217377
217186
  openProject: openProject2,
217378
217187
  enterEditOnPath(path2) {
217379
217188
  requestAnimationFrame(() => {
@@ -217389,25 +217198,27 @@ initShortcuts(() => ({
217389
217198
  }));
217390
217199
  var AUTO_SAVE_DELAY = 2000;
217391
217200
  function scheduleAutosave() {
217392
- if (!S.fileHandle || !S.dirty)
217201
+ const tab = activeTab.value;
217202
+ if (!tab?.fileHandle || !tab.doc.dirty)
217393
217203
  return;
217394
217204
  clearTimeout(view.autosaveTimer);
217395
217205
  view.autosaveTimer = setTimeout(async () => {
217396
- if (S.fileHandle && S.dirty && "createWritable" in S.fileHandle) {
217206
+ const t15 = activeTab.value;
217207
+ if (t15?.fileHandle && t15.doc.dirty && "createWritable" in t15.fileHandle) {
217397
217208
  try {
217398
- const writable = await S.fileHandle.createWritable();
217399
- await writable.write(JSON.stringify(S.document, null, 2));
217209
+ const writable = await t15.fileHandle.createWritable();
217210
+ await writable.write(JSON.stringify(t15.doc.document, null, 2));
217400
217211
  await writable.close();
217401
- activeTab.value.doc.dirty = false;
217212
+ t15.doc.dirty = false;
217402
217213
  statusMessage("Auto-saved");
217403
217214
  } catch {}
217404
217215
  }
217405
217216
  }, AUTO_SAVE_DELAY);
217406
217217
  }
217407
- addUpdateMiddleware((state3) => {
217408
- if (state3.dirty)
217218
+ effect(() => {
217219
+ if (activeTab.value?.doc.dirty)
217409
217220
  scheduleAutosave();
217410
217221
  });
217411
217222
 
217412
- //# debugId=B17DF22CF984123464756E2164756E21
217223
+ //# debugId=B73DF558C97F3D0664756E2164756E21
217413
217224
  //# sourceMappingURL=studio.js.map