@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
@@ -0,0 +1,665 @@
1
+ import {
2
+ dismiss,
3
+ effect,
4
+ effectScope,
5
+ shallowRef,
6
+ toasts
7
+ } from "./studio-xrapxwwc.js";
8
+ import {
9
+ live,
10
+ ref,
11
+ repeat
12
+ } from "./studio-4rzyrtjz.js";
13
+ import {
14
+ html,
15
+ nothing,
16
+ render
17
+ } from "./studio-kryvsw6j.js";
18
+
19
+ // src/ui/choice-field.ts
20
+ function choiceField(spec) {
21
+ const current = spec.options.find((option) => option.value === spec.value);
22
+ if (spec.options.length < 2) {
23
+ return html`<div class="choice-row">
24
+ <sp-field-label size="s">${spec.label}</sp-field-label>
25
+ <span class="choice-static">${current?.label ?? spec.value}</span>
26
+ </div>`;
27
+ }
28
+ return html`<div class="choice-row">
29
+ <sp-field-label size="s">${spec.label}</sp-field-label>
30
+ <sp-picker
31
+ size="s"
32
+ label=${spec.label}
33
+ .value=${live(spec.value)}
34
+ @change=${(e) => spec.onChange(e.target.value)}
35
+ >
36
+ ${spec.options.map((option) => html`${option.dividerBefore === true ? html`<sp-menu-divider></sp-menu-divider>` : nothing}<sp-menu-item value=${option.value}>${option.label}</sp-menu-item>`)}
37
+ </sp-picker>
38
+ </div>`;
39
+ }
40
+
41
+ // src/ui/regions.ts
42
+ var REGION_ATTR = "data-jx-region";
43
+ var REGION_SURFACES = [
44
+ "rail",
45
+ "navigator",
46
+ "inspector",
47
+ "pane",
48
+ "dock.bottom",
49
+ "statusbar",
50
+ "commandbar",
51
+ "overlay"
52
+ ];
53
+ var DOTTED_SURFACES = new Set(["dock.bottom"]);
54
+ function parseRegionId(id) {
55
+ const slash = id.indexOf("/");
56
+ const head = slash === -1 ? id : id.slice(0, slash);
57
+ const part = slash === -1 ? undefined : id.slice(slash + 1);
58
+ if (part === "" || head === "") {
59
+ return null;
60
+ }
61
+ let surface = head;
62
+ let instance;
63
+ if (!DOTTED_SURFACES.has(head)) {
64
+ const dot = head.indexOf(".");
65
+ if (dot !== -1) {
66
+ surface = head.slice(0, dot);
67
+ instance = head.slice(dot + 1);
68
+ if (instance === "") {
69
+ return null;
70
+ }
71
+ }
72
+ }
73
+ if (!REGION_SURFACES.includes(surface)) {
74
+ return null;
75
+ }
76
+ return instance === undefined ? part === undefined ? { surface } : { part, surface } : part === undefined ? { instance, surface } : { instance, part, surface };
77
+ }
78
+ function isRegionId(id) {
79
+ return parseRegionId(id) !== null;
80
+ }
81
+ function canonicalRegionId(id) {
82
+ if (id === "pane") {
83
+ return "pane.primary";
84
+ }
85
+ return id.startsWith("pane/") ? `pane.primary/${id.slice(5)}` : id;
86
+ }
87
+ function regionRoot(root) {
88
+ return root ?? document;
89
+ }
90
+ var DERIVED_RESOLVERS = [
91
+ {
92
+ locate: ([, prop], root) => {
93
+ const row = resolveRegion(`inspector/field:${prop}`, root);
94
+ const browse = row?.querySelector(".media-picker-browse");
95
+ return browse ? [browse] : [];
96
+ },
97
+ pattern: /^inspector\/field:(.+)\/browse$/
98
+ },
99
+ {
100
+ locate: ([, prop], root) => {
101
+ const inspector = resolveRegion("inspector", root);
102
+ return inspector ? [...inspector.querySelectorAll(`[data-prop="${CSS.escape(prop)}"]`)] : [];
103
+ },
104
+ pattern: /^inspector\/field:(.+)$/
105
+ }
106
+ ];
107
+ function resolveAllRegions(id, root) {
108
+ const canonical = canonicalRegionId(id);
109
+ if (!isRegionId(canonical)) {
110
+ return [];
111
+ }
112
+ const stamped = [
113
+ ...regionRoot(root).querySelectorAll(`[${REGION_ATTR}="${CSS.escape(canonical)}"]`)
114
+ ];
115
+ if (stamped.length > 0) {
116
+ return stamped;
117
+ }
118
+ for (const resolver of DERIVED_RESOLVERS) {
119
+ const match = canonical.match(resolver.pattern);
120
+ if (match) {
121
+ return resolver.locate(match, regionRoot(root));
122
+ }
123
+ }
124
+ return [];
125
+ }
126
+ function resolveRegion(id, root) {
127
+ const all = resolveAllRegions(id, root);
128
+ return all.at(-1) ?? null;
129
+ }
130
+ var REGION_FOR_FOCUS = {
131
+ dock: "dock.bottom",
132
+ inspector: "inspector",
133
+ navigator: "navigator",
134
+ pane: "pane.primary",
135
+ rail: "rail",
136
+ status: "statusbar"
137
+ };
138
+ function paneRegion(paneId, part) {
139
+ return part ? `pane.${paneId}/${part}` : `pane.${paneId}`;
140
+ }
141
+ function paneStripRegion(paneId) {
142
+ return paneRegion(paneId, "tabs");
143
+ }
144
+ function navigatorPanelRegion(panelId) {
145
+ return `navigator/panel:${panelId}`;
146
+ }
147
+ function inspectorTabRegion(tabId) {
148
+ return `inspector/tab:${tabId}`;
149
+ }
150
+ var NAVIGATOR_STATEMENTS_REGION = "navigator/statements";
151
+ function inspectorStatementsRegion(eventKey) {
152
+ return `inspector/statements:${eventKey}`;
153
+ }
154
+ function bottomPanelRegion(panelId) {
155
+ return `dock.bottom/panel:${panelId}`;
156
+ }
157
+ var OVERLAY_INSTANCE = {
158
+ dialog: "dialog",
159
+ modal: "dialog",
160
+ popover: "menu",
161
+ toast: "toasts"
162
+ };
163
+ function overlayRegion(layer, id) {
164
+ const instance = OVERLAY_INSTANCE[layer];
165
+ return id ? `overlay.${instance}:${id}` : `overlay.${instance}`;
166
+ }
167
+
168
+ // src/commands/active-registry.ts
169
+ var _registry = shallowRef(null);
170
+ function setActiveRegistry(registry) {
171
+ _registry.value = registry;
172
+ }
173
+ function activeRegistry() {
174
+ return _registry.value;
175
+ }
176
+
177
+ // src/ui/layers.ts
178
+ var _popoverLayer;
179
+ var _modalLayer;
180
+ var _dialogLayer;
181
+ var _toastLayer;
182
+ function layerHost(kind) {
183
+ const host = kind === "popover" ? _popoverLayer : kind === "modal" ? _modalLayer : kind === "toast" ? _toastLayer : _dialogLayer;
184
+ return host || document.body;
185
+ }
186
+ function initLayers() {
187
+ _popoverLayer = document.querySelector("#layer-popover");
188
+ _modalLayer = document.querySelector("#layer-modal");
189
+ _dialogLayer = document.querySelector("#layer-dialog");
190
+ _toastLayer = document.querySelector("#layer-toast");
191
+ mountToastHost();
192
+ }
193
+ var UNDERLAID = "sp-dialog-wrapper[open], sp-underlay[open]";
194
+ function isModalOpen() {
195
+ return Boolean(_dialogLayer?.querySelector(UNDERLAID) || _modalLayer?.querySelector(UNDERLAID));
196
+ }
197
+ var BODY_FOCUSABLE = 'a[href], input, textarea, select, button, sp-textfield, sp-button, sp-action-button, sp-picker, sp-checkbox, sp-menu-item, [tabindex]:not([tabindex="-1"])';
198
+ function focusablesIn(slot) {
199
+ return [...slot.querySelectorAll(BODY_FOCUSABLE)].filter((el) => !el.hasAttribute("disabled") && el.getAttribute("aria-hidden") !== "true");
200
+ }
201
+ function focusOverlay(slot) {
202
+ requestAnimationFrame(() => {
203
+ if (!slot.isConnected || slot.contains(document.activeElement)) {
204
+ return;
205
+ }
206
+ const wrapper = slot.querySelector("sp-dialog-wrapper");
207
+ const target = focusablesIn(slot)[0] ?? wrapper?.shadowRoot?.querySelector("sp-button") ?? slot;
208
+ target.focus();
209
+ });
210
+ }
211
+ function trapTab(slot, e) {
212
+ e.preventDefault();
213
+ const items = focusablesIn(slot);
214
+ if (items.length === 0) {
215
+ return;
216
+ }
217
+ const at = items.indexOf(document.activeElement);
218
+ const next = e.shiftKey ? items[at <= 0 ? items.length - 1 : at - 1] : items[at === -1 || at === items.length - 1 ? 0 : at + 1];
219
+ next?.focus();
220
+ }
221
+ function openOverlaySlot(opts) {
222
+ const slot = document.createElement("div");
223
+ slot.style.pointerEvents = "auto";
224
+ slot.setAttribute(REGION_ATTR, overlayRegion(opts.kind, opts.regionId));
225
+ slot.tabIndex = -1;
226
+ slot.style.outline = "none";
227
+ opts.layer.append(slot);
228
+ const restoreTo = document.activeElement instanceof HTMLElement ? document.activeElement : null;
229
+ const onKeydown = (e) => {
230
+ if (e.key === "Escape") {
231
+ opts.onEscape?.(e, slot);
232
+ return;
233
+ }
234
+ if (e.key === "Tab" && opts.trapFocus) {
235
+ trapTab(slot, e);
236
+ }
237
+ };
238
+ slot.addEventListener("keydown", onKeydown);
239
+ return {
240
+ release() {
241
+ slot.removeEventListener("keydown", onKeydown);
242
+ render(nothing, slot);
243
+ slot.remove();
244
+ if (restoreTo?.isConnected) {
245
+ restoreTo.focus();
246
+ }
247
+ },
248
+ slot
249
+ };
250
+ }
251
+ function showDialog(templateFn, opts = {}) {
252
+ return new Promise((resolve) => {
253
+ const { release, slot } = openOverlaySlot({
254
+ kind: "dialog",
255
+ layer: layerHost("dialog"),
256
+ regionId: opts.region,
257
+ onEscape(e, host) {
258
+ const wrapper = host.querySelector("sp-dialog-wrapper");
259
+ if (!wrapper) {
260
+ return;
261
+ }
262
+ e.preventDefault();
263
+ e.stopPropagation();
264
+ wrapper.dispatchEvent(new Event("close", { bubbles: true }));
265
+ }
266
+ });
267
+ slot.setAttribute("role", "dialog");
268
+ slot.setAttribute("aria-modal", "true");
269
+ let resolved = false;
270
+ const done = (value) => {
271
+ if (resolved) {
272
+ return;
273
+ }
274
+ resolved = true;
275
+ release();
276
+ resolve(value);
277
+ };
278
+ render(templateFn(done), slot);
279
+ const headline = opts.label ?? slot.querySelector("sp-dialog-wrapper")?.getAttribute("headline") ?? null;
280
+ if (headline !== null && headline !== "") {
281
+ slot.setAttribute("aria-label", headline);
282
+ }
283
+ focusOverlay(slot);
284
+ });
285
+ }
286
+ function showConfirmDialog(headline, message, opts = {}) {
287
+ const { confirmLabel = "Confirm", cancelLabel = "Cancel", destructive = false } = opts;
288
+ return showDialog((done) => html`
289
+ <sp-dialog-wrapper
290
+ open
291
+ underlay
292
+ headline=${headline}
293
+ confirm-label=${confirmLabel}
294
+ cancel-label=${cancelLabel}
295
+ size="s"
296
+ @confirm=${() => done(true)}
297
+ @cancel=${() => done(false)}
298
+ @close=${() => done(false)}
299
+ class=${destructive ? "dialog-destructive" : ""}
300
+ >
301
+ <p>${message}</p>
302
+ </sp-dialog-wrapper>
303
+ `);
304
+ }
305
+ function showSaveDiscardDialog(headline, message, opts = {}) {
306
+ const { saveLabel = "Save", discardLabel = "Discard", cancelLabel = "Cancel" } = opts;
307
+ return showDialog((done) => html`
308
+ <sp-dialog-wrapper
309
+ open
310
+ underlay
311
+ headline=${headline}
312
+ confirm-label=${saveLabel}
313
+ secondary-label=${discardLabel}
314
+ cancel-label=${cancelLabel}
315
+ size="s"
316
+ @confirm=${() => done("save")}
317
+ @secondary=${() => done("discard")}
318
+ @cancel=${() => done("cancel")}
319
+ @close=${() => done("cancel")}
320
+ >
321
+ <p>${message}</p>
322
+ </sp-dialog-wrapper>
323
+ `);
324
+ }
325
+ function showPromptDialog(headline, opts = {}) {
326
+ const {
327
+ cancelLabel = "Cancel",
328
+ choice,
329
+ confirmLabel = "OK",
330
+ message,
331
+ placeholder = "",
332
+ select = "all",
333
+ validate,
334
+ value: initialValue = ""
335
+ } = opts;
336
+ const check = (candidate) => validate ? validate(candidate, chosen) : candidate.trim() ? "" : "Enter a value.";
337
+ let value = initialValue;
338
+ let chosen = choice?.initial ?? "";
339
+ let error = "";
340
+ let wrapperEl = null;
341
+ let focusRequested = false;
342
+ let touched = false;
343
+ return showDialog((done) => {
344
+ function rerender() {
345
+ const host = wrapperEl?.parentElement;
346
+ if (host) {
347
+ render(buildTpl(), host);
348
+ }
349
+ }
350
+ function confirm() {
351
+ error = check(value);
352
+ if (error) {
353
+ rerender();
354
+ return;
355
+ }
356
+ done(value.trim());
357
+ }
358
+ function onInput(e) {
359
+ touched = true;
360
+ value = e.target.value || "";
361
+ const next = check(value);
362
+ if (next !== error) {
363
+ error = next;
364
+ rerender();
365
+ }
366
+ }
367
+ function onPick(next) {
368
+ chosen = next;
369
+ choice?.onChange?.(next);
370
+ const candidate = check(value);
371
+ error = touched || error ? candidate : "";
372
+ rerender();
373
+ }
374
+ function onKeydown(e) {
375
+ if (e.key === "Enter") {
376
+ confirm();
377
+ }
378
+ }
379
+ function onWrapperRef(el) {
380
+ if (el) {
381
+ wrapperEl = el;
382
+ }
383
+ }
384
+ function onFieldRef(el) {
385
+ if (!el || focusRequested) {
386
+ return;
387
+ }
388
+ focusRequested = true;
389
+ const field = el;
390
+ requestAnimationFrame(() => {
391
+ field.focus();
392
+ const input = field.shadowRoot?.querySelector("input");
393
+ if (!input || select === "none") {
394
+ return;
395
+ }
396
+ if (select === "stem") {
397
+ const dot = input.value.lastIndexOf(".");
398
+ input.setSelectionRange(0, dot > 0 ? dot : input.value.length);
399
+ return;
400
+ }
401
+ input.select();
402
+ });
403
+ }
404
+ function buildTpl() {
405
+ return html`
406
+ <sp-dialog-wrapper
407
+ open
408
+ underlay
409
+ headline=${headline}
410
+ confirm-label=${confirmLabel}
411
+ cancel-label=${cancelLabel}
412
+ size="s"
413
+ @confirm=${confirm}
414
+ @cancel=${() => done(null)}
415
+ @close=${() => done(null)}
416
+ ${ref(onWrapperRef)}
417
+ >
418
+ ${message ? html`<p style="margin:0 0 8px">${message}</p>` : nothing}
419
+ ${choice ? choiceField({
420
+ label: choice.label,
421
+ onChange: onPick,
422
+ options: choice.options(),
423
+ value: chosen
424
+ }) : nothing}
425
+ <sp-textfield
426
+ style="width:100%"
427
+ placeholder=${typeof placeholder === "function" ? placeholder() : placeholder}
428
+ value=${value}
429
+ ?invalid=${Boolean(error)}
430
+ @input=${onInput}
431
+ @keydown=${onKeydown}
432
+ ${ref(onFieldRef)}
433
+ >
434
+ ${error ? html`<sp-help-text slot="negative-help-text">${error}</sp-help-text>` : nothing}
435
+ </sp-textfield>
436
+ </sp-dialog-wrapper>
437
+ `;
438
+ }
439
+ return buildTpl();
440
+ });
441
+ }
442
+ function openModal(template, opts) {
443
+ const { release, slot } = openOverlaySlot({
444
+ kind: "modal",
445
+ layer: layerHost("modal"),
446
+ onEscape(e) {
447
+ if (opts.dismissible === false) {
448
+ return;
449
+ }
450
+ e.preventDefault();
451
+ e.stopPropagation();
452
+ (opts.onDismiss ?? handle.close)();
453
+ },
454
+ regionId: opts.region,
455
+ trapFocus: true
456
+ });
457
+ slot.setAttribute("role", "dialog");
458
+ slot.setAttribute("aria-modal", "true");
459
+ slot.setAttribute("aria-label", opts.label);
460
+ const handle = {
461
+ close() {
462
+ release();
463
+ },
464
+ host: slot,
465
+ update(tpl) {
466
+ render(tpl, slot);
467
+ }
468
+ };
469
+ render(template, slot);
470
+ focusOverlay(slot);
471
+ return handle;
472
+ }
473
+ function renderPopover(template, opts = {}) {
474
+ const kind = opts.layer ?? "popover";
475
+ const slot = document.createElement("div");
476
+ slot.style.pointerEvents = "auto";
477
+ slot.setAttribute(REGION_ATTR, overlayRegion(kind, opts.region));
478
+ layerHost(kind).append(slot);
479
+ render(template, slot);
480
+ let outsideClickHandler = null;
481
+ if (opts.dismissOnOutsideClick !== false) {
482
+ outsideClickHandler = (e) => {
483
+ if (!slot.contains(e.target)) {
484
+ handle.dismiss();
485
+ opts.onDismiss?.();
486
+ }
487
+ };
488
+ requestAnimationFrame(() => {
489
+ if (outsideClickHandler) {
490
+ document.addEventListener("mousedown", outsideClickHandler, true);
491
+ }
492
+ });
493
+ }
494
+ const handle = {
495
+ dismiss() {
496
+ if (outsideClickHandler) {
497
+ document.removeEventListener("mousedown", outsideClickHandler, true);
498
+ outsideClickHandler = null;
499
+ }
500
+ render(nothing, slot);
501
+ slot.remove();
502
+ },
503
+ host: slot,
504
+ update(tpl) {
505
+ render(tpl, slot);
506
+ }
507
+ };
508
+ return handle;
509
+ }
510
+ var _namedSlots = new Map;
511
+ function popoverLayerFor(anchor) {
512
+ if (anchor?.closest("#layer-dialog")) {
513
+ return "dialog";
514
+ }
515
+ return anchor?.closest("#layer-modal") ? "modal" : "popover";
516
+ }
517
+ function getLayerSlot(layer, id) {
518
+ const key = `${layer}:${id}`;
519
+ let slot = _namedSlots.get(key);
520
+ if (slot && slot.parentElement) {
521
+ return slot;
522
+ }
523
+ slot = document.createElement("div");
524
+ slot.style.pointerEvents = "auto";
525
+ slot.setAttribute(REGION_ATTR, overlayRegion(layer, id));
526
+ layerHost(layer).append(slot);
527
+ _namedSlots.set(key, slot);
528
+ return slot;
529
+ }
530
+ function clearLayerSlot(layer, id) {
531
+ const key = `${layer}:${id}`;
532
+ const slot = _namedSlots.get(key);
533
+ if (slot) {
534
+ render(nothing, slot);
535
+ slot.remove();
536
+ _namedSlots.delete(key);
537
+ }
538
+ }
539
+ var TOAST_ENTER_MS = 180;
540
+ var TOAST_ICON = {
541
+ error: "✕",
542
+ info: "ℹ",
543
+ success: "✓",
544
+ warn: "!"
545
+ };
546
+ var _toastScope = null;
547
+ var _toastTimers = new Map;
548
+ var _toastEntering = new Set;
549
+ function reducedMotion() {
550
+ return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
551
+ }
552
+ function toastsAreHeld() {
553
+ try {
554
+ return new URLSearchParams(globalThis.location?.search ?? "").get("automation") === "1";
555
+ } catch {
556
+ return false;
557
+ }
558
+ }
559
+ function overlayIdleBlockers() {
560
+ return [..._toastEntering].map((id) => `overlay: toast ${id} settling in`);
561
+ }
562
+ function retireToast(id) {
563
+ const timer = _toastTimers.get(id);
564
+ if (timer !== undefined) {
565
+ clearTimeout(timer);
566
+ _toastTimers.delete(id);
567
+ }
568
+ _toastEntering.delete(id);
569
+ dismiss(id);
570
+ }
571
+ function scheduleToast(record) {
572
+ if (_toastTimers.has(record.id) || _toastEntering.has(record.id)) {
573
+ return;
574
+ }
575
+ const settle = reducedMotion() ? 0 : TOAST_ENTER_MS;
576
+ if (settle > 0) {
577
+ _toastEntering.add(record.id);
578
+ setTimeout(() => _toastEntering.delete(record.id), settle);
579
+ }
580
+ const rest = record.timeoutMs ?? 0;
581
+ if (rest <= 0 || toastsAreHeld()) {
582
+ return;
583
+ }
584
+ _toastTimers.set(record.id, setTimeout(() => retireToast(record.id), rest));
585
+ }
586
+ function toastActionTpl(record) {
587
+ const registry = record.action === undefined ? null : activeRegistry();
588
+ const id = record.action;
589
+ if (!registry || id === undefined || !registry.get(id) || !registry.isVisible(id)) {
590
+ return nothing;
591
+ }
592
+ const command = registry.get(id);
593
+ const reason = registry.disabledReason(id);
594
+ return html`
595
+ <button
596
+ class="toast-action"
597
+ ?disabled=${reason !== undefined}
598
+ title=${reason === undefined ? command.title : `${command.title} — requires ${reason}`}
599
+ @click=${() => {
600
+ retireToast(record.id);
601
+ registry.run(id, record.actionArgs);
602
+ }}
603
+ >
604
+ ${command.title}
605
+ </button>
606
+ `;
607
+ }
608
+ function toastTpl(record) {
609
+ return html`
610
+ <div class="toast toast--${record.severity}">
611
+ <span class="toast-icon" aria-hidden="true">${TOAST_ICON[record.severity]}</span>
612
+ <span class="toast-message">${record.message}</span>
613
+ ${toastActionTpl(record)}
614
+ <button
615
+ class="toast-dismiss"
616
+ title="Dismiss"
617
+ aria-label="Dismiss notification"
618
+ @click=${() => retireToast(record.id)}
619
+ >
620
+ <span aria-hidden="true">×</span>
621
+ </button>
622
+ </div>
623
+ `;
624
+ }
625
+ function toastStackTemplate() {
626
+ return html`
627
+ <div class="toast-stack">
628
+ ${repeat(toasts, (record) => record.id, (record) => toastTpl(record))}
629
+ </div>
630
+ `;
631
+ }
632
+ function mountToastHost() {
633
+ unmountToastHost();
634
+ if (!_toastLayer) {
635
+ return;
636
+ }
637
+ _toastScope = effectScope();
638
+ _toastScope.run(() => {
639
+ effect(() => {
640
+ toasts.length;
641
+ activeRegistry();
642
+ for (const record of toasts) {
643
+ scheduleToast(record);
644
+ }
645
+ render(toastStackTemplate(), _toastLayer);
646
+ });
647
+ });
648
+ }
649
+ function unmountToastHost() {
650
+ _toastScope?.stop();
651
+ _toastScope = null;
652
+ for (const timer of _toastTimers.values()) {
653
+ clearTimeout(timer);
654
+ }
655
+ _toastTimers.clear();
656
+ _toastEntering.clear();
657
+ if (_toastLayer) {
658
+ render(nothing, _toastLayer);
659
+ }
660
+ }
661
+
662
+ export { REGION_ATTR, resolveRegion, REGION_FOR_FOCUS, paneRegion, paneStripRegion, navigatorPanelRegion, inspectorTabRegion, NAVIGATOR_STATEMENTS_REGION, inspectorStatementsRegion, bottomPanelRegion, overlayRegion, setActiveRegistry, activeRegistry, initLayers, isModalOpen, showDialog, showConfirmDialog, showSaveDiscardDialog, showPromptDialog, openModal, renderPopover, popoverLayerFor, getLayerSlot, clearLayerSlot, TOAST_ENTER_MS, toastsAreHeld, overlayIdleBlockers, toastStackTemplate, mountToastHost, unmountToastHost };
663
+
664
+ //# debugId=8A616F848280CD3764756E2164756E21
665
+ //# sourceMappingURL=studio-t7qb9db8.js.map
@@ -0,0 +1,8 @@
1
+ // ../../node_modules/lit-html/development/directives/when.js
2
+ function when(condition, trueCase, falseCase) {
3
+ return condition ? trueCase(condition) : falseCase?.(condition);
4
+ }
5
+ export { when };
6
+
7
+ //# debugId=BA8B685BA2BBF07D64756E2164756E21
8
+ //# sourceMappingURL=studio-tmc5emrw.js.map