@juo/blocks 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/ExtensionRoot-CRJx0Dtr.js +378 -0
  2. package/dist/block.d.ts.map +1 -1
  3. package/dist/{bridge-w5KQ-czl.js → bridge-D838SWmN.js} +146 -32
  4. package/dist/context.d.ts.map +1 -1
  5. package/dist/core.js +775 -35
  6. package/dist/{juo-workflow-BlG9CcAG.js → css-runtime-DWytAzZ5.js} +466 -611
  7. package/dist/editor/bridge.d.ts +8 -0
  8. package/dist/editor/bridge.d.ts.map +1 -1
  9. package/dist/editor/canvas-mode-signal.d.ts +22 -0
  10. package/dist/editor/canvas-mode-signal.d.ts.map +1 -0
  11. package/dist/editor/canvas-mode.d.ts +15 -0
  12. package/dist/editor/canvas-mode.d.ts.map +1 -0
  13. package/dist/editor/canvas-mode.test.d.ts +2 -0
  14. package/dist/editor/canvas-mode.test.d.ts.map +1 -0
  15. package/dist/editor/components.d.ts +113 -0
  16. package/dist/editor/components.d.ts.map +1 -1
  17. package/dist/editor/components.test.d.ts.map +1 -1
  18. package/dist/editor/handler.d.ts.map +1 -1
  19. package/dist/editor/handler.test.d.ts +2 -0
  20. package/dist/editor/handler.test.d.ts.map +1 -0
  21. package/dist/editor/layout-command-emitter.d.ts +31 -0
  22. package/dist/editor/layout-command-emitter.d.ts.map +1 -0
  23. package/dist/editor/layout-command-emitter.test.d.ts +2 -0
  24. package/dist/editor/layout-command-emitter.test.d.ts.map +1 -0
  25. package/dist/editor/layout-system-signal.d.ts +21 -0
  26. package/dist/editor/layout-system-signal.d.ts.map +1 -0
  27. package/dist/editor/main.d.ts +1 -0
  28. package/dist/editor/main.d.ts.map +1 -1
  29. package/dist/editor/messages.d.ts +90 -3
  30. package/dist/editor/messages.d.ts.map +1 -1
  31. package/dist/editor/messages.test.d.ts +2 -0
  32. package/dist/editor/messages.test.d.ts.map +1 -0
  33. package/dist/editor/surface-context.d.ts +7 -0
  34. package/dist/editor/surface-context.d.ts.map +1 -0
  35. package/dist/editor/surface-context.test.d.ts +2 -0
  36. package/dist/editor/surface-context.test.d.ts.map +1 -0
  37. package/dist/editor/wrapper-shared.d.ts +31 -0
  38. package/dist/editor/wrapper-shared.d.ts.map +1 -0
  39. package/dist/editor.js +863 -45
  40. package/dist/gridstack-adapter-DreG3XnB.js +5490 -0
  41. package/dist/layout/css-runtime.d.ts +41 -0
  42. package/dist/layout/css-runtime.d.ts.map +1 -0
  43. package/dist/layout/css-runtime.test.d.ts +2 -0
  44. package/dist/layout/css-runtime.test.d.ts.map +1 -0
  45. package/dist/layout/derive.d.ts +4 -0
  46. package/dist/layout/derive.d.ts.map +1 -0
  47. package/dist/layout/derive.test.d.ts +2 -0
  48. package/dist/layout/derive.test.d.ts.map +1 -0
  49. package/dist/layout/dividers.d.ts +34 -0
  50. package/dist/layout/dividers.d.ts.map +1 -0
  51. package/dist/layout/dividers.test.d.ts +2 -0
  52. package/dist/layout/dividers.test.d.ts.map +1 -0
  53. package/dist/layout/engine.d.ts +3 -0
  54. package/dist/layout/engine.d.ts.map +1 -0
  55. package/dist/layout/engine.test.d.ts +2 -0
  56. package/dist/layout/engine.test.d.ts.map +1 -0
  57. package/dist/layout/grid-utils.d.ts +57 -0
  58. package/dist/layout/grid-utils.d.ts.map +1 -0
  59. package/dist/layout/grid-utils.test.d.ts +2 -0
  60. package/dist/layout/grid-utils.test.d.ts.map +1 -0
  61. package/dist/layout/index.d.ts +12 -0
  62. package/dist/layout/index.d.ts.map +1 -0
  63. package/dist/layout/index.test.d.ts +2 -0
  64. package/dist/layout/index.test.d.ts.map +1 -0
  65. package/dist/layout/insert.d.ts +31 -0
  66. package/dist/layout/insert.d.ts.map +1 -0
  67. package/dist/layout/insert.test.d.ts +2 -0
  68. package/dist/layout/insert.test.d.ts.map +1 -0
  69. package/dist/layout/project-css.d.ts +6 -0
  70. package/dist/layout/project-css.d.ts.map +1 -0
  71. package/dist/layout/project-css.test.d.ts +2 -0
  72. package/dist/layout/project-css.test.d.ts.map +1 -0
  73. package/dist/layout/project-gridstack.d.ts +50 -0
  74. package/dist/layout/project-gridstack.d.ts.map +1 -0
  75. package/dist/layout/project-gridstack.test.d.ts +2 -0
  76. package/dist/layout/project-gridstack.test.d.ts.map +1 -0
  77. package/dist/layout/reconcile.d.ts +22 -0
  78. package/dist/layout/reconcile.d.ts.map +1 -0
  79. package/dist/layout/reconcile.test.d.ts +2 -0
  80. package/dist/layout/reconcile.test.d.ts.map +1 -0
  81. package/dist/layout/types.d.ts +118 -0
  82. package/dist/layout/types.d.ts.map +1 -0
  83. package/dist/layout-mode-adapter-BBd4JRQd.js +21 -0
  84. package/dist/main.d.ts +7 -1
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/morph-Dj-xvrwt.js +182 -0
  87. package/dist/preact.js +1 -1
  88. package/dist/project-gridstack-DYLMKSH1.js +52 -0
  89. package/dist/react.js +1 -1
  90. package/dist/theme-state.d.ts +16 -0
  91. package/dist/theme-state.d.ts.map +1 -1
  92. package/dist/theme-state.layout.test.d.ts +2 -0
  93. package/dist/theme-state.layout.test.d.ts.map +1 -0
  94. package/dist/theme-state.test.d.ts +2 -0
  95. package/dist/theme-state.test.d.ts.map +1 -0
  96. package/dist/vue.js +1 -1
  97. package/dist/web-components/ExtensionRoot.d.ts +50 -2
  98. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  99. package/dist/web-components/editor/ExtensionRoot.d.ts +11 -0
  100. package/dist/web-components/editor/ExtensionRoot.d.ts.map +1 -0
  101. package/dist/web-components/editor/ExtensionRoot.test.d.ts +2 -0
  102. package/dist/web-components/editor/ExtensionRoot.test.d.ts.map +1 -0
  103. package/dist/web-components/editor/InlineText.d.ts +1 -0
  104. package/dist/web-components/editor/InlineText.d.ts.map +1 -1
  105. package/dist/web-components/editor/editor-layout-controller.d.ts +28 -0
  106. package/dist/web-components/editor/editor-layout-controller.d.ts.map +1 -0
  107. package/dist/web-components/editor/gridstack-adapter.d.ts +3 -0
  108. package/dist/web-components/editor/gridstack-adapter.d.ts.map +1 -0
  109. package/dist/web-components/editor/gridstack-adapter.test.d.ts +2 -0
  110. package/dist/web-components/editor/gridstack-adapter.test.d.ts.map +1 -0
  111. package/dist/web-components/editor/morph.d.ts +32 -0
  112. package/dist/web-components/editor/morph.d.ts.map +1 -0
  113. package/dist/web-components/editor/morph.test.d.ts +2 -0
  114. package/dist/web-components/editor/morph.test.d.ts.map +1 -0
  115. package/dist/web-components/layout/layout-controller.d.ts +55 -0
  116. package/dist/web-components/layout/layout-controller.d.ts.map +1 -0
  117. package/dist/web-components/layout/view-layout-controller.d.ts +17 -0
  118. package/dist/web-components/layout/view-layout-controller.d.ts.map +1 -0
  119. package/dist/web-components/layout/view-layout-controller.test.d.ts +2 -0
  120. package/dist/web-components/layout/view-layout-controller.test.d.ts.map +1 -0
  121. package/dist/web-components/layout-grid.d.ts +47 -0
  122. package/dist/web-components/layout-grid.d.ts.map +1 -0
  123. package/dist/web-components/layout-grid.test.d.ts +2 -0
  124. package/dist/web-components/layout-grid.test.d.ts.map +1 -0
  125. package/dist/web-components/layout-mode-adapter.d.ts +51 -0
  126. package/dist/web-components/layout-mode-adapter.d.ts.map +1 -0
  127. package/dist/web-components/layout-mode-adapter.test.d.ts +2 -0
  128. package/dist/web-components/layout-mode-adapter.test.d.ts.map +1 -0
  129. package/dist/web-components-editor.js +125 -17
  130. package/dist/web-components-runtime.js +4 -3
  131. package/package.json +3 -2
  132. package/dist/ExtensionRoot-2xTGTu3K.js +0 -219
