@jxsuite/studio 3.0.0 → 4.1.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.
Files changed (197) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/{2020-xp8vnwma.js → 2020-n6tfwnda.js} +2 -2
  3. package/dist/chunks/Overlay.dev-etqjwyf9.js +23 -0
  4. package/dist/chunks/cf-account-picker-en86v7x7.js +163 -0
  5. package/dist/chunks/{cf-settings-zj2cj1ar.js → cf-settings-45fgyx8y.js} +6 -5
  6. package/dist/chunks/{components-z6cnkyy1.js → components-zmx10t62.js} +6 -5
  7. package/dist/chunks/content-source-48xg86wj.js +49 -0
  8. package/dist/chunks/{convert-to-repeater-6vvx96n2.js → convert-to-repeater-43tfn7cs.js} +33 -25
  9. package/dist/chunks/entry-commands-e63f1xc0.js +46 -0
  10. package/dist/chunks/{extension-sections-kwzvpemr.js → extension-sections-txv08xxg.js} +34 -26
  11. package/dist/chunks/file-ops-wbh4hhsx.js +48 -0
  12. package/dist/chunks/files-3kfkwhk4.js +93 -0
  13. package/dist/chunks/{focus-trap.esm-ggawf1hy.js → focus-trap.esm-9t2drp0g.js} +6 -5
  14. package/dist/chunks/{format-host-8fr3545e.js → format-host-w16q81tf.js} +3 -3
  15. package/dist/chunks/fs-events-hrrg328g.js +21 -0
  16. package/dist/chunks/{git-panel-g01d93vc.js → git-panel-532whr1y.js} +22 -16
  17. package/dist/chunks/{index-nj44jpzj.js → index-wcnt3r9g.js} +2 -2
  18. package/dist/chunks/{jx-validate-jj9rnt4n.js → jx-validate-8er6gbxy.js} +6 -4
  19. package/dist/chunks/layers-panel-07hm7g5j.js +67 -0
  20. package/dist/chunks/layers-q75tj2mf.js +45 -0
  21. package/dist/chunks/lit-html-j055mkh8.js +22 -0
  22. package/dist/chunks/monaco-buffer-dqw0xxpx.js +25 -0
  23. package/dist/chunks/{monaco-setup-a5wkmbgh.js → monaco-setup-vx9bhp1d.js} +4 -4
  24. package/dist/chunks/notify-yjm79n4s.js +30 -0
  25. package/dist/chunks/parse-24d0gay3.js +19 -0
  26. package/dist/chunks/platform-ba1j1gbh.js +16 -0
  27. package/dist/chunks/publish-panel-v9st96ja.js +29 -0
  28. package/dist/chunks/quick-search-zccjp6gv.js +66 -0
  29. package/dist/chunks/references-3qx8fkyp.js +29 -0
  30. package/dist/chunks/right-panel-vm3b6kwy.js +46 -0
  31. package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +18 -0
  32. package/dist/chunks/sp-popover.dev-n2etmqdp.js +9 -0
  33. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +15 -0
  34. package/dist/chunks/sp-tooltip.dev-4sastdnw.js +15 -0
  35. package/dist/chunks/{sp-tray.dev-64v4pxw8.js → sp-tray.dev-tkbscm06.js} +5 -5
  36. package/dist/chunks/{studio-wdt9y92a.js → studio-0bq6eh7v.js} +2 -2
  37. package/dist/chunks/studio-1ngbejft.js +181 -0
  38. package/dist/chunks/studio-1wagb550.js +118 -0
  39. package/dist/chunks/{studio-j595e748.js → studio-2b946z26.js} +172 -95
  40. package/dist/chunks/{studio-pkp61mh8.js → studio-3bqpr0zh.js} +25 -17
  41. package/dist/chunks/{studio-k4jvjcfx.js → studio-4b5z1x43.js} +46 -12
  42. package/dist/chunks/{studio-ry1vz5sv.js → studio-4n2b5gzb.js} +15 -13
  43. package/dist/chunks/{studio-p5dja96s.js → studio-4r1pv6zf.js} +2 -2
  44. package/dist/chunks/{studio-kvfx9z2c.js → studio-4rzyrtjz.js} +70 -31
  45. package/dist/chunks/{studio-tzx3xmvx.js → studio-5fx3g9jg.js} +33 -52
  46. package/dist/chunks/{studio-rh1cnamv.js → studio-5myknm0a.js} +565 -135
  47. package/dist/chunks/studio-6yw4y3my.js +91 -0
  48. package/dist/chunks/{studio-0rqqhrdy.js → studio-7nte2hj4.js} +2 -2
  49. package/dist/chunks/studio-92ab2jqe.js +282 -0
  50. package/dist/chunks/{studio-6z5eyjwn.js → studio-950k0dx6.js} +72 -135
  51. package/dist/chunks/{studio-sas7mt3k.js → studio-9ab8gqsm.js} +2 -2
  52. package/dist/chunks/studio-9n4mrmnb.js +184 -0
  53. package/dist/chunks/{studio-hcxzyk3x.js → studio-ahn3pdgx.js} +6 -6
  54. package/dist/chunks/studio-b55y6ewx.js +498 -0
  55. package/dist/chunks/{studio-s519zc99.js → studio-bgxt93ga.js} +3 -3
  56. package/dist/chunks/studio-cft9r4r7.js +119 -0
  57. package/dist/chunks/{studio-dc8s8heb.js → studio-cmb03bg5.js} +6904 -8321
  58. package/dist/chunks/studio-dm19q43r.js +195 -0
  59. package/dist/chunks/{studio-2x9zbxmx.js → studio-ef49pnzx.js} +11 -9
  60. package/dist/chunks/{studio-ay8wcr2b.js → studio-eqq1w638.js} +7 -9
  61. package/dist/chunks/{studio-5efrtn1m.js → studio-ew0djmhg.js} +23 -19
  62. package/dist/chunks/{studio-tr20m8g8.js → studio-f3wqjtk5.js} +39 -3
  63. package/dist/chunks/{studio-xntfdy1x.js → studio-fbf92ckf.js} +36 -23
  64. package/dist/chunks/{studio-4q0wznzf.js → studio-gcye7qka.js} +442 -126
  65. package/dist/chunks/{studio-7p35254k.js → studio-gfgb8pe6.js} +36 -193
  66. package/dist/chunks/studio-jc994dnr.js +1066 -0
  67. package/dist/chunks/{studio-hj2se583.js → studio-jkftxyvz.js} +69 -3423
  68. package/dist/chunks/{studio-5x5774ak.js → studio-kryvsw6j.js} +3 -3
  69. package/dist/chunks/{studio-kfpek536.js → studio-kyh9avvv.js} +2 -2
  70. package/dist/chunks/{studio-twsafr1e.js → studio-m3hwn7y1.js} +3 -3
  71. package/dist/chunks/studio-msd847zn.js +1315 -0
  72. package/dist/chunks/{studio-g5gdqnyd.js → studio-mtfnaqs9.js} +19 -19
  73. package/dist/chunks/{studio-7ejemhej.js → studio-n6j9t10q.js} +6 -6
  74. package/dist/chunks/{studio-vhk5fmfv.js → studio-n8b9wqwy.js} +5 -5
  75. package/dist/chunks/{studio-cjm7fdjf.js → studio-p4ngc046.js} +8 -104
  76. package/dist/chunks/studio-q43a5y9h.js +394 -0
  77. package/dist/chunks/studio-q7v10cg2.js +106 -0
  78. package/dist/chunks/{studio-6kv3apa9.js → studio-q9jd1a60.js} +27 -11
  79. package/dist/chunks/studio-qcy05dp8.js +1743 -0
  80. package/dist/chunks/{studio-a0yp7syn.js → studio-qjy2z9bv.js} +29 -132
  81. package/dist/chunks/{studio-2w11grav.js → studio-qq6jym04.js} +3 -3
  82. package/dist/chunks/{studio-3fk1ac9z.js → studio-rdx8jcxy.js} +4 -4
  83. package/dist/chunks/{studio-4mqb9a0j.js → studio-rn9ta2mz.js} +4 -4
  84. package/dist/chunks/studio-t7qb9db8.js +665 -0
  85. package/dist/chunks/studio-tmc5emrw.js +8 -0
  86. package/dist/chunks/{studio-r5xbtctf.js → studio-trxrabqf.js} +292 -2297
  87. package/dist/chunks/studio-wcy8trfx.js +263 -0
  88. package/dist/chunks/{studio-3dkcd4c5.js → studio-x4qkdat5.js} +62 -57
  89. package/dist/chunks/studio-x813zp48.js +195 -0
  90. package/dist/chunks/{studio-qpfq7xhm.js → studio-xrapxwwc.js} +22 -285
  91. package/dist/chunks/{studio-xm3dbxvn.js → studio-zczps70q.js} +2 -2
  92. package/dist/chunks/{studio-8ezdegcx.js → studio-zqazsct2.js} +40 -36
  93. package/dist/chunks/workspace-fjx52ryv.js +89 -0
  94. package/dist/iframe-entry.js +141 -56
  95. package/dist/manifest.json +7 -0
  96. package/dist/studio.js +2605 -1950
  97. package/favicon.ico +0 -0
  98. package/index.html +1 -0
  99. package/package.json +20 -18
  100. package/src/about/about-modal.ts +4 -3
  101. package/src/browse/library-pane.ts +57 -3
  102. package/src/canvas/canvas-render.ts +23 -1
  103. package/src/canvas/iframe-patch.ts +47 -21
  104. package/src/canvas/iframe-render.ts +22 -6
  105. package/src/commands/app-commands.ts +4 -0
  106. package/src/commands/command-args.ts +29 -0
  107. package/src/commands/context.ts +15 -1
  108. package/src/commands/defaults.ts +29 -1
  109. package/src/commands/levels.ts +16 -0
  110. package/src/commands/live-context.ts +3 -0
  111. package/src/content/collection-match.ts +267 -0
  112. package/src/content/entry-commands.ts +38 -29
  113. package/src/content/entry-fields.ts +6 -0
  114. package/src/editor/shortcuts.ts +5 -0
  115. package/src/files/file-ops.ts +10 -42
  116. package/src/files/files.ts +487 -59
  117. package/src/files/fs-events.ts +9 -0
  118. package/src/files/gitignore.ts +432 -0
  119. package/src/files/media-paths.ts +13 -42
  120. package/src/files/media-usage.ts +41 -131
  121. package/src/files/serialize-document.ts +60 -0
  122. package/src/format/convert-file.ts +511 -0
  123. package/src/format/format-choices.ts +199 -0
  124. package/src/grid/grid-view.ts +16 -2
  125. package/src/hosting/document.ts +2 -0
  126. package/src/hosting/layout.ts +8 -0
  127. package/src/media/media-open.ts +58 -0
  128. package/src/media/media-pane.ts +310 -0
  129. package/src/new-project/import-tab.ts +357 -163
  130. package/src/new-project/location-fields.ts +8 -5
  131. package/src/new-project/new-project-modal.ts +27 -34
  132. package/src/packages/ensure-deps.ts +14 -7
  133. package/src/packages/jxsuite-update.ts +11 -11
  134. package/src/page-params.ts +10 -46
  135. package/src/panels/activity-bar.ts +45 -16
  136. package/src/panels/ai-chat/attached-context.ts +6 -1
  137. package/src/panels/ai-chat/chat-view.ts +255 -13
  138. package/src/panels/ai-chat/composer.ts +31 -97
  139. package/src/panels/ai-panel.ts +116 -2
  140. package/src/panels/navigator-panels.ts +7 -6
  141. package/src/panels/settings-menu.ts +799 -0
  142. package/src/panels/toolbar.ts +135 -15
  143. package/src/platforms/cloud.ts +261 -70
  144. package/src/platforms/devserver.ts +67 -33
  145. package/src/preview/preview-overlay.ts +226 -0
  146. package/src/publish/publish-panel.ts +62 -2
  147. package/src/services/ai-ask.ts +247 -0
  148. package/src/services/ai-import-tools.ts +532 -0
  149. package/src/services/ai-models.ts +108 -1
  150. package/src/services/ai-project-tools.ts +20 -26
  151. package/src/services/ai-system-prompt.ts +88 -2
  152. package/src/services/ai-turn-signal.ts +70 -0
  153. package/src/services/connection.ts +74 -0
  154. package/src/services/context-manager.ts +101 -1
  155. package/src/services/document-assistant.ts +45 -4
  156. package/src/services/import-client.ts +33 -6
  157. package/src/services/import-run.ts +158 -0
  158. package/src/services/import-seed.ts +120 -0
  159. package/src/services/jx-validate.ts +58 -6
  160. package/src/services/project-adoption.ts +71 -0
  161. package/src/services/references.ts +0 -0
  162. package/src/services/settings/definitions.ts +17 -0
  163. package/src/services/tool-executor.ts +45 -2
  164. package/src/settings/contexts-section.ts +45 -3
  165. package/src/settings/dependencies-editor.ts +43 -23
  166. package/src/settings/general-settings.ts +30 -12
  167. package/src/settings/preferences-accounts.ts +193 -12
  168. package/src/settings/preferences-dialog.ts +93 -59
  169. package/src/settings/preferences-sections.ts +57 -0
  170. package/src/settings/settings-document.ts +65 -9
  171. package/src/studio.ts +33 -6
  172. package/src/tabs/transact.ts +42 -19
  173. package/src/types.ts +129 -7
  174. package/src/ui/ai-managed-connect.ts +62 -13
  175. package/src/ui/ai-model-picker.ts +189 -0
  176. package/src/ui/cf-account-picker.ts +200 -0
  177. package/src/ui/choice-field.ts +72 -0
  178. package/src/ui/layers.ts +83 -5
  179. package/src/utils/studio-utils.ts +22 -52
  180. package/styles/forced-colors.css +7 -0
  181. package/styles/overlays.css +256 -0
  182. package/styles/panels.css +13 -1
  183. package/styles/shell.css +147 -0
  184. package/dist/chunks/Overlay.dev-d2ajy6sj.js +0 -23
  185. package/dist/chunks/content-source-7fy9qrm0.js +0 -40
  186. package/dist/chunks/files-xcybanxe.js +0 -70
  187. package/dist/chunks/layers-panel-27essgkc.js +0 -60
  188. package/dist/chunks/publish-panel-09sy2bab.js +0 -22
  189. package/dist/chunks/quick-search-sefb61v8.js +0 -55
  190. package/dist/chunks/right-panel-9r32jd5j.js +0 -39
  191. package/dist/chunks/sp-overlay.dev-s18hymn9.js +0 -18
  192. package/dist/chunks/sp-popover.dev-dj9x7e7a.js +0 -9
  193. package/dist/chunks/sp-progress-circle.dev-0zxcyz3r.js +0 -15
  194. package/dist/chunks/sp-tooltip.dev-5c6d1kjz.js +0 -15
  195. package/dist/chunks/studio-bw5dz6km.js +0 -608
  196. package/dist/chunks/studio-c31yb4t6.js +0 -55
  197. package/src/canvas/site-style-css.ts +0 -117
