@jxsuite/studio 3.0.0 → 4.0.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 (173) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/Overlay.dev-723bv0df.js +23 -0
  3. package/dist/chunks/{cf-settings-zj2cj1ar.js → cf-settings-45fgyx8y.js} +6 -5
  4. package/dist/chunks/{components-z6cnkyy1.js → components-zmx10t62.js} +6 -5
  5. package/dist/chunks/content-source-t88vb2dr.js +49 -0
  6. package/dist/chunks/{convert-to-repeater-6vvx96n2.js → convert-to-repeater-dhw1nrz9.js} +27 -19
  7. package/dist/chunks/entry-commands-6z6bhxg0.js +46 -0
  8. package/dist/chunks/{extension-sections-kwzvpemr.js → extension-sections-3ydgjbdy.js} +32 -24
  9. package/dist/chunks/file-ops-rskmhxyq.js +48 -0
  10. package/dist/chunks/files-0cratsr0.js +92 -0
  11. package/dist/chunks/{format-host-8fr3545e.js → format-host-tgcmfs4p.js} +3 -3
  12. package/dist/chunks/fs-events-hrrg328g.js +21 -0
  13. package/dist/chunks/{git-panel-g01d93vc.js → git-panel-0yywyk76.js} +21 -16
  14. package/dist/chunks/{jx-validate-jj9rnt4n.js → jx-validate-8q2g05x1.js} +6 -4
  15. package/dist/chunks/layers-panel-z3tqe5cd.js +67 -0
  16. package/dist/chunks/layers-q75tj2mf.js +45 -0
  17. package/dist/chunks/lit-html-j055mkh8.js +22 -0
  18. package/dist/chunks/monaco-buffer-dqw0xxpx.js +25 -0
  19. package/dist/chunks/{monaco-setup-a5wkmbgh.js → monaco-setup-rws7k4br.js} +4 -4
  20. package/dist/chunks/notify-yjm79n4s.js +30 -0
  21. package/dist/chunks/parse-24d0gay3.js +19 -0
  22. package/dist/chunks/platform-ba1j1gbh.js +16 -0
  23. package/dist/chunks/publish-panel-54jvhskq.js +28 -0
  24. package/dist/chunks/quick-search-cgfmjwq5.js +65 -0
  25. package/dist/chunks/references-3qx8fkyp.js +29 -0
  26. package/dist/chunks/right-panel-cqp8bc4v.js +46 -0
  27. package/dist/chunks/sp-overlay.dev-yztmtrs1.js +18 -0
  28. package/dist/chunks/sp-popover.dev-n2etmqdp.js +9 -0
  29. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +15 -0
  30. package/dist/chunks/sp-tooltip.dev-xcvpnqr0.js +15 -0
  31. package/dist/chunks/{sp-tray.dev-64v4pxw8.js → sp-tray.dev-tkbscm06.js} +5 -5
  32. package/dist/chunks/{studio-8ezdegcx.js → studio-1hbqnt19.js} +36 -32
  33. package/dist/chunks/{studio-r5xbtctf.js → studio-2zkz8evn.js} +446 -2451
  34. package/dist/chunks/{studio-pkp61mh8.js → studio-4pqqxbrt.js} +23 -15
  35. package/dist/chunks/{studio-kvfx9z2c.js → studio-4rzyrtjz.js} +70 -31
  36. package/dist/chunks/{studio-3dkcd4c5.js → studio-5q69gfag.js} +60 -56
  37. package/dist/chunks/{studio-rh1cnamv.js → studio-5rywrkxz.js} +563 -133
  38. package/dist/chunks/{studio-6kv3apa9.js → studio-68n67094.js} +25 -9
  39. package/dist/chunks/{studio-0rqqhrdy.js → studio-7nte2hj4.js} +2 -2
  40. package/dist/chunks/{studio-xntfdy1x.js → studio-8swrjbny.js} +31 -18
  41. package/dist/chunks/studio-92ab2jqe.js +282 -0
  42. package/dist/chunks/{studio-sas7mt3k.js → studio-9ab8gqsm.js} +2 -2
  43. package/dist/chunks/{studio-ry1vz5sv.js → studio-9c4k4vhv.js} +15 -13
  44. package/dist/chunks/studio-9n4mrmnb.js +184 -0
  45. package/dist/chunks/{studio-tr20m8g8.js → studio-9r6j5ev1.js} +37 -2
  46. package/dist/chunks/{studio-2x9zbxmx.js → studio-ahjfdy6e.js} +9 -7
  47. package/dist/chunks/{studio-s519zc99.js → studio-bgxt93ga.js} +3 -3
  48. package/dist/chunks/{studio-dc8s8heb.js → studio-cb12yz9w.js} +8528 -8780
  49. package/dist/chunks/studio-cft9r4r7.js +119 -0
  50. package/dist/chunks/{studio-hcxzyk3x.js → studio-eenfkt4e.js} +6 -6
  51. package/dist/chunks/studio-eesa1myv.js +498 -0
  52. package/dist/chunks/{studio-ay8wcr2b.js → studio-eqq1w638.js} +7 -9
  53. package/dist/chunks/{studio-7p35254k.js → studio-ex8zyp98.js} +30 -26
  54. package/dist/chunks/studio-gv8vvshc.js +118 -0
  55. package/dist/chunks/studio-hbtp0eh1.js +1315 -0
  56. package/dist/chunks/{studio-a0yp7syn.js → studio-htsf0w6m.js} +29 -114
  57. package/dist/chunks/{studio-j595e748.js → studio-kjjsjak4.js} +139 -63
  58. package/dist/chunks/{studio-5x5774ak.js → studio-kryvsw6j.js} +3 -3
  59. package/dist/chunks/{studio-kfpek536.js → studio-kyh9avvv.js} +2 -2
  60. package/dist/chunks/{studio-g5gdqnyd.js → studio-kyk2v92a.js} +14 -14
  61. package/dist/chunks/{studio-twsafr1e.js → studio-m3hwn7y1.js} +3 -3
  62. package/dist/chunks/{studio-tzx3xmvx.js → studio-mmv72a27.js} +8 -8
  63. package/dist/chunks/{studio-vhk5fmfv.js → studio-n8b9wqwy.js} +5 -5
  64. package/dist/chunks/{studio-cjm7fdjf.js → studio-p4ngc046.js} +8 -104
  65. package/dist/chunks/{studio-p5dja96s.js → studio-p8j86wag.js} +2 -2
  66. package/dist/chunks/{studio-6z5eyjwn.js → studio-pdfjntbk.js} +66 -129
  67. package/dist/chunks/studio-q43a5y9h.js +394 -0
  68. package/dist/chunks/studio-q7v10cg2.js +106 -0
  69. package/dist/chunks/{studio-2w11grav.js → studio-qq6jym04.js} +3 -3
  70. package/dist/chunks/studio-r1r7afxx.js +1066 -0
  71. package/dist/chunks/{studio-3fk1ac9z.js → studio-rdx8jcxy.js} +4 -4
  72. package/dist/chunks/{studio-4mqb9a0j.js → studio-rn9ta2mz.js} +4 -4
  73. package/dist/chunks/studio-sf7zjgv1.js +91 -0
  74. package/dist/chunks/studio-t7qb9db8.js +665 -0
  75. package/dist/chunks/studio-tmc5emrw.js +8 -0
  76. package/dist/chunks/{studio-wdt9y92a.js → studio-txwkm6p9.js} +2 -2
  77. package/dist/chunks/{studio-k4jvjcfx.js → studio-v38hmvx1.js} +7 -7
  78. package/dist/chunks/{studio-7ejemhej.js → studio-vadzgkrz.js} +6 -6
  79. package/dist/chunks/studio-wcy8trfx.js +263 -0
  80. package/dist/chunks/{studio-5efrtn1m.js → studio-wx5609xd.js} +21 -17
  81. package/dist/chunks/{studio-qpfq7xhm.js → studio-xrapxwwc.js} +22 -285
  82. package/dist/chunks/{studio-hj2se583.js → studio-yxrkyv8a.js} +41 -31
  83. package/dist/chunks/{studio-xm3dbxvn.js → studio-zczps70q.js} +2 -2
  84. package/dist/chunks/workspace-xpres40v.js +89 -0
  85. package/dist/iframe-entry.js +108 -24
  86. package/dist/studio.js +2362 -1695
  87. package/package.json +16 -15
  88. package/src/browse/library-pane.ts +57 -3
  89. package/src/canvas/canvas-render.ts +23 -1
  90. package/src/canvas/iframe-patch.ts +47 -21
  91. package/src/canvas/iframe-render.ts +22 -6
  92. package/src/commands/app-commands.ts +4 -0
  93. package/src/commands/command-args.ts +29 -0
  94. package/src/commands/context.ts +15 -1
  95. package/src/commands/defaults.ts +29 -1
  96. package/src/commands/levels.ts +16 -0
  97. package/src/commands/live-context.ts +3 -0
  98. package/src/content/collection-match.ts +267 -0
  99. package/src/content/entry-commands.ts +38 -29
  100. package/src/content/entry-fields.ts +6 -0
  101. package/src/editor/shortcuts.ts +5 -0
  102. package/src/files/file-ops.ts +10 -42
  103. package/src/files/files.ts +485 -59
  104. package/src/files/fs-events.ts +9 -0
  105. package/src/files/gitignore.ts +432 -0
  106. package/src/files/serialize-document.ts +60 -0
  107. package/src/format/convert-file.ts +511 -0
  108. package/src/format/format-choices.ts +199 -0
  109. package/src/grid/grid-view.ts +16 -2
  110. package/src/media/media-open.ts +58 -0
  111. package/src/media/media-pane.ts +310 -0
  112. package/src/new-project/import-tab.ts +332 -160
  113. package/src/new-project/new-project-modal.ts +27 -34
  114. package/src/packages/ensure-deps.ts +14 -7
  115. package/src/packages/jxsuite-update.ts +11 -11
  116. package/src/page-params.ts +10 -46
  117. package/src/panels/activity-bar.ts +45 -16
  118. package/src/panels/ai-chat/attached-context.ts +6 -1
  119. package/src/panels/ai-chat/chat-view.ts +255 -13
  120. package/src/panels/ai-chat/composer.ts +21 -97
  121. package/src/panels/ai-panel.ts +116 -2
  122. package/src/panels/navigator-panels.ts +7 -6
  123. package/src/panels/settings-menu.ts +799 -0
  124. package/src/panels/toolbar.ts +135 -15
  125. package/src/platforms/cloud.ts +20 -0
  126. package/src/platforms/devserver.ts +67 -33
  127. package/src/preview/preview-overlay.ts +226 -0
  128. package/src/services/ai-ask.ts +247 -0
  129. package/src/services/ai-import-tools.ts +494 -0
  130. package/src/services/ai-project-tools.ts +20 -26
  131. package/src/services/ai-system-prompt.ts +88 -2
  132. package/src/services/ai-turn-signal.ts +70 -0
  133. package/src/services/connection.ts +74 -0
  134. package/src/services/context-manager.ts +89 -0
  135. package/src/services/document-assistant.ts +45 -4
  136. package/src/services/import-client.ts +33 -6
  137. package/src/services/import-run.ts +158 -0
  138. package/src/services/import-seed.ts +120 -0
  139. package/src/services/jx-validate.ts +58 -6
  140. package/src/services/project-adoption.ts +71 -0
  141. package/src/services/references.ts +0 -0
  142. package/src/services/settings/definitions.ts +17 -0
  143. package/src/services/tool-executor.ts +34 -2
  144. package/src/settings/contexts-section.ts +45 -3
  145. package/src/settings/dependencies-editor.ts +43 -23
  146. package/src/settings/general-settings.ts +30 -12
  147. package/src/settings/preferences-dialog.ts +18 -41
  148. package/src/settings/preferences-sections.ts +57 -0
  149. package/src/settings/settings-document.ts +65 -9
  150. package/src/studio.ts +33 -6
  151. package/src/tabs/transact.ts +42 -19
  152. package/src/types.ts +103 -5
  153. package/src/ui/ai-model-picker.ts +162 -0
  154. package/src/ui/choice-field.ts +72 -0
  155. package/src/ui/layers.ts +83 -5
  156. package/src/utils/studio-utils.ts +22 -52
  157. package/styles/forced-colors.css +7 -0
  158. package/styles/overlays.css +256 -0
  159. package/styles/panels.css +13 -1
  160. package/styles/shell.css +111 -0
  161. package/dist/chunks/Overlay.dev-d2ajy6sj.js +0 -23
  162. package/dist/chunks/content-source-7fy9qrm0.js +0 -40
  163. package/dist/chunks/files-xcybanxe.js +0 -70
  164. package/dist/chunks/layers-panel-27essgkc.js +0 -60
  165. package/dist/chunks/publish-panel-09sy2bab.js +0 -22
  166. package/dist/chunks/quick-search-sefb61v8.js +0 -55
  167. package/dist/chunks/right-panel-9r32jd5j.js +0 -39
  168. package/dist/chunks/sp-overlay.dev-s18hymn9.js +0 -18
  169. package/dist/chunks/sp-popover.dev-dj9x7e7a.js +0 -9
  170. package/dist/chunks/sp-progress-circle.dev-0zxcyz3r.js +0 -15
  171. package/dist/chunks/sp-tooltip.dev-5c6d1kjz.js +0 -15
  172. package/dist/chunks/studio-c31yb4t6.js +0 -55
  173. 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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Overlay
3
- } from "./studio-tzx3xmvx.js";
3
+ } from "./studio-mmv72a27.js";
4
4
  import {
5
5
  defineElement
6
6
  } from "./studio-18j3bmcz.js";
@@ -9,4 +9,4 @@ import {
9
9
  defineElement("sp-overlay", Overlay);
10
10
 
11
11
  //# debugId=24A9645EA10C33DD64756E2164756E21
12
- //# sourceMappingURL=studio-wdt9y92a.js.map
12
+ //# sourceMappingURL=studio-txwkm6p9.js.map