package/dist/core.js CHANGED
@@ -1,9 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { c as createContext, d, w, r as registerBlock, E, u } from "./juo-workflow-BlG9CcAG.js";
5
- import { B, C, a, D, S, T, b, W, e, f, g, h, i, j, k, l, m, n, o, p, q, s, t, v, x, y, z, A, F, G, H, I, J, K, L } from "./juo-workflow-BlG9CcAG.js";
4
+ import { c as createContext, d, w, r as registerBlock, E, u, g as getDefinedBlocks, a as createBlockInstance, b as defineBlock, s as subscribeContext, G as GRID_V1_ENGINE_ID, e as clampRect, f as applyFillExpansion, h as compactItems, i as findFreeRect, D as DEFAULT_GRID } from "./css-runtime-DWytAzZ5.js";
5
+ import { B, C, j, k, l, L, P, S, T, m, n, o, p, q, t, v, x, y, z, A, F, H, I, J, K, M, N, O, Q, R, U, V, W, X, Y, Z, _, $, a0, a1, a2, a3, a4, a5 } from "./css-runtime-DWytAzZ5.js";
6
6
  import { reportBlockWarning, reportBlockError } from "./observability.js";
7
+ import { c as createEditorBridge, a as createSelectBlockMessage } from "./bridge-D838SWmN.js";
8
+ import { p as p2 } from "./project-gridstack-DYLMKSH1.js";
9
+ import { clearLayoutModeAdapter, getLayoutModeAdapter, registerLayoutModeAdapter } from "./layout-mode-adapter-BBd4JRQd.js";
7
10
  function createState() {
8
11
  const discountCode = d(null);
9
12
  const products = d([]);
@@ -132,7 +135,7 @@ async function loadBlockRegistry(options = {}) {
132
135
  if ("registerBlocks" in module && typeof module.registerBlocks === "function") {
133
136
  module.registerBlocks();
134
137
  } else {
135
- Object.entries(module).forEach(([_, item]) => {
138
+ Object.entries(module).forEach(([_2, item]) => {
136
139
  if (typeof item === "object" && item != null) {
137
140
  registerBlock(item);
138
141
  }
@@ -793,7 +796,7 @@ function routeNameTableFromPages(pages) {
793
796
  function createRouterService(options) {
794
797
  const { pages, pushImplementation } = options;
795
798
  const routeNameToPagePath = routeNameTableFromPages(pages);
796
- const pathSet = new Set(pages.map((p2) => p2.path));
799
+ const pathSet = new Set(pages.map((p3) => p3.path));
797
800
  const navigationSubscribers = [];
798
801
  function notifySubscribers(logicalPath) {
799
802
  for (const cb of navigationSubscribers) cb({ path: logicalPath });
@@ -1221,6 +1224,487 @@ const DISCOUNT_REJECTION_REASONS = [
1221
1224
  "INVALID_COMBINATION",
1222
1225
  "QUANTITY_REQUIREMENT_NOT_MET"
1223
1226
  ];
1227
+ function getDefaultBlockForAction(actionType, actionConfig, blockId) {
1228
+ const blockName = `action:${actionType}`;
1229
+ const definedBlocks = getDefinedBlocks();
1230
+ const exists = definedBlocks.some((b) => b.name === blockName);
1231
+ if (!exists) {
1232
+ throw new Error(
1233
+ `No default block registered for action type "${actionType}". Expected a block named "${blockName}" to be registered in blocks-extensions.`
1234
+ );
1235
+ }
1236
+ return createBlockInstance(blockName, { props: actionConfig, id: blockId });
1237
+ }
1238
+ function hasDefaultBlockForAction(actionType) {
1239
+ const blockName = `action:${actionType}`;
1240
+ return getDefinedBlocks().some((b) => b.name === blockName);
1241
+ }
1242
+ const WorkflowServiceContext = createContext("services/workflow");
1243
+ const RUN_SCOPED_RESET = {
1244
+ firstPollReason: null,
1245
+ feedbackCollected: false
1246
+ };
1247
+ function createWorkflowApiAdapter(sdk) {
1248
+ return {
1249
+ async start(flowType, context, workflowId, dryRun) {
1250
+ const { data } = await sdk.post("/customer/v1/workflows/start", {
1251
+ flowType,
1252
+ context,
1253
+ ...workflowId ? { workflowId } : {},
1254
+ ...dryRun ? { dryRun: true } : {}
1255
+ });
1256
+ return data;
1257
+ },
1258
+ async respond(runId, interactionId, responseType, responseData, expectedRunVersion, eventId) {
1259
+ const { data } = await sdk.post(
1260
+ "/customer/v1/workflows/{runId}/respond",
1261
+ {
1262
+ runId,
1263
+ interactionId,
1264
+ responseType,
1265
+ responseData,
1266
+ expectedRunVersion,
1267
+ eventId
1268
+ }
1269
+ );
1270
+ return data;
1271
+ },
1272
+ async getState(runId) {
1273
+ const { data } = await sdk.get("/customer/v1/workflows/{runId}", {
1274
+ runId
1275
+ });
1276
+ return data;
1277
+ },
1278
+ async cancel(runId) {
1279
+ const { data } = await sdk.post("/customer/v1/workflows/{runId}/cancel", {
1280
+ runId
1281
+ });
1282
+ return data;
1283
+ }
1284
+ };
1285
+ }
1286
+ function createWorkflowService(deps) {
1287
+ const { api } = deps;
1288
+ const editor = createEditorBridge();
1289
+ const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1290
+ const previewWorkflowTrigger = (urlParams == null ? void 0 : urlParams.get("trigger")) ?? null;
1291
+ const previewStepId = (urlParams == null ? void 0 : urlParams.get("step-id")) ?? null;
1292
+ const previewWorkflowId = (urlParams == null ? void 0 : urlParams.get("workflow-id")) ?? null;
1293
+ const isEditorMode = editor.isEditorMode || previewWorkflowTrigger !== null;
1294
+ const _state = d({
1295
+ status: "idle",
1296
+ flowType: null,
1297
+ workflowId: null,
1298
+ workflowVersion: null,
1299
+ runId: null,
1300
+ runVersion: null,
1301
+ currentStepId: null,
1302
+ currentInteraction: null,
1303
+ error: null,
1304
+ result: null,
1305
+ flowParams: null,
1306
+ invalidatedResources: [],
1307
+ outcome: null,
1308
+ completionData: null,
1309
+ dryRun: null,
1310
+ ...RUN_SCOPED_RESET
1311
+ });
1312
+ const _backendInteractionId = d(null);
1313
+ const _registeredRootBlocks = /* @__PURE__ */ new Set();
1314
+ const isActive = w(() => _state.value.status === "active");
1315
+ const isLoading = w(() => _state.value.status === "loading");
1316
+ const isCompleted = w(() => _state.value.status === "completed");
1317
+ const hasError = w(() => _state.value.status === "error");
1318
+ const currentInteraction = w(() => _state.value.currentInteraction);
1319
+ const canRespond = w(() => {
1320
+ const interaction = _state.value.currentInteraction;
1321
+ const backendId = _backendInteractionId.value;
1322
+ if (!interaction || !backendId) return false;
1323
+ return interaction.interactionId === backendId;
1324
+ });
1325
+ const currentStepInfo = w(() => {
1326
+ const interaction = _state.value.currentInteraction;
1327
+ if (!interaction) return null;
1328
+ const actionConfig = deps.shopCurrencyCode ? { ...interaction.actionConfig, currency: deps.shopCurrencyCode } : interaction.actionConfig;
1329
+ return {
1330
+ interactionId: interaction.interactionId,
1331
+ stepId: interaction.stepId,
1332
+ actionType: interaction.actionType,
1333
+ actionConfig,
1334
+ availableResponses: interaction.availableResponses
1335
+ };
1336
+ });
1337
+ function updateState(updates) {
1338
+ _state.value = { ..._state.value, ...updates };
1339
+ }
1340
+ function hashString(value) {
1341
+ let hash = 2166136261;
1342
+ for (let index = 0; index < value.length; index += 1) {
1343
+ hash ^= value.charCodeAt(index);
1344
+ hash = Math.imul(hash, 16777619);
1345
+ }
1346
+ return (hash >>> 0).toString(36);
1347
+ }
1348
+ function shortenId(value, slugLength = 6) {
1349
+ const compact = value.toLowerCase().replace(/[^a-z0-9]/g, "");
1350
+ const slug = (compact || "id").slice(0, slugLength);
1351
+ return `${slug}-${hashString(value)}`;
1352
+ }
1353
+ function createStableStepBlockId(workflowId, stepId) {
1354
+ return `wf-${shortenId(workflowId)}-${shortenId(stepId)}`;
1355
+ }
1356
+ function handleFlowResponse(data) {
1357
+ var _a, _b, _c, _d, _e, _f, _g;
1358
+ const mergedInvalidated = [
1359
+ ..._state.value.invalidatedResources,
1360
+ ...data.invalidatedResources ?? []
1361
+ ];
1362
+ if (data.status === "waiting_interaction") {
1363
+ 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);
1364
+ _backendInteractionId.value = ((_d = data.pendingInteraction) == null ? void 0 : _d.interactionId) ?? null;
1365
+ const isInitialResponse = _state.value.runId == null;
1366
+ updateState({
1367
+ status: "active",
1368
+ workflowId: data.workflowId,
1369
+ workflowVersion: data.workflowVersion,
1370
+ runId: data.runId,
1371
+ runVersion: data.runVersion,
1372
+ currentStepId,
1373
+ currentInteraction: data.pendingInteraction,
1374
+ invalidatedResources: mergedInvalidated,
1375
+ outcome: null
1376
+ });
1377
+ if (editor.isEditorMode) {
1378
+ const displayStepId = isInitialResponse && previewStepId && ((_e = data.interactiveSteps) == null ? void 0 : _e.some((s) => s.stepId === previewStepId)) ? previewStepId : currentStepId;
1379
+ const overlayBlocks = deps.themeState.overlay.blocks.value;
1380
+ const rootBlock = overlayBlocks[0];
1381
+ const stepSlot = displayStepId ? (_f = rootBlock == null ? void 0 : rootBlock.slots) == null ? void 0 : _f[displayStepId] : null;
1382
+ const stepBlock = Array.isArray(stepSlot) ? stepSlot[0] : null;
1383
+ const blockId = stepBlock && typeof stepBlock === "object" && "id" in stepBlock ? stepBlock.id : null;
1384
+ if (blockId) {
1385
+ editor.sendMessage(
1386
+ createSelectBlockMessage({ blockId }, blockId)
1387
+ );
1388
+ }
1389
+ }
1390
+ } else if (data.status === "completed") {
1391
+ _backendInteractionId.value = null;
1392
+ updateState({
1393
+ status: "completed",
1394
+ currentStepId: null,
1395
+ currentInteraction: null,
1396
+ runVersion: data.runVersion,
1397
+ result: data.result || null,
1398
+ invalidatedResources: mergedInvalidated,
1399
+ outcome: data.outcome || null,
1400
+ completionData: data.completionData || null
1401
+ });
1402
+ } else if (data.status === "failed") {
1403
+ _backendInteractionId.value = null;
1404
+ handleError(new Error(((_g = data.error) == null ? void 0 : _g.message) || "Flow failed"));
1405
+ } else if (data.status === "cancelled") {
1406
+ _backendInteractionId.value = null;
1407
+ updateState({
1408
+ status: "idle",
1409
+ flowType: null,
1410
+ workflowId: null,
1411
+ workflowVersion: null,
1412
+ runId: null,
1413
+ runVersion: null,
1414
+ currentStepId: null,
1415
+ currentInteraction: null,
1416
+ error: null,
1417
+ result: null,
1418
+ invalidatedResources: [],
1419
+ outcome: null,
1420
+ completionData: null,
1421
+ ...RUN_SCOPED_RESET
1422
+ });
1423
+ }
1424
+ }
1425
+ function handleError(error) {
1426
+ const message = error instanceof Error ? error.message : "Unknown error";
1427
+ updateState({
1428
+ status: "error",
1429
+ error: message
1430
+ });
1431
+ }
1432
+ function maybeApplyPreviewStep(flowType, data) {
1433
+ var _a;
1434
+ if (!previewWorkflowTrigger) return;
1435
+ if (flowType !== previewWorkflowTrigger) return;
1436
+ if (data.status !== "waiting_interaction") return;
1437
+ const step = (_a = data.interactiveSteps) == null ? void 0 : _a.find(
1438
+ (interactiveStep) => interactiveStep.stepId === previewStepId
1439
+ );
1440
+ if (!step) return;
1441
+ updateState({
1442
+ currentStepId: step.stepId,
1443
+ currentInteraction: {
1444
+ interactionId: `preview-${data.runId}-${step.stepId}`,
1445
+ stepId: step.stepId,
1446
+ actionType: step.actionType,
1447
+ actionBehavior: "input",
1448
+ actionConfig: step.actionConfig,
1449
+ availableResponses: step.availableResponses,
1450
+ presentedAt: /* @__PURE__ */ new Date()
1451
+ }
1452
+ });
1453
+ }
1454
+ function initWorkflowRootBlock(data) {
1455
+ if (_registeredRootBlocks.has(data.workflowId)) {
1456
+ return;
1457
+ }
1458
+ const allSteps = data.interactiveSteps ?? (data.pendingInteraction ? [
1459
+ {
1460
+ stepId: data.pendingInteraction.stepId,
1461
+ actionType: data.pendingInteraction.actionType,
1462
+ actionConfig: data.pendingInteraction.actionConfig,
1463
+ availableResponses: data.pendingInteraction.availableResponses
1464
+ }
1465
+ ] : []);
1466
+ const slotProperties = {};
1467
+ for (const step of allSteps) {
1468
+ slotProperties[step.stepId] = {};
1469
+ }
1470
+ const presets = {};
1471
+ const baseLabelFor = (step) => {
1472
+ var _a;
1473
+ return ((_a = getDefinedBlocks().find((b) => b.name === `action:${step.actionType}`)) == null ? void 0 : _a.displayName) ?? step.stepId;
1474
+ };
1475
+ const totalCounts = /* @__PURE__ */ new Map();
1476
+ for (const step of allSteps) {
1477
+ const baseLabel = baseLabelFor(step);
1478
+ totalCounts.set(baseLabel, (totalCounts.get(baseLabel) ?? 0) + 1);
1479
+ }
1480
+ const seenCounts = /* @__PURE__ */ new Map();
1481
+ for (const step of allSteps) {
1482
+ const baseLabel = baseLabelFor(step);
1483
+ const occurrence = (seenCounts.get(baseLabel) ?? 0) + 1;
1484
+ seenCounts.set(baseLabel, occurrence);
1485
+ const isDuplicated = (totalCounts.get(baseLabel) ?? 0) > 1;
1486
+ const label = isDuplicated ? `${baseLabel} (${occurrence})` : baseLabel;
1487
+ presets[step.stepId] = {
1488
+ label,
1489
+ description: step.actionType,
1490
+ state: step.stepId,
1491
+ // @ts-expect-error Untyped
1492
+ context: step
1493
+ };
1494
+ }
1495
+ registerBlock(
1496
+ defineBlock(`workflow:${data.workflowId}`, {
1497
+ group: "workflow",
1498
+ schema: {
1499
+ type: "object",
1500
+ properties: {
1501
+ props: { type: "object" },
1502
+ slots: {
1503
+ type: "object",
1504
+ properties: slotProperties
1505
+ }
1506
+ },
1507
+ required: ["props", "slots"],
1508
+ additionalProperties: true
1509
+ },
1510
+ initialValue: () => ({
1511
+ props: {},
1512
+ slots: Object.fromEntries(
1513
+ allSteps.map((step) => [
1514
+ step.stepId,
1515
+ [
1516
+ getDefaultBlockForAction(
1517
+ step.actionType,
1518
+ step.actionConfig,
1519
+ createStableStepBlockId(data.workflowId, step.stepId)
1520
+ )
1521
+ ]
1522
+ ])
1523
+ )
1524
+ }),
1525
+ presets,
1526
+ renderer() {
1527
+ return null;
1528
+ }
1529
+ })
1530
+ );
1531
+ _registeredRootBlocks.add(data.workflowId);
1532
+ }
1533
+ async function initWorkflowState(data) {
1534
+ const { blocks } = await deps.themeState.resolve(
1535
+ "overlay",
1536
+ `workflow:${data.workflowId}`
1537
+ );
1538
+ if (blocks.length === 0) return;
1539
+ editor.onBlockPresetChange(blocks[0].id, (preset) => {
1540
+ if (!preset) {
1541
+ return;
1542
+ }
1543
+ updateState({
1544
+ // @ts-expect-error Untyped
1545
+ currentStepId: preset.state,
1546
+ // @ts-expect-error Untyped
1547
+ currentInteraction: { ...preset == null ? void 0 : preset.context }
1548
+ });
1549
+ });
1550
+ }
1551
+ const service = {
1552
+ // State signals (readonly)
1553
+ state: _state,
1554
+ /** True when the portal is running inside the Blocks Editor (editorMode dep
1555
+ * or ?trigger=... URL param). Consumers use this to suppress auto-start. */
1556
+ isPreviewMode: isEditorMode,
1557
+ // Computed signals
1558
+ isActive,
1559
+ isLoading,
1560
+ isCompleted,
1561
+ hasError,
1562
+ canRespond,
1563
+ currentInteraction,
1564
+ currentStepInfo,
1565
+ // Methods
1566
+ async startFlow(flowType, context, workflowId) {
1567
+ const isDryRun = isEditorMode;
1568
+ updateState({
1569
+ status: "loading",
1570
+ error: null,
1571
+ flowParams: context,
1572
+ flowType,
1573
+ dryRun: isDryRun,
1574
+ ...RUN_SCOPED_RESET
1575
+ });
1576
+ try {
1577
+ const data = await api.start(
1578
+ flowType,
1579
+ context,
1580
+ workflowId,
1581
+ isDryRun || void 0
1582
+ );
1583
+ if (data.status === "no_workflow") {
1584
+ service.reset();
1585
+ return;
1586
+ }
1587
+ if (data.status === "completed_silently") {
1588
+ updateState({
1589
+ status: "completed",
1590
+ currentStepId: null,
1591
+ currentInteraction: null,
1592
+ result: null,
1593
+ invalidatedResources: data.invalidatedResources ?? [],
1594
+ outcome: data.outcome || null,
1595
+ completionData: data.completionData || null
1596
+ });
1597
+ return;
1598
+ }
1599
+ initWorkflowRootBlock(data);
1600
+ await initWorkflowState(data);
1601
+ handleFlowResponse(data);
1602
+ maybeApplyPreviewStep(flowType, data);
1603
+ } catch (error) {
1604
+ handleError(error);
1605
+ }
1606
+ },
1607
+ async respond(responseType, responseData) {
1608
+ const { runId, runVersion, currentInteraction: currentInteraction2 } = _state.value;
1609
+ if (!runId || !currentInteraction2) {
1610
+ throw new Error("No active interaction to respond to");
1611
+ }
1612
+ updateState({ status: "loading" });
1613
+ try {
1614
+ const data = await api.respond(
1615
+ runId,
1616
+ currentInteraction2.interactionId,
1617
+ responseType,
1618
+ responseData,
1619
+ runVersion ?? void 0
1620
+ );
1621
+ if (_state.value.firstPollReason == null && currentInteraction2.actionType === "poll") {
1622
+ const reason = responseData == null ? void 0 : responseData.reason;
1623
+ if (typeof reason === "string" && reason.length > 0) {
1624
+ updateState({ firstPollReason: reason });
1625
+ }
1626
+ }
1627
+ if (!_state.value.feedbackCollected && currentInteraction2.actionType === "collect_feedback" && responseType === "submitted") {
1628
+ const feedback = responseData == null ? void 0 : responseData.feedback;
1629
+ if (typeof feedback === "string" && feedback.trim().length > 0) {
1630
+ updateState({ feedbackCollected: true });
1631
+ }
1632
+ }
1633
+ handleFlowResponse(data);
1634
+ } catch (error) {
1635
+ handleError(error);
1636
+ }
1637
+ },
1638
+ async cancel() {
1639
+ const { runId, status } = _state.value;
1640
+ const isTerminal = status === "completed" || status === "error";
1641
+ if (runId && !isTerminal) {
1642
+ try {
1643
+ const data = await api.cancel(runId);
1644
+ if (data.outcome) {
1645
+ updateState({
1646
+ status: "completed",
1647
+ flowType: null,
1648
+ workflowId: null,
1649
+ workflowVersion: null,
1650
+ runId: null,
1651
+ runVersion: null,
1652
+ currentStepId: null,
1653
+ currentInteraction: null,
1654
+ error: null,
1655
+ result: null,
1656
+ flowParams: null,
1657
+ invalidatedResources: data.invalidatedResources ?? [],
1658
+ outcome: data.outcome || null,
1659
+ dryRun: null
1660
+ });
1661
+ return;
1662
+ }
1663
+ } catch {
1664
+ }
1665
+ }
1666
+ service.reset();
1667
+ },
1668
+ reset() {
1669
+ _backendInteractionId.value = null;
1670
+ updateState({
1671
+ status: "idle",
1672
+ flowType: null,
1673
+ workflowId: null,
1674
+ workflowVersion: null,
1675
+ runId: null,
1676
+ runVersion: null,
1677
+ currentStepId: null,
1678
+ currentInteraction: null,
1679
+ error: null,
1680
+ result: null,
1681
+ flowParams: null,
1682
+ invalidatedResources: [],
1683
+ outcome: null,
1684
+ completionData: null,
1685
+ ...RUN_SCOPED_RESET
1686
+ });
1687
+ },
1688
+ async refresh() {
1689
+ const { runId } = _state.value;
1690
+ if (!runId) return;
1691
+ try {
1692
+ const data = await api.getState(runId);
1693
+ handleFlowResponse(data);
1694
+ } catch (error) {
1695
+ handleError(error);
1696
+ }
1697
+ }
1698
+ };
1699
+ if (previewWorkflowTrigger) {
1700
+ void service.startFlow(
1701
+ previewWorkflowTrigger,
1702
+ {},
1703
+ previewWorkflowId ?? void 0
1704
+ );
1705
+ }
1706
+ return service;
1707
+ }
1224
1708
  const MOCK_FLOWS = {
1225
1709
  cancellation: [
1226
1710
  {
@@ -1471,17 +1955,241 @@ function createMockWorkflowApiAdapter() {
1471
1955
  }
1472
1956
  };
1473
1957
  }
1958
+ class JuoWorkflowElement extends HTMLElement {
1959
+ constructor() {
1960
+ super(...arguments);
1961
+ __publicField(this, "workflowService", null);
1962
+ __publicField(this, "unsubscribeContext", null);
1963
+ __publicField(this, "unsubscribeEffect", null);
1964
+ /** Tracks which step is currently mounted to avoid unnecessary DOM teardown. */
1965
+ __publicField(this, "renderedStepId", null);
1966
+ /**
1967
+ * Optional function to wrap rendered content (step blocks).
1968
+ * Must be set before workflow becomes active for correct behavior.
1969
+ */
1970
+ __publicField(this, "blockWrapper", null);
1971
+ }
1972
+ connectedCallback() {
1973
+ this.style.display = "contents";
1974
+ this.unsubscribeContext = subscribeContext(
1975
+ this,
1976
+ WorkflowServiceContext,
1977
+ (service) => {
1978
+ this.workflowService = service;
1979
+ this.setupSubscription();
1980
+ }
1981
+ );
1982
+ }
1983
+ disconnectedCallback() {
1984
+ var _a, _b;
1985
+ (_a = this.unsubscribeContext) == null ? void 0 : _a.call(this);
1986
+ (_b = this.unsubscribeEffect) == null ? void 0 : _b.call(this);
1987
+ this.unsubscribeContext = null;
1988
+ this.unsubscribeEffect = null;
1989
+ this.renderedStepId = null;
1990
+ }
1991
+ setupSubscription() {
1992
+ var _a;
1993
+ if (!this.workflowService) return;
1994
+ (_a = this.unsubscribeEffect) == null ? void 0 : _a.call(this);
1995
+ this.unsubscribeEffect = E(() => {
1996
+ var _a2, _b;
1997
+ const status = ((_a2 = this.workflowService) == null ? void 0 : _a2.state.value.status) ?? "idle";
1998
+ const stepInfo = (_b = this.workflowService) == null ? void 0 : _b.currentStepInfo.value;
1999
+ const stepId = (stepInfo == null ? void 0 : stepInfo.stepId) ?? null;
2000
+ queueMicrotask(() => {
2001
+ if (this.isConnected) {
2002
+ this.render(status, stepId);
2003
+ }
2004
+ });
2005
+ });
2006
+ }
2007
+ render(status, stepId) {
2008
+ var _a;
2009
+ if ((status === "active" || status === "loading") && stepId) {
2010
+ if (this.renderedStepId !== stepId) {
2011
+ this.innerHTML = "";
2012
+ this.renderedStepId = stepId;
2013
+ const extensionRoot = document.createElement(
2014
+ "juo-extension-root"
2015
+ );
2016
+ extensionRoot.setAttribute("surface", "overlay");
2017
+ extensionRoot.setAttribute("name", stepId);
2018
+ extensionRoot.blockWrapper = this.blockWrapper;
2019
+ this.appendChild(extensionRoot);
2020
+ }
2021
+ return;
2022
+ }
2023
+ this.innerHTML = "";
2024
+ this.renderedStepId = null;
2025
+ if (status === "error") {
2026
+ const error = ((_a = this.workflowService) == null ? void 0 : _a.state.value.error) ?? "Unknown error";
2027
+ this.dispatchEvent(
2028
+ new CustomEvent("juo-workflow-error", {
2029
+ bubbles: true,
2030
+ composed: true,
2031
+ detail: { error }
2032
+ })
2033
+ );
2034
+ }
2035
+ }
2036
+ }
2037
+ if (typeof customElements !== "undefined" && !customElements.get("juo-workflow")) {
2038
+ customElements.define("juo-workflow", JuoWorkflowElement);
2039
+ }
2040
+ const gridV1Engine = {
2041
+ id: GRID_V1_ENGINE_ID,
2042
+ applyCommand(doc, cmd, ctx2) {
2043
+ const next = structuredClone(doc);
2044
+ const existing = next.layouts[ctx2.breakpoint];
2045
+ const layout = existing ?? {
2046
+ grid: { cols: ctx2.cols, gap: ctx2.gap, rowUnit: ctx2.rowUnit },
2047
+ items: {}
2048
+ };
2049
+ layout.grid = { cols: ctx2.cols, gap: ctx2.gap, rowUnit: ctx2.rowUnit };
2050
+ switch (cmd.kind) {
2051
+ case "add": {
2052
+ layout.items[cmd.blockId] = cmd.rect ? clampRect(cmd.rect, ctx2.cols) : findFreeRect(layout.items, { w: ctx2.cols, h: 1 }, ctx2.cols);
2053
+ break;
2054
+ }
2055
+ case "move": {
2056
+ const current = layout.items[cmd.blockId];
2057
+ if (current) {
2058
+ layout.items[cmd.blockId] = clampRect(
2059
+ { ...current, c: cmd.to.c, r: cmd.to.r },
2060
+ ctx2.cols
2061
+ );
2062
+ }
2063
+ break;
2064
+ }
2065
+ case "resize": {
2066
+ const current = layout.items[cmd.blockId];
2067
+ if (current) {
2068
+ const w2 = Math.max(1, Math.min(cmd.size.w, ctx2.cols - current.c));
2069
+ const h = Math.max(1, cmd.size.h);
2070
+ layout.items[cmd.blockId] = { ...current, w: w2, h };
2071
+ }
2072
+ break;
2073
+ }
2074
+ case "remove": {
2075
+ delete layout.items[cmd.blockId];
2076
+ layout.items = compactItems(layout.items, ctx2.cols);
2077
+ break;
2078
+ }
2079
+ case "setRects": {
2080
+ for (const [blockId, rect] of Object.entries(cmd.rects)) {
2081
+ const prev = layout.items[blockId];
2082
+ const clamped = clampRect(rect, ctx2.cols);
2083
+ clamped.fill = (prev == null ? void 0 : prev.fill) === true && rect.w === prev.w;
2084
+ if (!clamped.fill) delete clamped.fill;
2085
+ layout.items[blockId] = clamped;
2086
+ }
2087
+ break;
2088
+ }
2089
+ case "fillWidth": {
2090
+ const current = layout.items[cmd.blockId];
2091
+ if (current) {
2092
+ const nextFill = current.fill !== true;
2093
+ layout.items[cmd.blockId] = nextFill ? { ...current, fill: true } : (() => {
2094
+ const { fill, ...rest } = current;
2095
+ return rest;
2096
+ })();
2097
+ }
2098
+ break;
2099
+ }
2100
+ }
2101
+ layout.items = applyFillExpansion(layout.items, ctx2.cols);
2102
+ next.layouts[ctx2.breakpoint] = layout;
2103
+ return next;
2104
+ },
2105
+ reflow(doc, ctx2) {
2106
+ const next = structuredClone(doc);
2107
+ const layout = next.layouts[ctx2.breakpoint];
2108
+ if (layout) {
2109
+ layout.grid = { cols: ctx2.cols, gap: ctx2.gap, rowUnit: ctx2.rowUnit };
2110
+ for (const id of Object.keys(layout.items)) {
2111
+ layout.items[id] = clampRect(layout.items[id], ctx2.cols);
2112
+ }
2113
+ layout.items = applyFillExpansion(layout.items, ctx2.cols);
2114
+ }
2115
+ return next;
2116
+ }
2117
+ };
2118
+ const DEFAULT_NEW_BLOCK_HEIGHT = 4;
2119
+ function insertRectRelative(doc, args) {
2120
+ var _a, _b;
2121
+ const baseId = (_a = doc.breakpoints[0]) == null ? void 0 : _a.id;
2122
+ if (!baseId) return doc;
2123
+ const baseLayout = doc.layouts[baseId];
2124
+ if (!baseLayout) return doc;
2125
+ const target = baseLayout.items[args.targetId];
2126
+ if (!target) return doc;
2127
+ const next = structuredClone(doc);
2128
+ const layout = next.layouts[baseId];
2129
+ if (!layout) return doc;
2130
+ const cols = ((_b = layout.grid) == null ? void 0 : _b.cols) ?? DEFAULT_GRID.cols;
2131
+ const newHeight = DEFAULT_NEW_BLOCK_HEIGHT;
2132
+ const insertRow = args.position === "before" ? target.r : target.r + target.h;
2133
+ for (const [id, rect] of Object.entries(layout.items)) {
2134
+ if (id === args.blockId) continue;
2135
+ if (rect.r >= insertRow) {
2136
+ layout.items[id] = { ...rect, r: rect.r + newHeight };
2137
+ }
2138
+ }
2139
+ layout.items[args.blockId] = clampRect(
2140
+ { c: target.c, r: insertRow, w: target.w, h: newHeight },
2141
+ cols
2142
+ );
2143
+ return next;
2144
+ }
2145
+ const canvasMode = d(false);
2146
+ const ctx = {};
2147
+ function setActiveSurfaceContext(surface, id) {
2148
+ if (id == null) {
2149
+ delete ctx[surface];
2150
+ return;
2151
+ }
2152
+ ctx[surface] = { id };
2153
+ }
2154
+ function getActiveSurfaceContext(surface) {
2155
+ return ctx[surface] ?? null;
2156
+ }
2157
+ function clearAllSurfaceContexts() {
2158
+ for (const key of Object.keys(ctx)) {
2159
+ delete ctx[key];
2160
+ }
2161
+ }
2162
+ let currentEmitter = null;
2163
+ function setLayoutCommandEmitter(emitter) {
2164
+ currentEmitter = emitter;
2165
+ }
2166
+ function emitLayoutSetRects(event) {
2167
+ currentEmitter == null ? void 0 : currentEmitter(event);
2168
+ }
2169
+ let currentDispatcher = null;
2170
+ function setLayoutCommandDispatcher(dispatcher) {
2171
+ currentDispatcher = dispatcher;
2172
+ }
2173
+ function emitLayoutCommand(event) {
2174
+ currentDispatcher == null ? void 0 : currentDispatcher(event);
2175
+ }
1474
2176
  export {
1475
2177
  AuthenticationError,
1476
2178
  AuthenticationErrorReason,
1477
2179
  B as BlockWrapperEvent,
1478
2180
  C as ContextProvideEvent,
1479
- a as ContextRequestEvent,
2181
+ j as ContextRequestEvent,
1480
2182
  CustomerServiceContext,
1481
- D as DEFAULT_GLOBAL_STYLES,
2183
+ k as DEFAULT_BREAKPOINTS,
2184
+ l as DEFAULT_GLOBAL_STYLES,
2185
+ DEFAULT_GRID,
2186
+ DEFAULT_NEW_BLOCK_HEIGHT,
1482
2187
  DISCOUNT_REJECTION_REASONS,
2188
+ GRID_V1_ENGINE_ID,
2189
+ L as LAYOUT_SCOPE_ATTR,
1483
2190
  LoginServiceContext,
1484
2191
  OrdersServiceContext,
2192
+ P as PAGE_ROOT_SLOT,
1485
2193
  ProductServiceContext,
1486
2194
  RouterServiceContext,
1487
2195
  S as SelectedBlockContext,
@@ -1489,17 +2197,27 @@ export {
1489
2197
  StateContext,
1490
2198
  SubscriptionServiceContext,
1491
2199
  T as ThemeStateContext,
1492
- b as TranslationContext,
1493
- W as WorkflowServiceContext,
1494
- e as attachEmptyTracking,
1495
- f as backfillInstanceDefaults,
2200
+ m as TranslationContext,
2201
+ WorkflowServiceContext,
2202
+ n as attachEmptyTracking,
2203
+ o as backfillInstanceDefaults,
2204
+ p as buildGridLayout,
2205
+ q as buildLayoutCss,
2206
+ canvasMode,
2207
+ clampRect,
2208
+ t as classifyRowDividers,
2209
+ clearAllSurfaceContexts,
2210
+ clearLayoutModeAdapter,
2211
+ compactItems,
2212
+ v as compactLayoutDocument,
1496
2213
  w as computed,
1497
- g as createBlockInstance,
1498
- h as createBlockInstanceFromJSON,
1499
- i as createBlockInstanceFromObject,
1500
- j as createCeRenderer,
2214
+ createBlockInstance,
2215
+ x as createBlockInstanceFromJSON,
2216
+ y as createBlockInstanceFromObject,
2217
+ z as createCeRenderer,
1501
2218
  createContext,
1502
2219
  createCustomerService,
2220
+ A as createDefaultLayoutDocument,
1503
2221
  createMockOrdersAdapter,
1504
2222
  createMockProductAdapter,
1505
2223
  createMockRouterService,
@@ -1508,33 +2226,55 @@ export {
1508
2226
  createOrdersService,
1509
2227
  createProductService,
1510
2228
  createRouterService,
1511
- k as createSelectedBlock,
2229
+ F as createSelectedBlock,
1512
2230
  createState,
1513
2231
  createSubscriptionService,
1514
- l as createThemeState,
1515
- m as createTranslationService,
1516
- n as createWorkflowApiAdapter,
1517
- o as createWorkflowService,
1518
- p as defineBlock,
1519
- q as defineBlockRuntime,
2232
+ H as createThemeState,
2233
+ I as createTranslationService,
2234
+ createWorkflowApiAdapter,
2235
+ createWorkflowService,
2236
+ defineBlock,
2237
+ J as defineBlockRuntime,
2238
+ K as deriveLayout,
1520
2239
  E as effect,
1521
- s as getDefaultBlockForAction,
1522
- t as getDefinedBlocks,
1523
- v as hasDefaultBlockForAction,
1524
- x as hasRenderedContent,
1525
- y as indexOverrides,
1526
- z as injectContext,
1527
- A as isEditorPreview,
1528
- F as isStubDefinition,
2240
+ emitLayoutCommand,
2241
+ emitLayoutSetRects,
2242
+ M as expandFillLayoutDocument,
2243
+ findFreeRect,
2244
+ getActiveSurfaceContext,
2245
+ getDefaultBlockForAction,
2246
+ getDefinedBlocks,
2247
+ getLayoutModeAdapter,
2248
+ gridV1Engine,
2249
+ hasDefaultBlockForAction,
2250
+ N as hasRenderedContent,
2251
+ O as indexOverrides,
2252
+ Q as injectContext,
2253
+ insertRectRelative,
2254
+ R as isEditorPreview,
2255
+ U as isStubDefinition,
2256
+ V as layoutScopeSelector,
2257
+ W as layoutSystemEnabled,
1529
2258
  loadBlockRegistry,
1530
2259
  loginService,
1531
- G as onRegisterBlock,
1532
- H as provideContext,
2260
+ X as onRegisterBlock,
2261
+ Y as projectToCss,
2262
+ p2 as projectToGridStack,
2263
+ Z as provideContext,
2264
+ _ as readingOrder,
2265
+ $ as reconcileLayout,
2266
+ a0 as rectsOverlap,
1533
2267
  registerBlock,
1534
- I as serializeBlocks,
2268
+ registerLayoutModeAdapter,
2269
+ a1 as resolveLayout,
2270
+ a2 as serializeBlocks,
2271
+ setActiveSurfaceContext,
2272
+ setLayoutCommandDispatcher,
2273
+ setLayoutCommandEmitter,
2274
+ a3 as setLayoutSystemEnabled,
1535
2275
  d as signal,
1536
- J as subscribeContext,
1537
- K as untracked,
2276
+ subscribeContext,
2277
+ a4 as untracked,
1538
2278
  waitForDevBlocksUrl,
1539
- L as withWrapper
2279
+ a5 as withWrapper
1540
2280
  };