@@ -1499,6 +1499,39 @@ function computed(getterOrOptions, debugOptions, isSSR = false) {
1499
1499
  return cRef;
1500
1500
  }
1501
1501
 
1502
+ // ../runtime/src/css.ts
1503
+ function camelToKebab(s) {
1504
+ return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
1505
+ }
1506
+ var MEDIA_TYPES = new Set(["all", "print", "screen", "speech"]);
1507
+ function resolveAtQuery(atKey, mediaQueries) {
1508
+ if (atKey.startsWith("@--")) {
1509
+ return mediaQueries[atKey.slice(1)] ?? atKey.slice(1);
1510
+ }
1511
+ if (atKey.startsWith("@(")) {
1512
+ const inner = atKey.slice(2, -1).trim();
1513
+ return MEDIA_TYPES.has(inner.toLowerCase()) ? inner : atKey.slice(1);
1514
+ }
1515
+ return null;
1516
+ }
1517
+ var COLOR_SCHEME_ATTR = "data-color-scheme";
1518
+ function pureSchemeOf(query) {
1519
+ const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
1520
+ return m?.[1] ?? null;
1521
+ }
1522
+ function schemeSelectors(selector, scheme) {
1523
+ if (selector === ":root" || selector === "html") {
1524
+ return {
1525
+ auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
1526
+ forced: `${selector}:where([${COLOR_SCHEME_ATTR}="${scheme}"])`
1527
+ };
1528
+ }
1529
+ return {
1530
+ auto: `:where(:root:not([${COLOR_SCHEME_ATTR}])) ${selector}`,
1531
+ forced: `:where(:root[${COLOR_SCHEME_ATTR}="${scheme}"]) ${selector}`
1532
+ };
1533
+ }
1534
+
1502
1535
  // ../schema/src/intl.ts
