@juo/blocks 1.11.0-alpha.0 → 1.12.0-alpha.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.
@@ -0,0 +1,1667 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { reportBlockError, reportBlockWarning } from "./observability.js";
5
+ import { a as createEditorBridge, e as createSelectBlockMessage } from "./bridge-w5KQ-czl.js";
6
+ const createContext = (key) => key;
7
+ class ContextRequestEvent extends Event {
8
+ constructor(context, callback, subscribe) {
9
+ super("context-request", { bubbles: true, composed: true });
10
+ this.context = context;
11
+ this.callback = callback;
12
+ this.subscribe = subscribe;
13
+ }
14
+ }
15
+ class ContextProvideEvent extends Event {
16
+ constructor(context, value, subscribe) {
17
+ super("context-provide", { bubbles: true, composed: true });
18
+ this.context = context;
19
+ this.value = value;
20
+ this.subscribe = subscribe;
21
+ }
22
+ }
23
+ function provideContext(target, context, init) {
24
+ console.log("context:provide", context, target);
25
+ const ev = new ContextProvideEvent(context, init);
26
+ target.dispatchEvent(ev);
27
+ }
28
+ function injectContext(target, context) {
29
+ let value = void 0;
30
+ console.log("context:inject", context, target);
31
+ const ev = new ContextRequestEvent(context, (received) => {
32
+ value = received;
33
+ });
34
+ target.dispatchEvent(ev);
35
+ if (value === void 0) {
36
+ throw new Error(`Context '${context}' not defined`);
37
+ }
38
+ return value;
39
+ }
40
+ function subscribeContext(target, context, callback) {
41
+ let unsubscribeFunction = null;
42
+ console.log("context:subscribe", context, target);
43
+ const protocolCallback = (value, unsubscribe) => {
44
+ if (unsubscribe) {
45
+ unsubscribeFunction = unsubscribe;
46
+ }
47
+ callback(value);
48
+ };
49
+ const ev = new ContextRequestEvent(context, protocolCallback, true);
50
+ target.dispatchEvent(ev);
51
+ return () => {
52
+ if (unsubscribeFunction) {
53
+ unsubscribeFunction();
54
+ }
55
+ };
56
+ }
57
+ class ContextRoot extends HTMLElement {
58
+ constructor() {
59
+ super(...arguments);
60
+ __publicField(this, "store", /* @__PURE__ */ new Map());
61
+ __publicField(this, "callbacks", /* @__PURE__ */ new Map());
62
+ }
63
+ connectedCallback() {
64
+ this.addEventListener("context-provide", (ev) => {
65
+ ev.stopPropagation();
66
+ console.log("context-root:provide", ev.context, ev.value);
67
+ this.store.set(ev.context, ev.value);
68
+ const registeredCallbacks = this.callbacks.get(ev.context) ?? [];
69
+ console.log("callbacks", registeredCallbacks);
70
+ registeredCallbacks.forEach((cb) => {
71
+ const unsubscribe = () => {
72
+ const callbacks = this.callbacks.get(ev.context);
73
+ if (callbacks) {
74
+ const cbIndex = callbacks.indexOf(cb);
75
+ if (cbIndex > -1) {
76
+ callbacks.splice(cbIndex, 1);
77
+ }
78
+ }
79
+ console.log("context-root:unsubscribed", ev.context);
80
+ };
81
+ cb(ev.value, unsubscribe);
82
+ });
83
+ });
84
+ this.addEventListener("context-request", (ev) => {
85
+ ev.stopPropagation();
86
+ console.log("context-root:request", ev.context, ev);
87
+ const storedValue = this.store.get(ev.context);
88
+ if (ev.subscribe) {
89
+ let callbacks = this.callbacks.get(ev.context);
90
+ if (!callbacks) {
91
+ callbacks = [];
92
+ this.callbacks.set(ev.context, callbacks);
93
+ }
94
+ const unsubscribe = () => {
95
+ const currentCallbacks = this.callbacks.get(ev.context);
96
+ if (currentCallbacks) {
97
+ const index = currentCallbacks.indexOf(ev.callback);
98
+ if (index > -1) {
99
+ currentCallbacks.splice(index, 1);
100
+ }
101
+ }
102
+ console.log("context-root:unsubscribed", ev.context);
103
+ };
104
+ callbacks.push(ev.callback);
105
+ if (storedValue !== void 0) {
106
+ ev.callback(storedValue, unsubscribe);
107
+ }
108
+ } else {
109
+ if (storedValue !== void 0) {
110
+ ev.callback(storedValue);
111
+ } else {
112
+ console.warn("Context not present in store: " + String(ev.context));
113
+ }
114
+ }
115
+ });
116
+ console.log("context-root:ready");
117
+ }
118
+ }
119
+ var i = Symbol.for("preact-signals");
120
+ function t() {
121
+ if (!(s > 1)) {
122
+ var i2, t2 = false;
123
+ while (void 0 !== h) {
124
+ var r = h;
125
+ h = void 0;
126
+ f++;
127
+ while (void 0 !== r) {
128
+ var o2 = r.o;
129
+ r.o = void 0;
130
+ r.f &= -3;
131
+ if (!(8 & r.f) && c(r)) try {
132
+ r.c();
133
+ } catch (r2) {
134
+ if (!t2) {
135
+ i2 = r2;
136
+ t2 = true;
137
+ }
138
+ }
139
+ r = o2;
140
+ }
141
+ }
142
+ f = 0;
143
+ s--;
144
+ if (t2) throw i2;
145
+ } else s--;
146
+ }
147
+ var o = void 0;
148
+ function n(i2) {
149
+ var t2 = o;
150
+ o = void 0;
151
+ try {
152
+ return i2();
153
+ } finally {
154
+ o = t2;
155
+ }
156
+ }
157
+ var h = void 0, s = 0, f = 0, v = 0;
158
+ function e(i2) {
159
+ if (void 0 !== o) {
160
+ var t2 = i2.n;
161
+ if (void 0 === t2 || t2.t !== o) {
162
+ t2 = { i: 0, S: i2, p: o.s, n: void 0, t: o, e: void 0, x: void 0, r: t2 };
163
+ if (void 0 !== o.s) o.s.n = t2;
164
+ o.s = t2;
165
+ i2.n = t2;
166
+ if (32 & o.f) i2.S(t2);
167
+ return t2;
168
+ } else if (-1 === t2.i) {
169
+ t2.i = 0;
170
+ if (void 0 !== t2.n) {
171
+ t2.n.p = t2.p;
172
+ if (void 0 !== t2.p) t2.p.n = t2.n;
173
+ t2.p = o.s;
174
+ t2.n = void 0;
175
+ o.s.n = t2;
176
+ o.s = t2;
177
+ }
178
+ return t2;
179
+ }
180
+ }
181
+ }
182
+ function u(i2, t2) {
183
+ this.v = i2;
184
+ this.i = 0;
185
+ this.n = void 0;
186
+ this.t = void 0;
187
+ this.W = null == t2 ? void 0 : t2.watched;
188
+ this.Z = null == t2 ? void 0 : t2.unwatched;
189
+ }
190
+ u.prototype.brand = i;
191
+ u.prototype.h = function() {
192
+ return true;
193
+ };
194
+ u.prototype.S = function(i2) {
195
+ var t2 = this, r = this.t;
196
+ if (r !== i2 && void 0 === i2.e) {
197
+ i2.x = r;
198
+ this.t = i2;
199
+ if (void 0 !== r) r.e = i2;
200
+ else n(function() {
201
+ var i3;
202
+ null == (i3 = t2.W) || i3.call(t2);
203
+ });
204
+ }
205
+ };
206
+ u.prototype.U = function(i2) {
207
+ var t2 = this;
208
+ if (void 0 !== this.t) {
209
+ var r = i2.e, o2 = i2.x;
210
+ if (void 0 !== r) {
211
+ r.x = o2;
212
+ i2.e = void 0;
213
+ }
214
+ if (void 0 !== o2) {
215
+ o2.e = r;
216
+ i2.x = void 0;
217
+ }
218
+ if (i2 === this.t) {
219
+ this.t = o2;
220
+ if (void 0 === o2) n(function() {
221
+ var i3;
222
+ null == (i3 = t2.Z) || i3.call(t2);
223
+ });
224
+ }
225
+ }
226
+ };
227
+ u.prototype.subscribe = function(i2) {
228
+ var t2 = this;
229
+ return E(function() {
230
+ var r = t2.value, n2 = o;
231
+ o = void 0;
232
+ try {
233
+ i2(r);
234
+ } finally {
235
+ o = n2;
236
+ }
237
+ });
238
+ };
239
+ u.prototype.valueOf = function() {
240
+ return this.value;
241
+ };
242
+ u.prototype.toString = function() {
243
+ return this.value + "";
244
+ };
245
+ u.prototype.toJSON = function() {
246
+ return this.value;
247
+ };
248
+ u.prototype.peek = function() {
249
+ var i2 = o;
250
+ o = void 0;
251
+ try {
252
+ return this.value;
253
+ } finally {
254
+ o = i2;
255
+ }
256
+ };
257
+ Object.defineProperty(u.prototype, "value", { get: function() {
258
+ var i2 = e(this);
259
+ if (void 0 !== i2) i2.i = this.i;
260
+ return this.v;
261
+ }, set: function(i2) {
262
+ if (i2 !== this.v) {
263
+ if (f > 100) throw new Error("Cycle detected");
264
+ this.v = i2;
265
+ this.i++;
266
+ v++;
267
+ s++;
268
+ try {
269
+ for (var r = this.t; void 0 !== r; r = r.x) r.t.N();
270
+ } finally {
271
+ t();
272
+ }
273
+ }
274
+ } });
275
+ function d(i2, t2) {
276
+ return new u(i2, t2);
277
+ }
278
+ function c(i2) {
279
+ for (var t2 = i2.s; void 0 !== t2; t2 = t2.n) if (t2.S.i !== t2.i || !t2.S.h() || t2.S.i !== t2.i) return true;
280
+ return false;
281
+ }
282
+ function a(i2) {
283
+ for (var t2 = i2.s; void 0 !== t2; t2 = t2.n) {
284
+ var r = t2.S.n;
285
+ if (void 0 !== r) t2.r = r;
286
+ t2.S.n = t2;
287
+ t2.i = -1;
288
+ if (void 0 === t2.n) {
289
+ i2.s = t2;
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ function l(i2) {
295
+ var t2 = i2.s, r = void 0;
296
+ while (void 0 !== t2) {
297
+ var o2 = t2.p;
298
+ if (-1 === t2.i) {
299
+ t2.S.U(t2);
300
+ if (void 0 !== o2) o2.n = t2.n;
301
+ if (void 0 !== t2.n) t2.n.p = o2;
302
+ } else r = t2;
303
+ t2.S.n = t2.r;
304
+ if (void 0 !== t2.r) t2.r = void 0;
305
+ t2 = o2;
306
+ }
307
+ i2.s = r;
308
+ }
309
+ function y(i2, t2) {
310
+ u.call(this, void 0);
311
+ this.x = i2;
312
+ this.s = void 0;
313
+ this.g = v - 1;
314
+ this.f = 4;
315
+ this.W = null == t2 ? void 0 : t2.watched;
316
+ this.Z = null == t2 ? void 0 : t2.unwatched;
317
+ }
318
+ y.prototype = new u();
319
+ y.prototype.h = function() {
320
+ this.f &= -3;
321
+ if (1 & this.f) return false;
322
+ if (32 == (36 & this.f)) return true;
323
+ this.f &= -5;
324
+ if (this.g === v) return true;
325
+ this.g = v;
326
+ this.f |= 1;
327
+ if (this.i > 0 && !c(this)) {
328
+ this.f &= -2;
329
+ return true;
330
+ }
331
+ var i2 = o;
332
+ try {
333
+ a(this);
334
+ o = this;
335
+ var t2 = this.x();
336
+ if (16 & this.f || this.v !== t2 || 0 === this.i) {
337
+ this.v = t2;
338
+ this.f &= -17;
339
+ this.i++;
340
+ }
341
+ } catch (i3) {
342
+ this.v = i3;
343
+ this.f |= 16;
344
+ this.i++;
345
+ }
346
+ o = i2;
347
+ l(this);
348
+ this.f &= -2;
349
+ return true;
350
+ };
351
+ y.prototype.S = function(i2) {
352
+ if (void 0 === this.t) {
353
+ this.f |= 36;
354
+ for (var t2 = this.s; void 0 !== t2; t2 = t2.n) t2.S.S(t2);
355
+ }
356
+ u.prototype.S.call(this, i2);
357
+ };
358
+ y.prototype.U = function(i2) {
359
+ if (void 0 !== this.t) {
360
+ u.prototype.U.call(this, i2);
361
+ if (void 0 === this.t) {
362
+ this.f &= -33;
363
+ for (var t2 = this.s; void 0 !== t2; t2 = t2.n) t2.S.U(t2);
364
+ }
365
+ }
366
+ };
367
+ y.prototype.N = function() {
368
+ if (!(2 & this.f)) {
369
+ this.f |= 6;
370
+ for (var i2 = this.t; void 0 !== i2; i2 = i2.x) i2.t.N();
371
+ }
372
+ };
373
+ Object.defineProperty(y.prototype, "value", { get: function() {
374
+ if (1 & this.f) throw new Error("Cycle detected");
375
+ var i2 = e(this);
376
+ this.h();
377
+ if (void 0 !== i2) i2.i = this.i;
378
+ if (16 & this.f) throw this.v;
379
+ return this.v;
380
+ } });
381
+ function w(i2, t2) {
382
+ return new y(i2, t2);
383
+ }
384
+ function _(i2) {
385
+ var r = i2.u;
386
+ i2.u = void 0;
387
+ if ("function" == typeof r) {
388
+ s++;
389
+ var n2 = o;
390
+ o = void 0;
391
+ try {
392
+ r();
393
+ } catch (t2) {
394
+ i2.f &= -2;
395
+ i2.f |= 8;
396
+ b(i2);
397
+ throw t2;
398
+ } finally {
399
+ o = n2;
400
+ t();
401
+ }
402
+ }
403
+ }
404
+ function b(i2) {
405
+ for (var t2 = i2.s; void 0 !== t2; t2 = t2.n) t2.S.U(t2);
406
+ i2.x = void 0;
407
+ i2.s = void 0;
408
+ _(i2);
409
+ }
410
+ function g(i2) {
411
+ if (o !== this) throw new Error("Out-of-order effect");
412
+ l(this);
413
+ o = i2;
414
+ this.f &= -2;
415
+ if (8 & this.f) b(this);
416
+ t();
417
+ }
418
+ function p(i2) {
419
+ this.x = i2;
420
+ this.u = void 0;
421
+ this.s = void 0;
422
+ this.o = void 0;
423
+ this.f = 32;
424
+ }
425
+ p.prototype.c = function() {
426
+ var i2 = this.S();
427
+ try {
428
+ if (8 & this.f) return;
429
+ if (void 0 === this.x) return;
430
+ var t2 = this.x();
431
+ if ("function" == typeof t2) this.u = t2;
432
+ } finally {
433
+ i2();
434
+ }
435
+ };
436
+ p.prototype.S = function() {
437
+ if (1 & this.f) throw new Error("Cycle detected");
438
+ this.f |= 1;
439
+ this.f &= -9;
440
+ _(this);
441
+ a(this);
442
+ s++;
443
+ var i2 = o;
444
+ o = this;
445
+ return g.bind(this, i2);
446
+ };
447
+ p.prototype.N = function() {
448
+ if (!(2 & this.f)) {
449
+ this.f |= 2;
450
+ this.o = h;
451
+ h = this;
452
+ }
453
+ };
454
+ p.prototype.d = function() {
455
+ this.f |= 8;
456
+ if (!(1 & this.f)) b(this);
457
+ };
458
+ p.prototype.dispose = function() {
459
+ this.d();
460
+ };
461
+ function E(i2) {
462
+ var t2 = new p(i2);
463
+ try {
464
+ t2.c();
465
+ } catch (i3) {
466
+ t2.d();
467
+ throw i3;
468
+ }
469
+ var r = t2.d.bind(t2);
470
+ r[Symbol.dispose] = r;
471
+ return r;
472
+ }
473
+ function isEditorPreview() {
474
+ if (typeof window === "undefined") return false;
475
+ return new URLSearchParams(window.location.search).get("editor") === "true";
476
+ }
477
+ function hasRenderedContent(scope) {
478
+ var _a;
479
+ for (const child of scope.children) {
480
+ if (!(child instanceof HTMLElement)) {
481
+ continue;
482
+ }
483
+ const display = (_a = child.ownerDocument.defaultView) == null ? void 0 : _a.getComputedStyle(child).display;
484
+ if (display === "contents") {
485
+ if (hasRenderedContent(child)) {
486
+ return true;
487
+ }
488
+ continue;
489
+ }
490
+ if (child.checkVisibility()) {
491
+ return true;
492
+ }
493
+ }
494
+ return false;
495
+ }
496
+ function attachEmptyTracking(host, scope) {
497
+ let observer = null;
498
+ let disposed = false;
499
+ queueMicrotask(() => {
500
+ if (disposed) return;
501
+ const observed = scope ?? host.shadowRoot ?? host;
502
+ const sync = () => host.toggleAttribute("data-empty", !hasRenderedContent(observed));
503
+ observer = new MutationObserver(sync);
504
+ observer.observe(observed, { childList: true, subtree: true });
505
+ sync();
506
+ });
507
+ return () => {
508
+ disposed = true;
509
+ observer == null ? void 0 : observer.disconnect();
510
+ observer = null;
511
+ };
512
+ }
513
+ function serializeBlocks(blocks) {
514
+ return blocks.map((block) => serializeBlock(block));
515
+ }
516
+ function serializeBlock(block) {
517
+ return {
518
+ id: block.id,
519
+ type: block.type,
520
+ props: JSON.parse(JSON.stringify(block.props)),
521
+ slots: Object.fromEntries(
522
+ Object.entries(block.slots ?? {}).map(([key, value]) => [
523
+ key,
524
+ Array.isArray(value) ? value.map(
525
+ (v2) => typeof v2 === "string" ? v2 : serializeBlock(v2)
526
+ ) : typeof value === "string" ? value : serializeBlock(value)
527
+ ])
528
+ )
529
+ };
530
+ }
531
+ function createSelectedBlock() {
532
+ const selected = d(null);
533
+ function setSelection(block) {
534
+ selected.value = null;
535
+ selected.value = block;
536
+ }
537
+ function clearSelection(block) {
538
+ var _a;
539
+ if (block == null || ((_a = selected.value) == null ? void 0 : _a.id) === block.id) {
540
+ selected.value = null;
541
+ }
542
+ }
543
+ return { selected, setSelection, clearSelection };
544
+ }
545
+ const SelectedBlockContext = createContext("selectedBlock");
546
+ const blockDefinitions = (() => {
547
+ if (typeof window !== "undefined") {
548
+ window._juoBlocks = window._juoBlocks || /* @__PURE__ */ new Map();
549
+ return window._juoBlocks;
550
+ }
551
+ return /* @__PURE__ */ new Map();
552
+ })();
553
+ class BlockWrapperEvent extends Event {
554
+ constructor(block, callback) {
555
+ super("juo:block-wrapper-render", {
556
+ bubbles: true,
557
+ composed: true,
558
+ cancelable: true
559
+ });
560
+ this.block = block;
561
+ this.callback = callback;
562
+ }
563
+ }
564
+ function withWrapper(fn) {
565
+ let wrapper = null;
566
+ return (block) => {
567
+ var _a;
568
+ let rendered;
569
+ try {
570
+ rendered = fn(block);
571
+ } catch (error) {
572
+ reportBlockError(error, {
573
+ site: "block.withWrapper",
574
+ block: { id: block.id, type: block.type, definition: block.definition },
575
+ keys: {
576
+ props: Object.keys(block.props ?? {}),
577
+ slots: Object.keys(block.slots ?? {})
578
+ }
579
+ });
580
+ rendered = createStubDefinition(block.type).render(block);
581
+ }
582
+ if (wrapper === null) {
583
+ if (isEditorPreview()) {
584
+ wrapper = document.createElement("juo-editor-block-wrapper");
585
+ wrapper.setAttribute("data-block-id", block.id);
586
+ (_a = wrapper.setBlock) == null ? void 0 : _a.call(wrapper, block);
587
+ wrapper.appendChild(rendered);
588
+ } else {
589
+ const evt = new BlockWrapperEvent(block, (evtWrapper) => {
590
+ wrapper = evtWrapper;
591
+ });
592
+ document.dispatchEvent(evt);
593
+ }
594
+ }
595
+ if (!wrapper) {
596
+ return rendered;
597
+ }
598
+ wrapper.replaceChildren(rendered);
599
+ return wrapper;
600
+ };
601
+ }
602
+ const registerBlockListeners = [];
603
+ function registerBlock(block) {
604
+ blockDefinitions.set(block.name, block);
605
+ stubDefinitionCache.delete(block.name);
606
+ registerBlockListeners.forEach((cb) => cb(block.name, block));
607
+ }
608
+ function onRegisterBlock(cb) {
609
+ registerBlockListeners.push(cb);
610
+ return () => {
611
+ const idx = registerBlockListeners.indexOf(cb);
612
+ if (idx >= 0) registerBlockListeners.splice(idx, 1);
613
+ };
614
+ }
615
+ function defineBlock(name, opts) {
616
+ const definition = {
617
+ name,
618
+ displayName: opts.displayName,
619
+ group: opts.group,
620
+ schema: opts.schema,
621
+ initialValue: opts.initialValue,
622
+ render: opts.renderer,
623
+ presets: opts.presets,
624
+ locales: opts.locales
625
+ };
626
+ return definition;
627
+ }
628
+ function defineBlockRuntime(name, opts) {
629
+ const definition = {
630
+ name,
631
+ displayName: opts.displayName,
632
+ group: opts.group,
633
+ schema: {},
634
+ initialValue() {
635
+ throw new Error("Initial value cannot be called in runtime mode");
636
+ },
637
+ render: opts.renderer
638
+ };
639
+ return definition;
640
+ }
641
+ function getDefinedBlocks() {
642
+ return [...blockDefinitions.values()];
643
+ }
644
+ function createCeRenderer(name) {
645
+ function renderSlots(slots, block) {
646
+ if (!slots) {
647
+ return slots;
648
+ }
649
+ return Object.entries(slots).flatMap(([key, value]) => {
650
+ const values = Array.isArray(value) ? value : [value];
651
+ return values.flatMap((value2) => {
652
+ if (typeof value2 === "string") {
653
+ const el = document.createElement("span");
654
+ if (key !== "default") {
655
+ el.slot = key;
656
+ }
657
+ el.innerText = value2;
658
+ return [el];
659
+ }
660
+ try {
661
+ const el = value2.definition.render({
662
+ ...value2,
663
+ props: {
664
+ ...value2.props,
665
+ parentProps: block.props
666
+ }
667
+ });
668
+ if (key !== "default") {
669
+ el.slot = key;
670
+ }
671
+ return [el];
672
+ } catch (error) {
673
+ reportBlockError(error, {
674
+ site: "block.createCeRenderer.renderSlots",
675
+ block: { id: value2.id, type: value2.type, definition: value2.definition },
676
+ extra: {
677
+ parentBlockId: block.id,
678
+ parentBlockType: block.type,
679
+ slotKey: key
680
+ }
681
+ });
682
+ return [];
683
+ }
684
+ });
685
+ });
686
+ }
687
+ return (block) => {
688
+ const el = document.createElement(name);
689
+ el.setAttribute("data-block-id", block.id);
690
+ el.setAttribute("data-block-type", block.type);
691
+ Object.entries(block.props).forEach(([key, value]) => {
692
+ el[key] = value;
693
+ });
694
+ el.replaceChildren(...renderSlots(block.slots, block));
695
+ attachEmptyTracking(el);
696
+ return el;
697
+ };
698
+ }
699
+ const stubDefinitionCache = /* @__PURE__ */ new Map();
700
+ function createStubDefinition(name) {
701
+ const cached = stubDefinitionCache.get(name);
702
+ if (cached) return cached;
703
+ const stub = {
704
+ name,
705
+ group: "internal",
706
+ schema: {},
707
+ initialValue: { props: {}, slots: {} },
708
+ __stub: true,
709
+ render() {
710
+ const el = document.createElement("div");
711
+ el.dataset.stubBlock = name;
712
+ if (isEditorPreview()) {
713
+ el.textContent = `Block definition not found: ${name}`;
714
+ } else {
715
+ el.style.display = "none";
716
+ }
717
+ return el;
718
+ }
719
+ };
720
+ stubDefinitionCache.set(name, stub);
721
+ reportBlockWarning(`Block definition '${name}' not found`, {
722
+ site: "block.createStubDefinition",
723
+ block: { id: "(none)", type: name }
724
+ });
725
+ console.warn(
726
+ `[juo/blocks] Block definition '${name}' not found. This block may have been removed or renamed. Rendering a hidden stub.`
727
+ );
728
+ return stub;
729
+ }
730
+ function isStubDefinition(definition) {
731
+ return definition.__stub === true;
732
+ }
733
+ function backfillInstanceDefaults(block) {
734
+ if (Object.keys(block.props ?? {}).length > 0) return false;
735
+ if (Object.keys(block.slots ?? {}).length > 0) return false;
736
+ if (isStubDefinition(block.definition)) return false;
737
+ let defaults;
738
+ try {
739
+ const iv = block.definition.initialValue;
740
+ defaults = (typeof iv === "function" ? iv() : iv) ?? {};
741
+ } catch (error) {
742
+ reportBlockError(error, {
743
+ site: "block.backfillInstanceDefaults",
744
+ block: { id: block.id, type: block.type, definition: block.definition }
745
+ });
746
+ return false;
747
+ }
748
+ const propsDefault = defaults.props ?? {};
749
+ const slotsDefault = defaults.slots ?? {};
750
+ const hasProps = Object.keys(propsDefault).length > 0;
751
+ const hasSlots = Object.keys(slotsDefault).length > 0;
752
+ if (!hasProps && !hasSlots) return false;
753
+ if (hasProps) Object.assign(block.props, propsDefault);
754
+ if (hasSlots) Object.assign(block.slots, slotsDefault);
755
+ return true;
756
+ }
757
+ function getDefinitionByName(name) {
758
+ const definition = blockDefinitions.get(name);
759
+ if (definition != null) {
760
+ return definition;
761
+ }
762
+ return createStubDefinition(name);
763
+ }
764
+ function createBlockInstance(name, opts) {
765
+ const initialValue = (() => {
766
+ const value = getDefinitionByName(name).initialValue ?? {};
767
+ if (typeof value === "function") {
768
+ return value();
769
+ }
770
+ return value;
771
+ })();
772
+ if ((opts == null ? void 0 : opts.props) == null && initialValue == null) {
773
+ const error = new Error(
774
+ `Block '${name}' cannot be created without value in runtime mode`
775
+ );
776
+ reportBlockError(error, {
777
+ site: "block.createBlockInstance",
778
+ block: { id: "(none)", type: name }
779
+ });
780
+ throw error;
781
+ }
782
+ const slots = {
783
+ ...initialValue.slots,
784
+ ...(opts == null ? void 0 : opts.slots) ?? {}
785
+ };
786
+ const props = {
787
+ ...initialValue.props ?? {},
788
+ ...(opts == null ? void 0 : opts.props) ?? {}
789
+ };
790
+ return {
791
+ // TODO: This should be unique
792
+ id: (opts == null ? void 0 : opts.id) ?? Math.round(1e3 * Math.random()).toString(10),
793
+ type: name,
794
+ props,
795
+ slots,
796
+ get definition() {
797
+ return getDefinitionByName(name);
798
+ }
799
+ };
800
+ }
801
+ function createBlockInstanceFromObject(input) {
802
+ const { id, type, props, slots } = input;
803
+ return createBlockInstance(type, {
804
+ props,
805
+ slots: Object.fromEntries(
806
+ Object.entries(slots).map(([key, value]) => [
807
+ key,
808
+ (Array.isArray(value) ? value : [value]).map(
809
+ (child) => createBlockInstanceFromObject(child)
810
+ )
811
+ ])
812
+ ),
813
+ id
814
+ });
815
+ }
816
+ function createBlockInstanceFromJSON(input) {
817
+ try {
818
+ return createBlockInstanceFromObject(JSON.parse(input));
819
+ } catch (error) {
820
+ reportBlockError(error, {
821
+ site: "block.createBlockInstanceFromJSON",
822
+ extra: { inputLength: input.length }
823
+ });
824
+ throw error;
825
+ }
826
+ }
827
+ const DEFAULT_GLOBAL_STYLES = {
828
+ volume: "comfort",
829
+ style: "ghost",
830
+ corners: "round",
831
+ buttonCorners: "round",
832
+ thumbnailCorners: "circle",
833
+ theme: "preset",
834
+ themeType: "neutral",
835
+ colors: {
836
+ accent: "#000000",
837
+ secondary: "#000000",
838
+ tint: "#111111",
839
+ callout: "#F5F5F5",
840
+ success: "#287a25",
841
+ error: "#a93c3c",
842
+ information: "#0075a3",
843
+ warning: "#8a5e00",
844
+ background: "#FFFFFF"
845
+ }
846
+ };
847
+ const ThemeStateContext = createContext("theme-state");
848
+ function normalizeLocale(locale) {
849
+ return locale.trim().toLowerCase().split("-")[0] || "en";
850
+ }
851
+ function toStringRecord$1(input) {
852
+ if (input == null) return {};
853
+ return Object.fromEntries(
854
+ Object.entries(input).filter(([, value]) => typeof value === "string")
855
+ );
856
+ }
857
+ function parseBlockLocaleFile(file) {
858
+ if (file == null) {
859
+ return { defaults: {}, modes: {} };
860
+ }
861
+ const entries = Object.entries(file).filter(
862
+ ([key, value]) => key !== "overrides" && typeof value === "string"
863
+ );
864
+ const topLevel = Object.fromEntries(entries);
865
+ const overrides = toStringRecord$1(file.overrides);
866
+ return {
867
+ defaults: { ...topLevel, ...overrides },
868
+ modes: {
869
+ ...Object.fromEntries(
870
+ Object.keys(topLevel).map((key) => [key, "default"])
871
+ ),
872
+ ...Object.fromEntries(
873
+ Object.keys(overrides).map((key) => [key, "override"])
874
+ )
875
+ }
876
+ };
877
+ }
878
+ function indexOverrides(overrides) {
879
+ const indexed = {
880
+ theme: {},
881
+ blocks: {}
882
+ };
883
+ for (const item of overrides) {
884
+ if (item.scope.kind === "theme") {
885
+ indexed.theme[item.key] = item.value;
886
+ continue;
887
+ }
888
+ if (indexed.blocks[item.scope.blockId] == null) {
889
+ indexed.blocks[item.scope.blockId] = {};
890
+ }
891
+ indexed.blocks[item.scope.blockId][item.key] = item.value;
892
+ }
893
+ return indexed;
894
+ }
895
+ function createThemeState(deps) {
896
+ var _a;
897
+ const surfaces = {
898
+ page: { blocks: d([]) },
899
+ overlay: { blocks: d([]) }
900
+ };
901
+ const locale = d("en");
902
+ const catalogs = d(null);
903
+ const globalStyles = d(
904
+ deps.initialGlobalStyles ?? DEFAULT_GLOBAL_STYLES
905
+ );
906
+ function setGlobalStyles(styles) {
907
+ globalStyles.value = styles;
908
+ }
909
+ async function collectBlockDefaults(loc) {
910
+ const nextDefaults = {};
911
+ const nextModes = {};
912
+ for (const block of getDefinedBlocks()) {
913
+ if (block.locales == null) continue;
914
+ let file = null;
915
+ try {
916
+ file = await block.locales.load(loc);
917
+ } catch {
918
+ file = null;
919
+ }
920
+ const parsed = parseBlockLocaleFile(file);
921
+ nextDefaults[block.name] = parsed.defaults;
922
+ nextModes[block.name] = parsed.modes;
923
+ }
924
+ return { defaults: nextDefaults, modes: nextModes };
925
+ }
926
+ async function setLocale(nextLocaleRaw) {
927
+ var _a2;
928
+ const nextLocale = normalizeLocale(nextLocaleRaw);
929
+ const [blockData, loadedOverrides] = await Promise.all([
930
+ collectBlockDefaults(nextLocale),
931
+ ((_a2 = deps.translations) == null ? void 0 : _a2.resolveTranslations(nextLocale).catch(() => [])) ?? Promise.resolve([])
932
+ ]);
933
+ const overrides = loadedOverrides.filter(
934
+ (item) => normalizeLocale(item.locale) === nextLocale
935
+ );
936
+ const indexed = indexOverrides(overrides);
937
+ catalogs.value = {
938
+ theme: {
939
+ defaults: {},
940
+ overrides: indexed.theme
941
+ },
942
+ blocks: {
943
+ defaults: blockData.defaults,
944
+ modes: blockData.modes,
945
+ overrides: indexed.blocks
946
+ }
947
+ };
948
+ locale.value = nextLocale;
949
+ }
950
+ async function resolve(surface, path) {
951
+ var _a2, _b, _c, _d;
952
+ surfaces[surface].blocks.value = [];
953
+ const stored = await deps.resolve(surface, path);
954
+ if (stored != null) {
955
+ surfaces[surface].blocks.value = stored.blocks.flatMap((block) => {
956
+ try {
957
+ return [createBlockInstanceFromObject(block)];
958
+ } catch (error) {
959
+ reportBlockError(error, {
960
+ site: "theme-state.resolve.hydrate",
961
+ extra: {
962
+ surface,
963
+ path,
964
+ blockType: typeof (block == null ? void 0 : block.type) === "string" ? block.type : "(unknown)"
965
+ }
966
+ });
967
+ return [];
968
+ }
969
+ });
970
+ return stored;
971
+ }
972
+ const blockToUse = surface === "page" ? (_b = (_a2 = deps.routerService) == null ? void 0 : _a2.getPages().find((p2) => p2.path === path)) == null ? void 0 : _b.block : (_c = getDefinedBlocks().find((b2) => b2.name === path)) == null ? void 0 : _c.name;
973
+ if (blockToUse != null) {
974
+ const instance = createBlockInstance(blockToUse);
975
+ surfaces[surface].blocks.value = [instance];
976
+ const serialized = serializeBlocks([instance]);
977
+ (_d = deps.upsertState) == null ? void 0 : _d.call(deps, surface, path, serialized);
978
+ return { blocks: serialized };
979
+ }
980
+ return { blocks: [] };
981
+ }
982
+ onRegisterBlock(async (_2, block) => {
983
+ if (block.locales == null || catalogs.value == null) return;
984
+ const localeAtLoadStart = locale.value;
985
+ let file = null;
986
+ try {
987
+ file = await block.locales.load(localeAtLoadStart);
988
+ } catch {
989
+ file = null;
990
+ }
991
+ if (catalogs.value == null || locale.value !== localeAtLoadStart) return;
992
+ const parsed = parseBlockLocaleFile(file);
993
+ const current = catalogs.value;
994
+ catalogs.value = {
995
+ ...current,
996
+ blocks: {
997
+ ...current.blocks,
998
+ defaults: {
999
+ ...current.blocks.defaults,
1000
+ [block.name]: parsed.defaults
1001
+ },
1002
+ modes: {
1003
+ ...current.blocks.modes,
1004
+ [block.name]: parsed.modes
1005
+ }
1006
+ }
1007
+ };
1008
+ });
1009
+ (_a = deps.routerService) == null ? void 0 : _a.subscribe(({ path }) => {
1010
+ resolve("page", path);
1011
+ });
1012
+ return {
1013
+ page: surfaces.page,
1014
+ overlay: surfaces.overlay,
1015
+ locales: { locale, catalogs, setLocale },
1016
+ globalStyles,
1017
+ setGlobalStyles,
1018
+ resolve
1019
+ };
1020
+ }
1021
+ const TranslationContext = createContext("translation");
1022
+ function toStringRecord(input) {
1023
+ if (input == null) return {};
1024
+ return Object.fromEntries(
1025
+ Object.entries(input).filter(([, value]) => typeof value === "string")
1026
+ );
1027
+ }
1028
+ function createTranslationService(locales, options = {}) {
1029
+ const loadedThemeDefaults = d({});
1030
+ if (options.loadDefaultTranslations) {
1031
+ let loadVersion = 0;
1032
+ E(() => {
1033
+ const locale = locales.locale.value;
1034
+ const currentVersion = ++loadVersion;
1035
+ void options.loadDefaultTranslations(locale).then((result) => toStringRecord(result)).catch(() => ({})).then((result) => {
1036
+ if (currentVersion !== loadVersion) return;
1037
+ loadedThemeDefaults.value = result;
1038
+ });
1039
+ });
1040
+ }
1041
+ return {
1042
+ locale: locales.locale,
1043
+ resolve(blockType, blockId, key) {
1044
+ var _a, _b, _c;
1045
+ const data = locales.catalogs.value;
1046
+ const themeDefault = loadedThemeDefaults.value[key] ?? (data == null ? void 0 : data.theme.defaults[key]);
1047
+ if (data == null) {
1048
+ return themeDefault ?? key;
1049
+ }
1050
+ if (blockId && ((_a = data.blocks.overrides[blockId]) == null ? void 0 : _a[key]) !== void 0) {
1051
+ return data.blocks.overrides[blockId][key];
1052
+ }
1053
+ const blockDefault = blockType != null ? (_b = data.blocks.defaults[blockType]) == null ? void 0 : _b[key] : void 0;
1054
+ const mode = (blockType != null ? (_c = data.blocks.modes[blockType]) == null ? void 0 : _c[key] : void 0) ?? "override";
1055
+ if (blockDefault !== void 0 && mode === "override") {
1056
+ return blockDefault;
1057
+ }
1058
+ if (data.theme.overrides[key] !== void 0) {
1059
+ return data.theme.overrides[key];
1060
+ }
1061
+ if (themeDefault !== void 0) {
1062
+ return themeDefault;
1063
+ }
1064
+ if (blockDefault !== void 0) {
1065
+ return blockDefault;
1066
+ }
1067
+ return key;
1068
+ }
1069
+ };
1070
+ }
1071
+ function getDefaultBlockForAction(actionType, actionConfig, blockId) {
1072
+ const blockName = `action:${actionType}`;
1073
+ const definedBlocks = getDefinedBlocks();
1074
+ const exists = definedBlocks.some((b2) => b2.name === blockName);
1075
+ if (!exists) {
1076
+ throw new Error(
1077
+ `No default block registered for action type "${actionType}". Expected a block named "${blockName}" to be registered in blocks-extensions.`
1078
+ );
1079
+ }
1080
+ return createBlockInstance(blockName, { props: actionConfig, id: blockId });
1081
+ }
1082
+ function hasDefaultBlockForAction(actionType) {
1083
+ const blockName = `action:${actionType}`;
1084
+ return getDefinedBlocks().some((b2) => b2.name === blockName);
1085
+ }
1086
+ const WorkflowServiceContext = createContext("services/workflow");
1087
+ function createWorkflowApiAdapter(sdk) {
1088
+ return {
1089
+ async start(flowType, context, workflowId, dryRun) {
1090
+ const { data } = await sdk.post("/customer/v1/workflows/start", {
1091
+ flowType,
1092
+ context,
1093
+ ...workflowId ? { workflowId } : {},
1094
+ ...dryRun ? { dryRun: true } : {}
1095
+ });
1096
+ return data;
1097
+ },
1098
+ async respond(runId, interactionId, responseType, responseData, expectedRunVersion, eventId) {
1099
+ const { data } = await sdk.post(
1100
+ "/customer/v1/workflows/{runId}/respond",
1101
+ {
1102
+ runId,
1103
+ interactionId,
1104
+ responseType,
1105
+ responseData,
1106
+ expectedRunVersion,
1107
+ eventId
1108
+ }
1109
+ );
1110
+ return data;
1111
+ },
1112
+ async getState(runId) {
1113
+ const { data } = await sdk.get("/customer/v1/workflows/{runId}", {
1114
+ runId
1115
+ });
1116
+ return data;
1117
+ },
1118
+ async cancel(runId) {
1119
+ const { data } = await sdk.post("/customer/v1/workflows/{runId}/cancel", {
1120
+ runId
1121
+ });
1122
+ return data;
1123
+ }
1124
+ };
1125
+ }
1126
+ function createWorkflowService(deps) {
1127
+ const { api } = deps;
1128
+ const editor = createEditorBridge();
1129
+ const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1130
+ const previewWorkflowTrigger = (urlParams == null ? void 0 : urlParams.get("trigger")) ?? null;
1131
+ const previewStepId = (urlParams == null ? void 0 : urlParams.get("step-id")) ?? null;
1132
+ const previewWorkflowId = (urlParams == null ? void 0 : urlParams.get("workflow-id")) ?? null;
1133
+ const isEditorMode = editor.isEditorMode || previewWorkflowTrigger !== null;
1134
+ const _state = d({
1135
+ status: "idle",
1136
+ flowType: null,
1137
+ workflowId: null,
1138
+ workflowVersion: null,
1139
+ runId: null,
1140
+ runVersion: null,
1141
+ currentStepId: null,
1142
+ currentInteraction: null,
1143
+ error: null,
1144
+ result: null,
1145
+ flowParams: null,
1146
+ invalidatedResources: [],
1147
+ outcome: null,
1148
+ completionData: null,
1149
+ dryRun: null,
1150
+ firstPollReason: null
1151
+ });
1152
+ const _backendInteractionId = d(null);
1153
+ const _registeredRootBlocks = /* @__PURE__ */ new Set();
1154
+ const isActive = w(() => _state.value.status === "active");
1155
+ const isLoading = w(() => _state.value.status === "loading");
1156
+ const isCompleted = w(() => _state.value.status === "completed");
1157
+ const hasError = w(() => _state.value.status === "error");
1158
+ const currentInteraction = w(() => _state.value.currentInteraction);
1159
+ const canRespond = w(() => {
1160
+ const interaction = _state.value.currentInteraction;
1161
+ const backendId = _backendInteractionId.value;
1162
+ if (!interaction || !backendId) return false;
1163
+ return interaction.interactionId === backendId;
1164
+ });
1165
+ const currentStepInfo = w(() => {
1166
+ const interaction = _state.value.currentInteraction;
1167
+ if (!interaction) return null;
1168
+ const actionConfig = deps.shopCurrencyCode ? { ...interaction.actionConfig, currency: deps.shopCurrencyCode } : interaction.actionConfig;
1169
+ return {
1170
+ interactionId: interaction.interactionId,
1171
+ stepId: interaction.stepId,
1172
+ actionType: interaction.actionType,
1173
+ actionConfig,
1174
+ availableResponses: interaction.availableResponses
1175
+ };
1176
+ });
1177
+ function updateState(updates) {
1178
+ _state.value = { ..._state.value, ...updates };
1179
+ }
1180
+ function hashString(value) {
1181
+ let hash = 2166136261;
1182
+ for (let index = 0; index < value.length; index += 1) {
1183
+ hash ^= value.charCodeAt(index);
1184
+ hash = Math.imul(hash, 16777619);
1185
+ }
1186
+ return (hash >>> 0).toString(36);
1187
+ }
1188
+ function shortenId(value, slugLength = 6) {
1189
+ const compact = value.toLowerCase().replace(/[^a-z0-9]/g, "");
1190
+ const slug = (compact || "id").slice(0, slugLength);
1191
+ return `${slug}-${hashString(value)}`;
1192
+ }
1193
+ function createStableStepBlockId(workflowId, stepId) {
1194
+ return `wf-${shortenId(workflowId)}-${shortenId(stepId)}`;
1195
+ }
1196
+ function handleFlowResponse(data) {
1197
+ var _a, _b, _c, _d, _e, _f, _g;
1198
+ const mergedInvalidated = [
1199
+ ..._state.value.invalidatedResources,
1200
+ ...data.invalidatedResources ?? []
1201
+ ];
1202
+ if (data.status === "waiting_interaction") {
1203
+ const currentStepId = ((_a = data.pendingInteraction) == null ? void 0 : _a.stepId) ?? (isEditorMode ? (_c = (_b = data.interactiveSteps) == null ? void 0 : _b[0]) == null ? void 0 : _c.stepId : null);
1204
+ _backendInteractionId.value = ((_d = data.pendingInteraction) == null ? void 0 : _d.interactionId) ?? null;
1205
+ const isInitialResponse = _state.value.runId == null;
1206
+ updateState({
1207
+ status: "active",
1208
+ workflowId: data.workflowId,
1209
+ workflowVersion: data.workflowVersion,
1210
+ runId: data.runId,
1211
+ runVersion: data.runVersion,
1212
+ currentStepId,
1213
+ currentInteraction: data.pendingInteraction,
1214
+ invalidatedResources: mergedInvalidated,
1215
+ outcome: null
1216
+ });
1217
+ if (editor.isEditorMode) {
1218
+ const displayStepId = isInitialResponse && previewStepId && ((_e = data.interactiveSteps) == null ? void 0 : _e.some((s2) => s2.stepId === previewStepId)) ? previewStepId : currentStepId;
1219
+ const overlayBlocks = deps.themeState.overlay.blocks.value;
1220
+ const rootBlock = overlayBlocks[0];
1221
+ const stepSlot = displayStepId ? (_f = rootBlock == null ? void 0 : rootBlock.slots) == null ? void 0 : _f[displayStepId] : null;
1222
+ const stepBlock = Array.isArray(stepSlot) ? stepSlot[0] : null;
1223
+ const blockId = stepBlock && typeof stepBlock === "object" && "id" in stepBlock ? stepBlock.id : null;
1224
+ if (blockId) {
1225
+ editor.sendMessage(
1226
+ createSelectBlockMessage({ blockId }, blockId)
1227
+ );
1228
+ }
1229
+ }
1230
+ } else if (data.status === "completed") {
1231
+ _backendInteractionId.value = null;
1232
+ updateState({
1233
+ status: "completed",
1234
+ currentStepId: null,
1235
+ currentInteraction: null,
1236
+ runVersion: data.runVersion,
1237
+ result: data.result || null,
1238
+ invalidatedResources: mergedInvalidated,
1239
+ outcome: data.outcome || null,
1240
+ completionData: data.completionData || null
1241
+ });
1242
+ } else if (data.status === "failed") {
1243
+ _backendInteractionId.value = null;
1244
+ handleError(new Error(((_g = data.error) == null ? void 0 : _g.message) || "Flow failed"));
1245
+ } else if (data.status === "cancelled") {
1246
+ _backendInteractionId.value = null;
1247
+ updateState({
1248
+ status: "idle",
1249
+ flowType: null,
1250
+ workflowId: null,
1251
+ workflowVersion: null,
1252
+ runId: null,
1253
+ runVersion: null,
1254
+ currentStepId: null,
1255
+ currentInteraction: null,
1256
+ error: null,
1257
+ result: null,
1258
+ invalidatedResources: [],
1259
+ outcome: null,
1260
+ completionData: null,
1261
+ firstPollReason: null
1262
+ });
1263
+ }
1264
+ }
1265
+ function handleError(error) {
1266
+ const message = error instanceof Error ? error.message : "Unknown error";
1267
+ updateState({
1268
+ status: "error",
1269
+ error: message
1270
+ });
1271
+ }
1272
+ function maybeApplyPreviewStep(flowType, data) {
1273
+ var _a;
1274
+ if (!previewWorkflowTrigger) return;
1275
+ if (flowType !== previewWorkflowTrigger) return;
1276
+ if (data.status !== "waiting_interaction") return;
1277
+ const step = (_a = data.interactiveSteps) == null ? void 0 : _a.find(
1278
+ (interactiveStep) => interactiveStep.stepId === previewStepId
1279
+ );
1280
+ if (!step) return;
1281
+ updateState({
1282
+ currentStepId: step.stepId,
1283
+ currentInteraction: {
1284
+ interactionId: `preview-${data.runId}-${step.stepId}`,
1285
+ stepId: step.stepId,
1286
+ actionType: step.actionType,
1287
+ actionBehavior: "input",
1288
+ actionConfig: step.actionConfig,
1289
+ availableResponses: step.availableResponses,
1290
+ presentedAt: /* @__PURE__ */ new Date()
1291
+ }
1292
+ });
1293
+ }
1294
+ function initWorkflowRootBlock(data) {
1295
+ if (_registeredRootBlocks.has(data.workflowId)) {
1296
+ return;
1297
+ }
1298
+ const allSteps = data.interactiveSteps ?? (data.pendingInteraction ? [
1299
+ {
1300
+ stepId: data.pendingInteraction.stepId,
1301
+ actionType: data.pendingInteraction.actionType,
1302
+ actionConfig: data.pendingInteraction.actionConfig,
1303
+ availableResponses: data.pendingInteraction.availableResponses
1304
+ }
1305
+ ] : []);
1306
+ const slotProperties = {};
1307
+ for (const step of allSteps) {
1308
+ slotProperties[step.stepId] = {};
1309
+ }
1310
+ const presets = {};
1311
+ const baseLabelFor = (step) => {
1312
+ var _a;
1313
+ return ((_a = getDefinedBlocks().find((b2) => b2.name === `action:${step.actionType}`)) == null ? void 0 : _a.displayName) ?? step.stepId;
1314
+ };
1315
+ const totalCounts = /* @__PURE__ */ new Map();
1316
+ for (const step of allSteps) {
1317
+ const baseLabel = baseLabelFor(step);
1318
+ totalCounts.set(baseLabel, (totalCounts.get(baseLabel) ?? 0) + 1);
1319
+ }
1320
+ const seenCounts = /* @__PURE__ */ new Map();
1321
+ for (const step of allSteps) {
1322
+ const baseLabel = baseLabelFor(step);
1323
+ const occurrence = (seenCounts.get(baseLabel) ?? 0) + 1;
1324
+ seenCounts.set(baseLabel, occurrence);
1325
+ const isDuplicated = (totalCounts.get(baseLabel) ?? 0) > 1;
1326
+ const label = isDuplicated ? `${baseLabel} (${occurrence})` : baseLabel;
1327
+ presets[step.stepId] = {
1328
+ label,
1329
+ description: step.actionType,
1330
+ state: step.stepId,
1331
+ // @ts-expect-error Untyped
1332
+ context: step
1333
+ };
1334
+ }
1335
+ registerBlock(
1336
+ defineBlock(`workflow:${data.workflowId}`, {
1337
+ group: "workflow",
1338
+ schema: {
1339
+ type: "object",
1340
+ properties: {
1341
+ props: { type: "object" },
1342
+ slots: {
1343
+ type: "object",
1344
+ properties: slotProperties
1345
+ }
1346
+ },
1347
+ required: ["props", "slots"],
1348
+ additionalProperties: true
1349
+ },
1350
+ initialValue: () => ({
1351
+ props: {},
1352
+ slots: Object.fromEntries(
1353
+ allSteps.map((step) => [
1354
+ step.stepId,
1355
+ [
1356
+ getDefaultBlockForAction(
1357
+ step.actionType,
1358
+ step.actionConfig,
1359
+ createStableStepBlockId(data.workflowId, step.stepId)
1360
+ )
1361
+ ]
1362
+ ])
1363
+ )
1364
+ }),
1365
+ presets,
1366
+ renderer() {
1367
+ return null;
1368
+ }
1369
+ })
1370
+ );
1371
+ _registeredRootBlocks.add(data.workflowId);
1372
+ }
1373
+ async function initWorkflowState(data) {
1374
+ const { blocks } = await deps.themeState.resolve(
1375
+ "overlay",
1376
+ `workflow:${data.workflowId}`
1377
+ );
1378
+ if (blocks.length === 0) return;
1379
+ editor.onBlockPresetChange(blocks[0].id, (preset) => {
1380
+ if (!preset) {
1381
+ return;
1382
+ }
1383
+ updateState({
1384
+ // @ts-expect-error Untyped
1385
+ currentStepId: preset.state,
1386
+ // @ts-expect-error Untyped
1387
+ currentInteraction: { ...preset == null ? void 0 : preset.context }
1388
+ });
1389
+ });
1390
+ }
1391
+ const service = {
1392
+ // State signals (readonly)
1393
+ state: _state,
1394
+ /** True when the portal is running inside the Blocks Editor (editorMode dep
1395
+ * or ?trigger=... URL param). Consumers use this to suppress auto-start. */
1396
+ isPreviewMode: isEditorMode,
1397
+ // Computed signals
1398
+ isActive,
1399
+ isLoading,
1400
+ isCompleted,
1401
+ hasError,
1402
+ canRespond,
1403
+ currentInteraction,
1404
+ currentStepInfo,
1405
+ // Methods
1406
+ async startFlow(flowType, context, workflowId) {
1407
+ const isDryRun = isEditorMode;
1408
+ updateState({
1409
+ status: "loading",
1410
+ error: null,
1411
+ flowParams: context,
1412
+ flowType,
1413
+ dryRun: isDryRun,
1414
+ firstPollReason: null
1415
+ });
1416
+ try {
1417
+ const data = await api.start(
1418
+ flowType,
1419
+ context,
1420
+ workflowId,
1421
+ isDryRun || void 0
1422
+ );
1423
+ if (data.status === "no_workflow") {
1424
+ service.reset();
1425
+ return;
1426
+ }
1427
+ if (data.status === "completed_silently") {
1428
+ updateState({
1429
+ status: "completed",
1430
+ currentStepId: null,
1431
+ currentInteraction: null,
1432
+ result: null,
1433
+ invalidatedResources: data.invalidatedResources ?? [],
1434
+ outcome: data.outcome || null,
1435
+ completionData: data.completionData || null
1436
+ });
1437
+ return;
1438
+ }
1439
+ initWorkflowRootBlock(data);
1440
+ await initWorkflowState(data);
1441
+ handleFlowResponse(data);
1442
+ maybeApplyPreviewStep(flowType, data);
1443
+ } catch (error) {
1444
+ handleError(error);
1445
+ }
1446
+ },
1447
+ async respond(responseType, responseData) {
1448
+ const { runId, runVersion, currentInteraction: currentInteraction2 } = _state.value;
1449
+ if (!runId || !currentInteraction2) {
1450
+ throw new Error("No active interaction to respond to");
1451
+ }
1452
+ updateState({ status: "loading" });
1453
+ try {
1454
+ const data = await api.respond(
1455
+ runId,
1456
+ currentInteraction2.interactionId,
1457
+ responseType,
1458
+ responseData,
1459
+ runVersion ?? void 0
1460
+ );
1461
+ if (_state.value.firstPollReason == null && currentInteraction2.actionType === "poll") {
1462
+ const reason = responseData == null ? void 0 : responseData.reason;
1463
+ if (typeof reason === "string" && reason.length > 0) {
1464
+ updateState({ firstPollReason: reason });
1465
+ }
1466
+ }
1467
+ handleFlowResponse(data);
1468
+ } catch (error) {
1469
+ handleError(error);
1470
+ }
1471
+ },
1472
+ async cancel() {
1473
+ const { runId, status } = _state.value;
1474
+ const isTerminal = status === "completed" || status === "error";
1475
+ if (runId && !isTerminal) {
1476
+ try {
1477
+ const data = await api.cancel(runId);
1478
+ if (data.outcome) {
1479
+ updateState({
1480
+ status: "completed",
1481
+ flowType: null,
1482
+ workflowId: null,
1483
+ workflowVersion: null,
1484
+ runId: null,
1485
+ runVersion: null,
1486
+ currentStepId: null,
1487
+ currentInteraction: null,
1488
+ error: null,
1489
+ result: null,
1490
+ flowParams: null,
1491
+ invalidatedResources: data.invalidatedResources ?? [],
1492
+ outcome: data.outcome || null,
1493
+ dryRun: null
1494
+ });
1495
+ return;
1496
+ }
1497
+ } catch {
1498
+ }
1499
+ }
1500
+ service.reset();
1501
+ },
1502
+ reset() {
1503
+ _backendInteractionId.value = null;
1504
+ updateState({
1505
+ status: "idle",
1506
+ flowType: null,
1507
+ workflowId: null,
1508
+ workflowVersion: null,
1509
+ runId: null,
1510
+ runVersion: null,
1511
+ currentStepId: null,
1512
+ currentInteraction: null,
1513
+ error: null,
1514
+ result: null,
1515
+ flowParams: null,
1516
+ invalidatedResources: [],
1517
+ outcome: null,
1518
+ completionData: null,
1519
+ firstPollReason: null
1520
+ });
1521
+ },
1522
+ async refresh() {
1523
+ const { runId } = _state.value;
1524
+ if (!runId) return;
1525
+ try {
1526
+ const data = await api.getState(runId);
1527
+ handleFlowResponse(data);
1528
+ } catch (error) {
1529
+ handleError(error);
1530
+ }
1531
+ }
1532
+ };
1533
+ if (previewWorkflowTrigger) {
1534
+ void service.startFlow(
1535
+ previewWorkflowTrigger,
1536
+ {},
1537
+ previewWorkflowId ?? void 0
1538
+ );
1539
+ }
1540
+ return service;
1541
+ }
1542
+ class JuoWorkflowElement extends HTMLElement {
1543
+ constructor() {
1544
+ super(...arguments);
1545
+ __publicField(this, "workflowService", null);
1546
+ __publicField(this, "unsubscribeContext", null);
1547
+ __publicField(this, "unsubscribeEffect", null);
1548
+ /** Tracks which step is currently mounted to avoid unnecessary DOM teardown. */
1549
+ __publicField(this, "renderedStepId", null);
1550
+ /**
1551
+ * Optional function to wrap rendered content (step blocks).
1552
+ * Must be set before workflow becomes active for correct behavior.
1553
+ */
1554
+ __publicField(this, "blockWrapper", null);
1555
+ }
1556
+ connectedCallback() {
1557
+ this.style.display = "contents";
1558
+ this.unsubscribeContext = subscribeContext(
1559
+ this,
1560
+ WorkflowServiceContext,
1561
+ (service) => {
1562
+ this.workflowService = service;
1563
+ this.setupSubscription();
1564
+ }
1565
+ );
1566
+ }
1567
+ disconnectedCallback() {
1568
+ var _a, _b;
1569
+ (_a = this.unsubscribeContext) == null ? void 0 : _a.call(this);
1570
+ (_b = this.unsubscribeEffect) == null ? void 0 : _b.call(this);
1571
+ this.unsubscribeContext = null;
1572
+ this.unsubscribeEffect = null;
1573
+ this.renderedStepId = null;
1574
+ }
1575
+ setupSubscription() {
1576
+ var _a;
1577
+ if (!this.workflowService) return;
1578
+ (_a = this.unsubscribeEffect) == null ? void 0 : _a.call(this);
1579
+ this.unsubscribeEffect = E(() => {
1580
+ var _a2, _b;
1581
+ const status = ((_a2 = this.workflowService) == null ? void 0 : _a2.state.value.status) ?? "idle";
1582
+ const stepInfo = (_b = this.workflowService) == null ? void 0 : _b.currentStepInfo.value;
1583
+ const stepId = (stepInfo == null ? void 0 : stepInfo.stepId) ?? null;
1584
+ queueMicrotask(() => {
1585
+ if (this.isConnected) {
1586
+ this.render(status, stepId);
1587
+ }
1588
+ });
1589
+ });
1590
+ }
1591
+ render(status, stepId) {
1592
+ var _a;
1593
+ if ((status === "active" || status === "loading") && stepId) {
1594
+ if (this.renderedStepId !== stepId) {
1595
+ this.innerHTML = "";
1596
+ this.renderedStepId = stepId;
1597
+ const extensionRoot = document.createElement(
1598
+ "juo-extension-root"
1599
+ );
1600
+ extensionRoot.setAttribute("surface", "overlay");
1601
+ extensionRoot.setAttribute("name", stepId);
1602
+ extensionRoot.blockWrapper = this.blockWrapper;
1603
+ this.appendChild(extensionRoot);
1604
+ }
1605
+ return;
1606
+ }
1607
+ this.innerHTML = "";
1608
+ this.renderedStepId = null;
1609
+ if (status === "error") {
1610
+ const error = ((_a = this.workflowService) == null ? void 0 : _a.state.value.error) ?? "Unknown error";
1611
+ this.dispatchEvent(
1612
+ new CustomEvent("juo-workflow-error", {
1613
+ bubbles: true,
1614
+ composed: true,
1615
+ detail: { error }
1616
+ })
1617
+ );
1618
+ }
1619
+ }
1620
+ }
1621
+ if (typeof customElements !== "undefined" && !customElements.get("juo-workflow")) {
1622
+ customElements.define("juo-workflow", JuoWorkflowElement);
1623
+ }
1624
+ export {
1625
+ isEditorPreview as A,
1626
+ BlockWrapperEvent as B,
1627
+ ContextProvideEvent as C,
1628
+ DEFAULT_GLOBAL_STYLES as D,
1629
+ E,
1630
+ isStubDefinition as F,
1631
+ onRegisterBlock as G,
1632
+ provideContext as H,
1633
+ serializeBlocks as I,
1634
+ subscribeContext as J,
1635
+ n as K,
1636
+ withWrapper as L,
1637
+ ContextRoot as M,
1638
+ SelectedBlockContext as S,
1639
+ ThemeStateContext as T,
1640
+ WorkflowServiceContext as W,
1641
+ ContextRequestEvent as a,
1642
+ TranslationContext as b,
1643
+ createContext as c,
1644
+ d,
1645
+ attachEmptyTracking as e,
1646
+ backfillInstanceDefaults as f,
1647
+ createBlockInstance as g,
1648
+ createBlockInstanceFromJSON as h,
1649
+ createBlockInstanceFromObject as i,
1650
+ createCeRenderer as j,
1651
+ createSelectedBlock as k,
1652
+ createThemeState as l,
1653
+ createTranslationService as m,
1654
+ createWorkflowApiAdapter as n,
1655
+ createWorkflowService as o,
1656
+ defineBlock as p,
1657
+ defineBlockRuntime as q,
1658
+ registerBlock as r,
1659
+ getDefaultBlockForAction as s,
1660
+ getDefinedBlocks as t,
1661
+ u,
1662
+ hasDefaultBlockForAction as v,
1663
+ w,
1664
+ hasRenderedContent as x,
1665
+ indexOverrides as y,
1666
+ injectContext as z
1667
+ };