1503
1536
  var DEFAULT_FORMAT_LOCALE = "en-US";
1504
1537
  var DEFAULT_TIME_ZONE = "UTC";
@@ -2372,7 +2405,6 @@ function serializeCookie(name, value, options) {
2372
2405
  }
2373
2406
  return parts.join("; ");
2374
2407
  }
2375
-
2376
2408
  // ../runtime/src/runtime.ts
2377
2409
  var _resolveCache = new Map;
2378
2410
  async function resolve(source) {
@@ -2688,6 +2720,32 @@ function evaluateTemplate(str, state) {
2688
2720
  const fn = new Function("state", "$map", "item", "index", `return \`${str}\``);
2689
2721
  return fn(state, $map, $map?.item, $map?.index);
2690
2722
  }
2723
+ function isSingleExpression(str) {
2724
+ if (!str.startsWith("${") || !str.endsWith("}")) {
2725
+ return false;
2726
+ }
2727
+ let depth = 0;
2728
+ for (let i = 1;i < str.length; i += 1) {
2729
+ const c = str[i];
2730
+ if (c === "{") {
2731
+ depth += 1;
2732
+ } else if (c === "}") {
2733
+ depth -= 1;
2734
+ if (depth === 0) {
2735
+ return i === str.length - 1;
2736
+ }
2737
+ }
2738
+ }
2739
+ return false;
2740
+ }
2741
+ function evaluateAttrTemplate(str, state) {
2742
+ if (!isSingleExpression(str)) {
2743
+ return evaluateTemplate(str, state);
2744
+ }
2745
+ const $map = state?.$map;
2746
+ const fn = new Function("state", "$map", "item", "index", `return (${str.slice(2, -1)})`);
2747
+ return fn(state, $map, $map?.item, $map?.index);
2748
+ }
2691
2749
  var _moduleCache = new Map;
2692
2750
  async function resolveFunction(def2, state, key, base) {
2693
2751
  if (def2.body && def2.$src) {
@@ -3084,16 +3142,33 @@ function reapplyStyle(el, styleDef, mediaQueries = {}, state = {}) {
3084
3142
  delete el.dataset.jx;
3085
3143
  applyStyle(el, styleDef ?? {}, mediaQueries, state);
3086
3144
  }
3145
+ var ENUMERATED_ATTRS = new Set(["contenteditable", "draggable", "spellcheck"]);
3146
+ function booleanAttrValue(name, value) {
3147
+ const lower = name.toLowerCase();
3148
+ if (lower.startsWith("aria-") || ENUMERATED_ATTRS.has(lower)) {
3149
+ return String(value);
3150
+ }
3151
+ return value ? "" : null;
3152
+ }
3087
3153
  function applyAttributes(el, attrs, state) {
3088
3154
  for (const [k, v] of Object.entries(attrs)) {
3089
3155
  const attr = canvasAttrName(el, k);
3090
3156
  const write = (resolved) => {
3157
+ if (typeof resolved === "boolean") {
3158
+ const text = booleanAttrValue(attr, resolved);
3159
+ if (text === null) {
3160
+ el.removeAttribute(attr);
3161
+ } else {
3162
+ el.setAttribute(attr, text);
3163
+ }
3164
+ return;
3165
+ }
3091
3166
  el.setAttribute(attr, canvasAssetValue(el.tagName, k, String(resolved ?? "")));
3092
3167
  };
3093
3168
  if (isRefObj(v)) {
3094
3169
  effect(() => write(resolveRef(v.$ref, state)));
3095
3170
  } else if (isTemplateString(v)) {
3096
- effect(() => write(evaluateTemplate(v, state)));
3171
+ effect(() => write(evaluateAttrTemplate(v, state)));
3097
3172
  } else {
3098
3173
  write(v);
3099
3174
  }
@@ -3764,40 +3839,9 @@ function mergeProps(def2, parentState) {
3764
3839
  }
3765
3840
  return child;
3766
3841
  }
3767
- function camelToKebab(s) {
3768
- return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
3769
- }
3770
3842
  function toCSSText(rules) {
3771
3843
  return Object.entries(rules).filter(([k, v]) => !isNestedSelector(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${camelToKebab(p)}: ${canvasStyleValue(String(v))}`).join("; ");
3772
3844
  }
3773
- var MEDIA_TYPES = new Set(["all", "print", "screen", "speech"]);
3774
- function resolveAtQuery(atKey, mediaQueries) {
3775
- if (atKey.startsWith("@--")) {
3776
- return mediaQueries[atKey.slice(1)] ?? atKey.slice(1);
3777
- }
3778
- if (atKey.startsWith("@(")) {
3779
- const inner = atKey.slice(2, -1).trim();
3780
- return MEDIA_TYPES.has(inner.toLowerCase()) ? inner : atKey.slice(1);
3781
- }
3782
- return null;
3783
- }
3784
- var COLOR_SCHEME_ATTR = "data-color-scheme";
3785
- function pureSchemeOf(query) {
3786
- const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
3787
- return m?.[1] ?? null;
3788
- }
3789
- function schemeSelectors(selector, scheme) {
3790
- if (selector === ":root" || selector === "html") {
3791
- return {
3792
- auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
3793
- forced: `${selector}:where([${COLOR_SCHEME_ATTR}="${scheme}"])`
3794
- };
3795
- }
3796
- return {
3797
- auto: `:where(:root:not([${COLOR_SCHEME_ATTR}])) ${selector}`,
3798
- forced: `:where(:root[${COLOR_SCHEME_ATTR}="${scheme}"]) ${selector}`
3799
- };
3800
- }
3801
3845
  var _rootMedia = {};
3802
3846
  var _elementDefs = new Map;
3803
3847
  function setRootMedia(map) {
@@ -4128,7 +4172,7 @@ function parseJxPath(serialized) {
4128
4172
  return JSON.parse(serialized);
4129
4173
  }
4130
4174
 
4131
- // src/canvas/site-style-css.ts
4175
+ // ../site/src/site-style.ts
4132
4176
  var SITE_STYLE_ID = "jx-site-style";
4133
4177
  function toDecls(props, transpose) {
4134
4178
  return Object.entries(props).map(([key, value]) => `${camelToKebab(key)}: ${transpose(String(value))}`).join("; ");
@@ -4252,7 +4296,7 @@ var EDIT_PLACEHOLDER_CSS = `
4252
4296
  font-size: 0;
4253
4297
  overflow: hidden;
4254
4298
  }
4255
- .empty-text-placeholder:not([contenteditable])::after {
4299
+ .empty-text-placeholder:is(:empty, :has(> br:only-child)):not([data-jx-active-block]):not([contenteditable])::after {
4256
4300
  content: "Click here to add text...";
4257
4301
  color: color-mix(in srgb, #808080 40%, transparent);
4258
4302
  font-style: italic;
@@ -4278,7 +4322,7 @@ var EDIT_PLACEHOLDER_CSS = `
4278
4322
  pointer-events: none;
4279
4323
  white-space: nowrap;
4280
4324
  }
4281
- [data-jx-active-block]:empty::after {
4325
+ [data-jx-active-block]:is(:empty, :has(> br:only-child))::after {
4282
4326
  content: "Type / for commands";
4283
4327
  color: color-mix(in srgb, #808080 40%, transparent);
4284
4328
  font-style: italic;
@@ -7397,6 +7441,42 @@ function startIframeSlashBridge(channel, doc) {
7397
7441
 
7398
7442
  // src/commands/levels.ts
7399
7443
  var KEY_SCOPES = ["global", "canvas", "caret", "grid", "code", "dock", "palette"];
7444
+ var PLACEMENT_MATRIX = {
7445
+ "commandbar/primary": {
7446
+ admits: ["application", "document"],
7447
+ note: "document only for Save / Undo / Redo / Open in Browser, by frequency; ≤5 total"
7448
+ },
7449
+ "commandbar/overflow": {
7450
+ admits: ["application", "project", "document"],
7451
+ note: "never selection — the Command Bar is not a selection surface"
7452
+ },
7453
+ "statusbar/project": { admits: ["project"], note: "the status bar's left field" },
7454
+ "statusbar/document": { admits: ["document"], note: "the status bar's centre field" },
7455
+ "statusbar/selection": { admits: ["selection"], note: "the status bar's right field" },
7456
+ "context/element": { admits: ["selection"], note: "the canvas element menu acts on a selection" },
7457
+ "context/file": { admits: ["project"], note: "a file row addresses the project's file set" },
7458
+ "context/layer": { admits: ["selection"], note: "an outline row IS a selection" },
7459
+ "context/tab": { admits: ["document"], note: "a tab addresses one document" },
7460
+ "context/pane": { admits: ["document"], note: "a pane hosts one document" },
7461
+ blockbar: { admits: ["selection"], note: "the floating bar owns selection-scoped verbs" },
7462
+ "blockbar/format": {
7463
+ admits: ["selection"],
7464
+ note: "the bar's inline-format cluster — a range inside the selection is still the selection"
7465
+ },
7466
+ "outline/row": { admits: ["selection"], note: "row actions act on the row's node" },
7467
+ "settings/menu": {
7468
+ admits: ["application", "project"],
7469
+ note: "the rail foot's gear menu — the settings family. It is a MENU, not a pinned slot, so it " + "may host two levels for the reason commandbar/overflow does: a menu prints each row's own " + "name, chord and gate, and draws a divider where the level changes. The rail's PINNED " + "groups stay single-level, in PANEL_PLACEMENT_MATRIX"
7470
+ },
7471
+ palette: {
7472
+ admits: ["application", "project", "document", "selection"],
7473
+ note: "the level-agnostic surface; it groups rows by level"
7474
+ },
7475
+ never: {
7476
+ admits: ["application", "project", "document", "selection"],
7477
+ note: "keyboard- and API-only; no rendered surface to be misplaced in"
7478
+ }
7479
+ };
7400
7480
 
7401
7481
  // src/commands/keymap.ts
7402
7482
  var MODIFIER_ORDER = ["mod", "ctrl", "alt", "shift"];
@@ -7683,11 +7763,18 @@ function applyIframePatch(shadowDoc, forwardOps, container, ctx, echoPaths) {
7683
7763
  const echoed = new Set(echoPaths.map((p) => serializeJxPath(p)));
7684
7764
  for (const op of forwardOps) {
7685
7765
  if (op.op === "set-key" && echoed.has(serializeJxPath(op.path))) {
7766
+ syncEchoedPlaceholder(shadowDoc, op.path, container);
7686
7767
  continue;
7687
7768
  }
7688
7769
  applyOpToDom(shadowDoc, op, container, ctx);
7689
7770
  }
7690
7771
  }
7772
+ function syncEchoedPlaceholder(doc, path, container) {
7773
+ const el = findElement(container, path);
7774
+ if (el) {
7775
+ syncPlaceholderClass(el, getNodeAtPath(doc, path));
7776
+ }
7777
+ }
7691
7778
  function requireCtx(ctx) {
7692
7779
  if (!ctx) {
7693
7780
  throw new Error("iframe-patch-no-render-ctx");
@@ -7738,7 +7825,7 @@ function insertChild(doc, parentPath, index, container, ctx) {
7738
7825
  const newEl = renderSubtreeIframe(doc, [...parentPath, "children", index], ctx);
7739
7826
  remapChildPaths(container, parentPath, index, 1);
7740
7827
  insertAt(parentEl, newEl, domChildReference(parentEl, parentNode, index));
7741
- syncContainerPlaceholder(parentEl, parentNode);
7828
+ syncPlaceholderClass(parentEl, parentNode);
7742
7829
  }
7743
7830
  function replaceSubtree(doc, docPath, container, ctx) {
7744
7831
  const oldEl = requireElement(container, docPath);
@@ -7753,7 +7840,7 @@ function removeChild(doc, parentPath, index, container) {
7753
7840
  el.remove();
7754
7841
  remapChildPaths(container, parentPath, index + 1, -1);
7755
7842
  if (parentEl) {
7756
- syncContainerPlaceholder(parentEl, getNodeAtPath(doc, parentPath));
7843
+ syncPlaceholderClass(parentEl, getNodeAtPath(doc, parentPath));
7757
7844
  }
7758
7845
  }
7759
7846
  function moveChild(doc, fromParentPath, fromIndex, toParentPath, toIndex, container) {
@@ -7769,17 +7856,17 @@ function moveChild(doc, fromParentPath, fromIndex, toParentPath, toIndex, contai
7769
7856
  const toParentNode = getNodeAtPath(doc, toPrefix);
7770
7857
  insertAt(toParentEl, el, domChildReference(toParentEl, toParentNode, toIndex));
7771
7858
  if (fromParentEl) {
7772
- syncContainerPlaceholder(fromParentEl, getNodeAtPath(doc, elementPath(fromParentEl) ?? fromParentPath));
7859
+ syncPlaceholderClass(fromParentEl, getNodeAtPath(doc, elementPath(fromParentEl) ?? fromParentPath));
7773
7860
  }
7774
- syncContainerPlaceholder(toParentEl, toParentNode);
7861
+ syncPlaceholderClass(toParentEl, toParentNode);
7775
7862
  }
7776
- function syncContainerPlaceholder(parentEl, parentNode) {
7863
+ function syncPlaceholderClass(el, node) {
7777
7864
  for (const cls of EMPTY_PLACEHOLDER_CLASSES) {
7778
- parentEl.classList.remove(cls);
7865
+ el.classList.remove(cls);
7779
7866
  }
7780
- const placeholder = parentNode ? computeEmptyPlaceholderClass(parentNode) : null;
7867
+ const placeholder = node ? computeEmptyPlaceholderClass(node) : null;
7781
7868
  if (placeholder) {
7782
- parentEl.classList.add(placeholder);
7869
+ el.classList.add(placeholder);
7783
7870
  }
7784
7871
  }
7785
7872
  function insertAt(parentEl, node, ref2) {
@@ -7837,22 +7924,20 @@ function patchText(doc, path, container) {
7837
7924
  const el = requireElement(container, path);
7838
7925
  const node = getNodeAtPath(doc, path);
7839
7926
  el.textContent = textDisplayValue(node);
7840
- for (const cls of EMPTY_PLACEHOLDER_CLASSES) {
7841
- el.classList.remove(cls);
7842
- }
7843
- const placeholder = node ? computeEmptyPlaceholderClass(node) : null;
7844
- if (placeholder) {
7845
- el.classList.add(placeholder);
7846
- }
7927
+ syncPlaceholderClass(el, node);
7847
7928
  }
7848
7929
  function requireElement(container, path) {
7930
+ const el = findElement(container, path);
7931
+ if (!el) {
7932
+ throw new Error(`iframe-patch-element-not-found:${serializeJxPath(path)}`);
7933
+ }
7934
+ return el;
7935
+ }
7936
+ function findElement(container, path) {
7849
7937
  const serialized = serializeJxPath(path);
7850
7938
  const esc = serialized.replaceAll("\\", String.raw`\\`).replaceAll("'", String.raw`\'`);
7851
7939
  const el = container.querySelector(`[data-jx-path='${esc}']`);
7852
- if (!(el instanceof HTMLElement)) {
7853
- throw new Error(`iframe-patch-element-not-found:${serialized}`);
7854
- }
7855
- return el;
7940
+ return el instanceof HTMLElement ? el : null;
7856
7941
  }
7857
7942
  function editModeStyle(style) {
7858
7943
  if (!style || typeof style !== "object") {
@@ -8580,5 +8665,5 @@ export {
8580
8665
  startCanvasIframe
8581
8666
  };
8582
8667
 
8583
- //# debugId=39CA18389F1F06A664756E2164756E21
8668
+ //# debugId=BF2F5E4A39B13F1864756E2164756E21
8584
8669
  //# sourceMappingURL=iframe-entry.js.map
@@ -14,6 +14,13 @@
14
14
  "required": true,
15
15
  "why": "the canvas iframe document. Without it every canvas frame 404s at boot."
16
16
  },
17
+ {
18
+ "dir": false,
19
+ "kind": "asset",
20
+ "path": "favicon.ico",
21
+ "required": true,
22
+ "why": "the shell document's <link rel=\"icon\">. A Chromium --app window (the NixOS desktop install) has no native title-bar icon of its own and falls back to the page's favicon, so without this the window chrome shows a generic icon even though the taskbar/dock entry is already branded via the .desktop file."
23
+ },
17
24
  {
18
25
  "dir": false,
19
26
  "kind": "entry",