@juo/blocks 1.12.0-alpha.0 → 1.12.0-alpha.2

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 (114) hide show
  1. package/dist/{ExtensionRoot-9XfhG8YM.js → ExtensionRoot-peABLAZZ.js} +15 -3
  2. package/dist/block-B6s9jL7l.js +966 -0
  3. package/dist/block.d.ts +50 -0
  4. package/dist/block.d.ts.map +1 -1
  5. package/dist/block.devtools.test.d.ts +2 -0
  6. package/dist/block.devtools.test.d.ts.map +1 -0
  7. package/dist/{bridge-w5KQ-czl.js → bridge-r7Yk8fjY.js} +34 -25
  8. package/dist/context.d.ts.map +1 -1
  9. package/dist/context.devtools.test.d.ts +2 -0
  10. package/dist/context.devtools.test.d.ts.map +1 -0
  11. package/dist/core.js +857 -149
  12. package/dist/devtools/env.d.ts +3 -0
  13. package/dist/devtools/env.d.ts.map +1 -0
  14. package/dist/devtools/hook.d.ts +35 -0
  15. package/dist/devtools/hook.d.ts.map +1 -0
  16. package/dist/devtools/index.d.ts +4 -0
  17. package/dist/devtools/index.d.ts.map +1 -0
  18. package/dist/devtools/protocol.d.ts +91 -0
  19. package/dist/devtools/protocol.d.ts.map +1 -0
  20. package/dist/devtools.js +44 -0
  21. package/dist/editor/bridge.d.ts +7 -0
  22. package/dist/editor/bridge.d.ts.map +1 -1
  23. package/dist/editor/components.d.ts.map +1 -1
  24. package/dist/editor/main.d.ts +6 -1
  25. package/dist/editor/main.d.ts.map +1 -1
  26. package/dist/editor/main.test.d.ts +2 -0
  27. package/dist/editor/main.test.d.ts.map +1 -0
  28. package/dist/editor/messages.d.ts +13 -2
  29. package/dist/editor/messages.d.ts.map +1 -1
  30. package/dist/editor/messages.test.d.ts +2 -0
  31. package/dist/editor/messages.test.d.ts.map +1 -0
  32. package/dist/editor/overlays.d.ts +14 -0
  33. package/dist/editor/overlays.d.ts.map +1 -0
  34. package/dist/editor/overlays.test.d.ts +2 -0
  35. package/dist/editor/overlays.test.d.ts.map +1 -0
  36. package/dist/editor.js +82 -47
  37. package/dist/{juo-workflow-CkyZRq60.js → juo-workflow-DY4rd256.js} +74 -873
  38. package/dist/main.d.ts +3 -1
  39. package/dist/main.d.ts.map +1 -1
  40. package/dist/overlay-wrapper.d.ts +69 -0
  41. package/dist/overlay-wrapper.d.ts.map +1 -0
  42. package/dist/overlay-wrapper.test.d.ts +2 -0
  43. package/dist/overlay-wrapper.test.d.ts.map +1 -0
  44. package/dist/overlays/OverlayService.d.ts +34 -0
  45. package/dist/overlays/OverlayService.d.ts.map +1 -0
  46. package/dist/overlays/OverlayService.test.d.ts +2 -0
  47. package/dist/overlays/OverlayService.test.d.ts.map +1 -0
  48. package/dist/preact.js +1 -1
  49. package/dist/react.js +1 -1
  50. package/dist/registry.devtools.test.d.ts +2 -0
  51. package/dist/registry.devtools.test.d.ts.map +1 -0
  52. package/dist/services/index.d.ts +2 -0
  53. package/dist/services/index.d.ts.map +1 -1
  54. package/dist/services/orders/adapter.d.ts +2 -1
  55. package/dist/services/orders/adapter.d.ts.map +1 -1
  56. package/dist/services/orders/types.d.ts +8 -0
  57. package/dist/services/orders/types.d.ts.map +1 -1
  58. package/dist/services/product/adapter.d.ts +23 -1
  59. package/dist/services/product/adapter.d.ts.map +1 -1
  60. package/dist/services/product/adapter.test.d.ts +2 -0
  61. package/dist/services/product/adapter.test.d.ts.map +1 -0
  62. package/dist/services/product/productService.d.ts.map +1 -1
  63. package/dist/services/product/types.d.ts +66 -0
  64. package/dist/services/product/types.d.ts.map +1 -1
  65. package/dist/services/schedules/adapter.d.ts +4 -1
  66. package/dist/services/schedules/adapter.d.ts.map +1 -1
  67. package/dist/services/schedules/adapter.test.d.ts +2 -0
  68. package/dist/services/schedules/adapter.test.d.ts.map +1 -0
  69. package/dist/services/schedules/index.d.ts +3 -3
  70. package/dist/services/schedules/index.d.ts.map +1 -1
  71. package/dist/services/schedules/schedulesService.d.ts +4 -3
  72. package/dist/services/schedules/schedulesService.d.ts.map +1 -1
  73. package/dist/services/schedules/schedulesService.test.d.ts +2 -0
  74. package/dist/services/schedules/schedulesService.test.d.ts.map +1 -0
  75. package/dist/services/schedules/types.d.ts +66 -12
  76. package/dist/services/schedules/types.d.ts.map +1 -1
  77. package/dist/services/settings/index.d.ts +3 -0
  78. package/dist/services/settings/index.d.ts.map +1 -0
  79. package/dist/services/settings/settingsService.d.ts +7 -0
  80. package/dist/services/settings/settingsService.d.ts.map +1 -0
  81. package/dist/services/settings/settingsService.test.d.ts +2 -0
  82. package/dist/services/settings/settingsService.test.d.ts.map +1 -0
  83. package/dist/services/settings/types.d.ts +35 -0
  84. package/dist/services/settings/types.d.ts.map +1 -0
  85. package/dist/services/shop/index.d.ts +3 -0
  86. package/dist/services/shop/index.d.ts.map +1 -0
  87. package/dist/services/shop/shopService.d.ts +12 -0
  88. package/dist/services/shop/shopService.d.ts.map +1 -0
  89. package/dist/services/shop/shopService.test.d.ts +2 -0
  90. package/dist/services/shop/shopService.test.d.ts.map +1 -0
  91. package/dist/services/shop/types.d.ts +7 -0
  92. package/dist/services/shop/types.d.ts.map +1 -0
  93. package/dist/services/subscription/adapter.d.ts +38 -1
  94. package/dist/services/subscription/adapter.d.ts.map +1 -1
  95. package/dist/services/subscription/adapter.test.d.ts +2 -0
  96. package/dist/services/subscription/adapter.test.d.ts.map +1 -0
  97. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  98. package/dist/services/subscription/types.d.ts +200 -1
  99. package/dist/services/subscription/types.d.ts.map +1 -1
  100. package/dist/services/subscription/types.test.d.ts +2 -0
  101. package/dist/services/subscription/types.test.d.ts.map +1 -0
  102. package/dist/theme-state.d.ts +2 -1
  103. package/dist/theme-state.d.ts.map +1 -1
  104. package/dist/theme-state.params.test.d.ts +2 -0
  105. package/dist/theme-state.params.test.d.ts.map +1 -0
  106. package/dist/theme-state.translations.test.d.ts +2 -0
  107. package/dist/theme-state.translations.test.d.ts.map +1 -0
  108. package/dist/vue/block.d.ts.map +1 -1
  109. package/dist/vue.js +25 -4
  110. package/dist/web-components/ExtensionRoot.d.ts +1 -0
  111. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  112. package/dist/web-components-editor.js +4 -3
  113. package/dist/web-components-runtime.js +3 -2
  114. package/package.json +5 -1
package/dist/core.js CHANGED
@@ -1,8 +1,9 @@
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-CkyZRq60.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-CkyZRq60.js";
4
+ import { e as createContext, d, k as w, l as defineBlock, g as createBlockInstance, h as getDefinedBlocks, r as registerBlock, E, u } from "./block-B6s9jL7l.js";
5
+ import { B, m, p, S, q, _, t, b, v, f, x, y, z, A, D, i, F, a, o, G, j, H, s, n, w as w2 } from "./block-B6s9jL7l.js";
6
+ import { D as D2, a as a2, T, W, c, b as b2, d as d2, e, g, h, i as i2 } from "./juo-workflow-DY4rd256.js";
6
7
  import { reportBlockWarning, reportBlockError } from "./observability.js";
7
8
  function createState() {
8
9
  const discountCode = d(null);
@@ -72,6 +73,111 @@ function createState() {
72
73
  };
73
74
  }
74
75
  const StateContext = createContext("state");
76
+ const OVERLAY_WRAPPER_SCHEMA = {
77
+ type: "object",
78
+ properties: {
79
+ props: {
80
+ type: "object",
81
+ properties: {
82
+ layout: {
83
+ type: "string",
84
+ enum: ["modal", "sidebar"]
85
+ },
86
+ canAbort: {
87
+ type: "boolean"
88
+ }
89
+ },
90
+ required: ["layout"],
91
+ additionalProperties: false
92
+ },
93
+ slots: {
94
+ type: "object",
95
+ properties: {
96
+ content: {}
97
+ },
98
+ additionalProperties: false
99
+ }
100
+ },
101
+ required: ["props", "slots"],
102
+ additionalProperties: false
103
+ };
104
+ function defineOverlayWrapper(opts) {
105
+ const layout = opts.layout ?? "sidebar";
106
+ const canAbort = opts.canAbort ?? true;
107
+ return defineBlock(opts.name, {
108
+ displayName: opts.title,
109
+ group: "internal",
110
+ schema: OVERLAY_WRAPPER_SCHEMA,
111
+ initialValue: () => ({
112
+ props: { layout, canAbort },
113
+ slots: {
114
+ content: [createBlockInstance(opts.content)]
115
+ }
116
+ }),
117
+ renderer: () => null
118
+ });
119
+ }
120
+ const OVERLAY_PREFIX$1 = "overlay:";
121
+ function callInitialValue(block) {
122
+ if (typeof block.initialValue !== "function") return block.initialValue;
123
+ try {
124
+ return block.initialValue();
125
+ } catch (error) {
126
+ console.warn(
127
+ `[overlays] initialValue() threw for "${block.name}"; its content block will not be hidden from the palette.`,
128
+ error
129
+ );
130
+ return void 0;
131
+ }
132
+ }
133
+ function buildOverlayRegistry(blocks) {
134
+ var _a, _b;
135
+ const registry = {};
136
+ for (const block of blocks) {
137
+ if (!block.name.startsWith(OVERLAY_PREFIX$1)) continue;
138
+ const id = block.name.slice(OVERLAY_PREFIX$1.length);
139
+ const initial = callInitialValue(block);
140
+ const first = (_b = (_a = initial == null ? void 0 : initial.slots) == null ? void 0 : _a.content) == null ? void 0 : _b[0];
141
+ const contentBlock = typeof (first == null ? void 0 : first.type) === "string" ? first.type : "";
142
+ registry[id] = {
143
+ block: block.name,
144
+ title: block.displayName ?? id,
145
+ contentBlock
146
+ };
147
+ }
148
+ return registry;
149
+ }
150
+ const OVERLAY_PREFIX = "overlay:";
151
+ const OverlayServiceContext = createContext("services/overlay");
152
+ function createOverlayService(themeState, options = {}) {
153
+ const getBlocks = options.getBlocks ?? getDefinedBlocks;
154
+ const current = w(() => {
155
+ const root = themeState.overlay.blocks.value[0];
156
+ const type = root == null ? void 0 : root.type;
157
+ if (typeof type !== "string" || !type.startsWith(OVERLAY_PREFIX)) {
158
+ return null;
159
+ }
160
+ const props = root.props ?? {};
161
+ return {
162
+ name: type,
163
+ // Defaults mirror defineOverlayWrapper's seeding in overlay-wrapper.ts — keep in sync.
164
+ layout: props.layout ?? "sidebar",
165
+ canAbort: Boolean(props.canAbort ?? true)
166
+ };
167
+ });
168
+ return {
169
+ getEditableOverlays() {
170
+ return buildOverlayRegistry(getBlocks());
171
+ },
172
+ open(name, params) {
173
+ void themeState.resolve("overlay", name, params);
174
+ },
175
+ close() {
176
+ themeState.overlay.blocks.value = [];
177
+ },
178
+ current
179
+ };
180
+ }
75
181
  function isLocalhostOrigin(origin) {
76
182
  try {
77
183
  const url = new URL(origin);
@@ -132,7 +238,7 @@ async function loadBlockRegistry(options = {}) {
132
238
  if ("registerBlocks" in module && typeof module.registerBlocks === "function") {
133
239
  module.registerBlocks();
134
240
  } else {
135
- Object.entries(module).forEach(([_, item]) => {
241
+ Object.entries(module).forEach(([_2, item]) => {
136
242
  if (typeof item === "object" && item != null) {
137
243
  registerBlock(item);
138
244
  }
@@ -206,7 +312,7 @@ const PARAMS = {
206
312
  function uuid() {
207
313
  return ("10000000-1000-4000-8000" + -1e11).replace(
208
314
  /[018]/g,
209
- (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
315
+ (c2) => (c2 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c2 / 4).toString(16)
210
316
  );
211
317
  }
212
318
  function createMockLoginAdapter() {
@@ -576,10 +682,56 @@ function createLoginService(init) {
576
682
  }
577
683
  const LoginServiceContext = createContext("services/login");
578
684
  function createMockOrdersAdapter() {
685
+ const mockOrders = [
686
+ {
687
+ id: "10001",
688
+ createdAt: "2024-10-15T09:30:00Z",
689
+ placedAt: "2024-10-15T09:30:00Z",
690
+ currencyCode: "USD",
691
+ totalPrice: 89.97,
692
+ financialStatus: "PAID",
693
+ fulfillmentStatus: "FULFILLED",
694
+ lines: [
695
+ {
696
+ id: "line_1",
697
+ title: "Monthly Coffee Subscription",
698
+ quantity: 1,
699
+ variantImage: null,
700
+ customAttributes: [
701
+ { key: "roast", value: "dark" },
702
+ { key: "size", value: "1lb" }
703
+ ]
704
+ }
705
+ ],
706
+ customAttributes: [
707
+ { key: "order_type", value: "subscription_renewal" },
708
+ { key: "gift_wrap", value: "false" }
709
+ ]
710
+ },
711
+ {
712
+ id: "10002",
713
+ createdAt: "2024-09-20T14:15:00Z",
714
+ placedAt: "2024-09-20T14:15:00Z",
715
+ currencyCode: "USD",
716
+ totalPrice: 45.99,
717
+ financialStatus: "PAID",
718
+ fulfillmentStatus: "PARTIALLY_FULFILLED",
719
+ lines: [
720
+ {
721
+ id: "line_2",
722
+ title: "Premium Tea Set",
723
+ quantity: 2,
724
+ variantImage: null,
725
+ customAttributes: []
726
+ }
727
+ ],
728
+ customAttributes: []
729
+ }
730
+ ];
579
731
  return {
580
732
  async getOrders() {
581
733
  return {
582
- items: [],
734
+ items: mockOrders,
583
735
  pageInfo: {
584
736
  hasNextPage: false,
585
737
  hasPrevPage: false,
@@ -743,6 +895,18 @@ function createMockProductAdapter() {
743
895
  );
744
896
  return product == null ? null : processProduct(product);
745
897
  },
898
+ async getProductsByIds() {
899
+ return [];
900
+ },
901
+ async getBoxVariants() {
902
+ return [];
903
+ },
904
+ async getAvailableProducts() {
905
+ return [];
906
+ },
907
+ async getBox() {
908
+ return null;
909
+ },
746
910
  async search(opts) {
747
911
  await new Promise((resolve) => setTimeout(resolve, 100));
748
912
  let filteredProducts = [...products];
@@ -880,6 +1044,85 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
880
1044
  }
881
1045
  };
882
1046
  }
1047
+ },
1048
+ async getProductsByIds({ ids }) {
1049
+ const params = new URLSearchParams();
1050
+ for (const id of ids) params.append("ids", id);
1051
+ const res = await fetcher(`/customer/products/by-ids?${params.toString()}`);
1052
+ if (!res.ok) return [];
1053
+ const data = await res.json();
1054
+ return (data ?? []).map((p2) => ({
1055
+ id: p2.id,
1056
+ title: p2.title ?? "",
1057
+ featuredImage: p2.featuredImage ? { url: p2.featuredImage.url, altText: p2.featuredImage.altText } : null,
1058
+ hasOnlyDefaultVariant: true,
1059
+ collections: []
1060
+ }));
1061
+ },
1062
+ async getBoxVariants({ ids, subscriptionId }) {
1063
+ const params = new URLSearchParams();
1064
+ for (const id of ids) params.append("ids", id);
1065
+ params.set("subscriptionId", subscriptionId);
1066
+ const res = await fetcher(`/customer/products/variants?${params.toString()}`);
1067
+ if (!res.ok) return [];
1068
+ const data = await res.json();
1069
+ return (data ?? []).map((p2) => {
1070
+ var _a;
1071
+ return {
1072
+ id: p2.id,
1073
+ title: p2.title,
1074
+ description: p2.description ?? "",
1075
+ featuredImage: p2.featuredImage,
1076
+ hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1077
+ variants: (p2.variants ?? []).map((v2) => ({
1078
+ id: v2.id,
1079
+ availableForSale: v2.availableForSale,
1080
+ title: v2.title,
1081
+ currentPrice: v2.currentPrice,
1082
+ basePrice: v2.basePrice,
1083
+ image: v2.image,
1084
+ recurring: v2.recurring
1085
+ }))
1086
+ };
1087
+ });
1088
+ },
1089
+ async getAvailableProducts({ subscriptionId, lineId, q: q2, mode, action, pagination }) {
1090
+ const params = new URLSearchParams();
1091
+ params.set("action", action);
1092
+ if (q2) params.set("q", q2);
1093
+ if (mode) params.set("mode", mode);
1094
+ if (pagination && "after" in pagination) params.set("after", pagination.after);
1095
+ if (pagination && "before" in pagination) params.set("before", pagination.before);
1096
+ const res = await fetcher(
1097
+ `/customer/subscriptions/${subscriptionId}/lines/${lineId}/available-products?${params.toString()}`
1098
+ );
1099
+ if (!res.ok) return [];
1100
+ const data = await res.json();
1101
+ return (data ?? []).map((p2) => {
1102
+ var _a;
1103
+ return {
1104
+ id: p2.id,
1105
+ title: p2.title,
1106
+ description: p2.description ?? "",
1107
+ featuredImage: p2.featuredImage,
1108
+ hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1109
+ variants: (p2.variants ?? []).map((v2) => ({
1110
+ id: v2.id,
1111
+ availableForSale: v2.availableForSale,
1112
+ title: v2.title,
1113
+ currentPrice: v2.currentPrice,
1114
+ basePrice: v2.basePrice,
1115
+ image: v2.image,
1116
+ recurring: v2.recurring
1117
+ }))
1118
+ };
1119
+ });
1120
+ },
1121
+ async getBox({ id }) {
1122
+ const res = await fetcher(`/customer/boxes/${id}`);
1123
+ if (!res.ok) return null;
1124
+ const data = await res.json();
1125
+ return { id, ...data };
883
1126
  }
884
1127
  };
885
1128
  }
@@ -894,7 +1137,11 @@ function createProductService(adapter) {
894
1137
  },
895
1138
  async search(opts) {
896
1139
  return adapter.search(opts);
897
- }
1140
+ },
1141
+ getProductsByIds: (ids) => adapter.getProductsByIds({ ids }),
1142
+ getBoxVariants: (ids, subscriptionId) => adapter.getBoxVariants({ ids, subscriptionId }),
1143
+ getAvailableProducts: (params) => adapter.getAvailableProducts(params),
1144
+ getBox: (id) => adapter.getBox({ id })
898
1145
  };
899
1146
  }
900
1147
  function routeNameTableFromPages(pages) {
@@ -949,66 +1196,135 @@ function createMockRouterService() {
949
1196
  }).routerService;
950
1197
  }
951
1198
  function futureDateStr(daysFromNow) {
952
- const d2 = /* @__PURE__ */ new Date();
953
- d2.setDate(d2.getDate() + daysFromNow);
954
- return d2.toISOString().split("T")[0] ?? "";
1199
+ const d3 = /* @__PURE__ */ new Date();
1200
+ d3.setDate(d3.getDate() + daysFromNow);
1201
+ return d3.toISOString().split("T")[0] ?? "";
955
1202
  }
956
1203
  function createMockSchedulesAdapter() {
957
1204
  let orders = [
958
1205
  {
959
- id: "schedule-order-1",
1206
+ id: "sched_1",
1207
+ customerId: "customer_1",
960
1208
  subscriptionId: "sub_1",
1209
+ date: "2026-05-22T12:00:00Z",
1210
+ skipped: false,
1211
+ currencyCode: "USD",
1212
+ subtotal: 2999,
1213
+ deliveryPrice: 500,
1214
+ cycleIndex: 4,
961
1215
  deliveryDate: futureDateStr(7),
1216
+ status: "scheduled",
962
1217
  items: [
963
1218
  {
964
- id: "si-1",
965
- productId: "p-beauty-1",
966
- variantId: "v-beauty-1",
967
- quantity: 1,
1219
+ id: "sched_item_1",
968
1220
  title: "Rose Face Serum",
969
- imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200"
1221
+ subtitle: null,
1222
+ imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
1223
+ variantId: "variant_1",
1224
+ quantity: 1,
1225
+ price: 2999,
1226
+ totalPrice: 2999,
1227
+ variantImage: null,
1228
+ variantAvailableForSale: true,
1229
+ subscriptionId: "sub_1",
1230
+ subscriptionLineId: "item_1",
1231
+ productId: "product_1",
1232
+ parentProductId: null,
1233
+ parentLineId: null,
1234
+ isVirtual: false,
1235
+ isUpsell: false,
1236
+ isOneTime: false,
1237
+ customAttributes: []
970
1238
  },
971
1239
  {
972
- id: "si-2",
973
- productId: "p-beauty-2",
974
- variantId: "v-beauty-2",
975
- quantity: 1,
1240
+ id: "sched_item_2",
976
1241
  title: "Vitamin C Moisturizer",
977
- imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200"
1242
+ subtitle: null,
1243
+ imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
1244
+ variantId: "variant_2",
1245
+ quantity: 1,
1246
+ price: 2999,
1247
+ totalPrice: 2999,
1248
+ variantImage: null,
1249
+ variantAvailableForSale: true,
1250
+ subscriptionId: "sub_1",
1251
+ subscriptionLineId: "item_2",
1252
+ productId: "product_2",
1253
+ parentProductId: null,
1254
+ parentLineId: null,
1255
+ isVirtual: false,
1256
+ isUpsell: false,
1257
+ isOneTime: false,
1258
+ customAttributes: []
978
1259
  }
979
1260
  ],
980
- status: "scheduled"
1261
+ discounts: []
981
1262
  },
982
1263
  {
983
- id: "schedule-order-2",
1264
+ id: "sched_2",
1265
+ customerId: "customer_1",
984
1266
  subscriptionId: "sub_1",
985
- deliveryDate: futureDateStr(35),
1267
+ date: "2026-05-22T12:00:00Z",
1268
+ skipped: false,
1269
+ currencyCode: "USD",
1270
+ subtotal: 2999,
1271
+ deliveryPrice: 500,
1272
+ cycleIndex: 4,
1273
+ deliveryDate: futureDateStr(7),
1274
+ status: "scheduled",
986
1275
  items: [
987
1276
  {
988
- id: "si-3",
989
- productId: "p-beauty-1",
990
- variantId: "v-beauty-1",
991
- quantity: 1,
1277
+ id: "sched_item_3",
992
1278
  title: "Rose Face Serum",
993
- imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200"
1279
+ subtitle: null,
1280
+ imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
1281
+ variantId: "variant_1",
1282
+ quantity: 1,
1283
+ price: 2999,
1284
+ totalPrice: 2999,
1285
+ variantImage: null,
1286
+ variantAvailableForSale: true,
1287
+ subscriptionId: "sub_1",
1288
+ subscriptionLineId: "item_1",
1289
+ productId: "product_1",
1290
+ parentProductId: null,
1291
+ parentLineId: null,
1292
+ isVirtual: false,
1293
+ isUpsell: false,
1294
+ isOneTime: false,
1295
+ customAttributes: []
994
1296
  },
995
1297
  {
996
- id: "si-4",
997
- productId: "p-beauty-3",
998
- variantId: "v-beauty-3",
999
- quantity: 1,
1298
+ id: "sched_item_4",
1000
1299
  title: "Hyaluronic Acid Serum",
1001
- imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200"
1300
+ subtitle: null,
1301
+ imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200",
1302
+ variantId: "variant_3",
1303
+ quantity: 1,
1304
+ price: 2999,
1305
+ totalPrice: 2999,
1306
+ variantImage: null,
1307
+ variantAvailableForSale: true,
1308
+ subscriptionId: "sub_1",
1309
+ subscriptionLineId: "item_3",
1310
+ productId: "product_3",
1311
+ parentProductId: null,
1312
+ parentLineId: null,
1313
+ isVirtual: false,
1314
+ isUpsell: false,
1315
+ isOneTime: false,
1316
+ customAttributes: []
1002
1317
  }
1003
1318
  ],
1004
- status: "scheduled"
1319
+ discounts: []
1005
1320
  }
1006
1321
  ];
1007
1322
  let adjustments = [];
1008
1323
  return {
1009
- async getUpcomingOrders(count) {
1324
+ async getUpcomingOrders(params) {
1010
1325
  await new Promise((r) => setTimeout(r, 200));
1011
- return { _tag: "Success", data: orders.slice(0, count) };
1326
+ const filtered = params.subscriptionId ? orders.filter((o2) => o2.subscriptionId === params.subscriptionId) : orders;
1327
+ return { _tag: "Success", data: filtered.slice(0, params.count) };
1012
1328
  },
1013
1329
  async getAdjustments() {
1014
1330
  await new Promise((r) => setTimeout(r, 200));
@@ -1051,16 +1367,18 @@ function createMockSchedulesAdapter() {
1051
1367
  },
1052
1368
  async removeAdjustment({ adjustmentId }) {
1053
1369
  await new Promise((r) => setTimeout(r, 200));
1054
- adjustments = adjustments.filter((a2) => a2.id !== adjustmentId);
1370
+ adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
1055
1371
  return { _tag: "Success", data: void 0 };
1056
1372
  }
1057
1373
  };
1058
1374
  }
1059
1375
  function createApiSchedulesAdapter(fetcher) {
1060
1376
  return {
1061
- async getUpcomingOrders(count) {
1377
+ async getUpcomingOrders({ count, subscriptionId }) {
1062
1378
  try {
1063
- const res = await fetcher(`/customer/v1/schedules/?count=${count}`);
1379
+ const params = new URLSearchParams({ count: String(count) });
1380
+ if (subscriptionId) params.set("query", `id:"${subscriptionId}"`);
1381
+ const res = await fetcher(`/customer/v1/schedules/?${params.toString()}`);
1064
1382
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1065
1383
  const data = await res.json();
1066
1384
  return { _tag: "Success", data: data.orders };
@@ -1073,11 +1391,11 @@ function createApiSchedulesAdapter(fetcher) {
1073
1391
  const res = await fetcher(`/customer/v1/schedules/adjustments`);
1074
1392
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1075
1393
  const data = await res.json();
1076
- const adjustments = data.data.map((a2) => ({
1077
- id: a2.id,
1078
- subscriptionId: a2.subscriptionId ?? "",
1079
- type: a2.type === "CHANGE_DATE" ? "date_change" : "skip",
1080
- newDate: a2.newDate
1394
+ const adjustments = data.data.map((a3) => ({
1395
+ id: a3.id,
1396
+ subscriptionId: a3.subscriptionId ?? "",
1397
+ type: a3.type === "CHANGE_DATE" ? "date_change" : "skip",
1398
+ newDate: a3.newDate
1081
1399
  }));
1082
1400
  return { _tag: "Success", data: adjustments };
1083
1401
  } catch (e2) {
@@ -1146,53 +1464,135 @@ function createApiSchedulesAdapter(fetcher) {
1146
1464
  }
1147
1465
  const SchedulesServiceContext = createContext("services/schedules");
1148
1466
  function createSchedulesService(adapter, opts) {
1149
- const upcoming = d([]);
1150
- async function refreshUpcoming() {
1151
- const count = Math.max(upcoming.value.length, 3);
1152
- const result = await adapter.getUpcomingOrders(count);
1467
+ const current = d(null);
1468
+ const currentLoading = d(false);
1469
+ const hasPendingBilling = (opts == null ? void 0 : opts.hasPendingBilling) ?? d(false);
1470
+ let reloadToken = 0;
1471
+ async function getUpcomingOrder() {
1472
+ const result = await adapter.getUpcomingOrders({ count: 1 });
1473
+ if (result._tag === "Failure") return result;
1474
+ return { _tag: "Success", data: result.data[0] ?? null };
1475
+ }
1476
+ async function getUpcomingOrders(count) {
1477
+ return adapter.getUpcomingOrders({ count });
1478
+ }
1479
+ async function reloadCurrent(subscriptionId) {
1480
+ var _a;
1481
+ const token = ++reloadToken;
1482
+ currentLoading.value = true;
1483
+ const count = Math.max(((_a = current.value) == null ? void 0 : _a.length) ?? 0, 3);
1484
+ const result = await adapter.getUpcomingOrders({
1485
+ count,
1486
+ subscriptionId
1487
+ });
1488
+ if (token !== reloadToken) return;
1489
+ currentLoading.value = false;
1153
1490
  if (result._tag === "Success") {
1154
- upcoming.value = result.data;
1491
+ current.value = result.data;
1155
1492
  }
1156
1493
  }
1157
1494
  return {
1158
- upcoming,
1159
- hasPendingBilling: opts.hasPendingBilling,
1160
- async getUpcomingOrder() {
1161
- const result = await adapter.getUpcomingOrders(1);
1162
- if (result._tag === "Failure") return result;
1163
- upcoming.value = result.data;
1164
- return { _tag: "Success", data: result.data[0] ?? null };
1165
- },
1166
- async getUpcomingOrders(count) {
1167
- const result = await adapter.getUpcomingOrders(count);
1168
- if (result._tag === "Success") {
1169
- upcoming.value = result.data;
1170
- }
1171
- return result;
1172
- },
1495
+ current,
1496
+ currentLoading,
1497
+ hasPendingBilling,
1498
+ getUpcomingOrder,
1499
+ getUpcomingOrders,
1173
1500
  async getAdjustments() {
1174
1501
  return adapter.getAdjustments();
1175
1502
  },
1176
1503
  async skipOrder(params) {
1177
1504
  const result = await adapter.skipOrder(params);
1178
1505
  if (result._tag === "Success") {
1179
- await refreshUpcoming();
1506
+ await reloadCurrent(params.subscriptionId);
1180
1507
  }
1181
1508
  return result;
1182
1509
  },
1183
1510
  async changeDateAdjustment(params) {
1184
1511
  const result = await adapter.changeDateAdjustment(params);
1185
1512
  if (result._tag === "Success") {
1186
- await refreshUpcoming();
1513
+ await reloadCurrent(params.subscriptionId);
1187
1514
  }
1188
1515
  return result;
1189
1516
  },
1190
1517
  async removeAdjustment(params) {
1191
1518
  return adapter.removeAdjustment(params);
1519
+ },
1520
+ reloadCurrent
1521
+ };
1522
+ }
1523
+ const SettingsServiceContext = createContext("services/settings");
1524
+ function createSettingsService(initial = {}) {
1525
+ const current = d(initial);
1526
+ return {
1527
+ current,
1528
+ get(key) {
1529
+ return current.value[key];
1192
1530
  }
1193
1531
  };
1194
1532
  }
1533
+ function createShopService(options) {
1534
+ const contactEmail = d(options.getContactEmail());
1535
+ const service = { contactEmail };
1536
+ return service;
1537
+ }
1538
+ const ShopServiceContext = createContext("services/shop");
1195
1539
  function createMockSubscriptionAdapter(options = {}) {
1540
+ const richBase = (id, itemId, renewalId) => ({
1541
+ id,
1542
+ customerId: "customer_1",
1543
+ items: [
1544
+ {
1545
+ id: itemId,
1546
+ productId: "product_1",
1547
+ variantId: "variant_1",
1548
+ quantity: 2,
1549
+ price: { amount: "29.99", currencyCode: "USD" },
1550
+ nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1551
+ isUpsell: false,
1552
+ isVirtual: false,
1553
+ nextBillingDate: "2025-11-15T00:00:00Z",
1554
+ currentPrice: { amount: "29.99", currencyCode: "USD" },
1555
+ lineDiscountedPrice: { amount: "26.99", currencyCode: "USD" },
1556
+ variantAvailableForSale: true
1557
+ }
1558
+ ],
1559
+ discounts: [
1560
+ {
1561
+ id: "discount_1",
1562
+ type: "percentage",
1563
+ value: 10,
1564
+ code: "SAVE10",
1565
+ description: "10% off subscription"
1566
+ }
1567
+ ],
1568
+ status: "active",
1569
+ nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1570
+ frequency: "1 MONTH",
1571
+ createdAt: "2024-10-01T00:00:00Z",
1572
+ updatedAt: "2024-10-14T00:00:00Z",
1573
+ billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
1574
+ deliveryPolicy: {
1575
+ intervalCount: 1,
1576
+ interval: "MONTH",
1577
+ anchors: [{ day: 15, type: "MONTHDAY" }]
1578
+ },
1579
+ nextBillingDate: "2025-11-15T00:00:00Z",
1580
+ nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
1581
+ lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
1582
+ nextFulfillment: "2025-11-17T00:00:00Z",
1583
+ estimatedOrderDate: "2025-11-13T00:00:00Z",
1584
+ customerPaymentMethod: {
1585
+ id: "pm_1",
1586
+ instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
1587
+ active: true,
1588
+ isRecurring: true
1589
+ },
1590
+ requiredBillingCyclesLeft: 3,
1591
+ renewal: { id: renewalId, isInActiveProcessState: false },
1592
+ lastPaymentStatus: "succeeded",
1593
+ pausePeriod: null,
1594
+ isEditable: true
1595
+ });
1196
1596
  const mockSubscriptions = [
1197
1597
  {
1198
1598
  id: "sub_1",
@@ -1205,8 +1605,18 @@ function createMockSubscriptionAdapter(options = {}) {
1205
1605
  quantity: 2,
1206
1606
  price: { amount: "29.99", currencyCode: "USD" },
1207
1607
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1608
+ isUpsell: false,
1609
+ isVirtual: false,
1610
+ nextBillingDate: "2025-11-15T00:00:00Z",
1611
+ currentPrice: { amount: "29.99", currencyCode: "USD" },
1612
+ lineDiscountedPrice: { amount: "26.99", currencyCode: "USD" },
1613
+ variantAvailableForSale: true,
1208
1614
  billingPolicy: { intervalCount: 1, interval: "MONTH" },
1209
- deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
1615
+ deliveryPolicy: { intervalCount: 1, interval: "MONTH" },
1616
+ customAttributes: [
1617
+ { key: "roast_level", value: "medium" },
1618
+ { key: "grind_type", value: "whole_bean" }
1619
+ ]
1210
1620
  }
1211
1621
  ],
1212
1622
  discounts: [
@@ -1222,7 +1632,33 @@ function createMockSubscriptionAdapter(options = {}) {
1222
1632
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1223
1633
  frequency: "1 MONTH",
1224
1634
  createdAt: "2024-10-01T00:00:00Z",
1225
- updatedAt: "2024-10-14T00:00:00Z"
1635
+ updatedAt: "2024-10-14T00:00:00Z",
1636
+ billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
1637
+ deliveryPolicy: {
1638
+ intervalCount: 1,
1639
+ interval: "MONTH",
1640
+ anchors: [{ day: 15, type: "MONTHDAY" }]
1641
+ },
1642
+ nextBillingDate: "2025-11-15T00:00:00Z",
1643
+ nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
1644
+ lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
1645
+ nextFulfillment: "2025-11-17T00:00:00Z",
1646
+ estimatedOrderDate: "2025-11-13T00:00:00Z",
1647
+ customerPaymentMethod: {
1648
+ id: "pm_1",
1649
+ instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
1650
+ active: true,
1651
+ isRecurring: true
1652
+ },
1653
+ requiredBillingCyclesLeft: 3,
1654
+ renewal: { id: "ren_1", isInActiveProcessState: false },
1655
+ lastPaymentStatus: "succeeded",
1656
+ pausePeriod: null,
1657
+ isEditable: true,
1658
+ customAttributes: [
1659
+ { key: "subscription_tier", value: "premium" },
1660
+ { key: "gift_message", value: "Enjoy your coffee!" }
1661
+ ]
1226
1662
  },
1227
1663
  {
1228
1664
  id: "sub_2",
@@ -1236,7 +1672,8 @@ function createMockSubscriptionAdapter(options = {}) {
1236
1672
  price: { amount: "49.99", currencyCode: "USD" },
1237
1673
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
1238
1674
  billingPolicy: { intervalCount: 2, interval: "WEEK" },
1239
- deliveryPolicy: { intervalCount: 2, interval: "WEEK" }
1675
+ deliveryPolicy: { intervalCount: 2, interval: "WEEK" },
1676
+ customAttributes: []
1240
1677
  }
1241
1678
  ],
1242
1679
  discounts: [],
@@ -1244,7 +1681,32 @@ function createMockSubscriptionAdapter(options = {}) {
1244
1681
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
1245
1682
  frequency: "2 WEEK",
1246
1683
  createdAt: "2024-09-15T00:00:00Z",
1247
- updatedAt: "2024-10-10T00:00:00Z"
1684
+ updatedAt: "2024-10-10T00:00:00Z",
1685
+ customAttributes: []
1686
+ },
1687
+ // Per-status fixtures: groundwork for the deferred editor preview picker
1688
+ // (docs/superpowers/specs/2026-06-17-renewalsummary-parity-and-mock-groundwork-design.md §9).
1689
+ // Not consumed yet — the editor still seeds the active sub_1 via getDefaultSubscriptionId().
1690
+ {
1691
+ ...richBase("sub_paused", "item_paused", "ren_paused"),
1692
+ status: "paused",
1693
+ pausePeriod: { start: "2025-11-01T00:00:00Z", end: "2026-01-01T00:00:00Z" }
1694
+ },
1695
+ {
1696
+ ...richBase("sub_canceled", "item_canceled", "ren_canceled"),
1697
+ status: "canceled",
1698
+ pausePeriod: null
1699
+ },
1700
+ {
1701
+ ...richBase("sub_failed", "item_failed", "ren_failed"),
1702
+ status: "failed",
1703
+ lastPaymentStatus: "failed",
1704
+ pausePeriod: null
1705
+ },
1706
+ {
1707
+ ...richBase("sub_expired", "item_expired", "ren_expired"),
1708
+ status: "expired",
1709
+ pausePeriod: null
1248
1710
  }
1249
1711
  ];
1250
1712
  const mockUpsellProducts = [
@@ -1314,6 +1776,17 @@ function createMockSubscriptionAdapter(options = {}) {
1314
1776
  await new Promise((resolve) => setTimeout(resolve, 300));
1315
1777
  return { _tag: "Success", data: void 0 };
1316
1778
  },
1779
+ async updateItem() {
1780
+ await new Promise((resolve) => setTimeout(resolve, 300));
1781
+ return { _tag: "Success", data: void 0 };
1782
+ },
1783
+ async skipLineItem() {
1784
+ await new Promise((resolve) => setTimeout(resolve, 300));
1785
+ return { _tag: "Success", data: void 0 };
1786
+ },
1787
+ async updateBoxItems() {
1788
+ return { _tag: "Success", data: void 0 };
1789
+ },
1317
1790
  async addDiscount() {
1318
1791
  await new Promise((resolve) => setTimeout(resolve, 300));
1319
1792
  const behavior = options.addDiscountBehavior ?? { kind: "success" };
@@ -1422,6 +1895,49 @@ function createMockSubscriptionAdapter(options = {}) {
1422
1895
  ]
1423
1896
  };
1424
1897
  },
1898
+ async getLastOrder(params) {
1899
+ await new Promise((resolve) => setTimeout(resolve, 200));
1900
+ const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
1901
+ if (!subscription) return { _tag: "Success", data: null };
1902
+ return {
1903
+ _tag: "Success",
1904
+ data: {
1905
+ id: `mock_last_order_${params.subscriptionId}`,
1906
+ createdAt: "2026-04-22T12:00:00Z"
1907
+ }
1908
+ };
1909
+ },
1910
+ async renewNow(_params) {
1911
+ await new Promise((resolve) => setTimeout(resolve, 300));
1912
+ return { _tag: "Success", data: { result: "success" } };
1913
+ },
1914
+ async changeFrequency(params) {
1915
+ await new Promise((resolve) => setTimeout(resolve, 300));
1916
+ const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
1917
+ if (!subscription) {
1918
+ return { _tag: "Failure", error: "Subscription not found" };
1919
+ }
1920
+ if (typeof params.plan === "string") {
1921
+ subscription.frequency = `1 ${params.plan}`;
1922
+ } else {
1923
+ subscription.frequency = `${params.plan.intervalCount} ${params.plan.interval}`;
1924
+ if (subscription.billingPolicy) {
1925
+ subscription.billingPolicy = { ...subscription.billingPolicy, ...params.plan };
1926
+ }
1927
+ if (subscription.deliveryPolicy) {
1928
+ subscription.deliveryPolicy = { ...subscription.deliveryPolicy, ...params.plan };
1929
+ }
1930
+ }
1931
+ subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1932
+ return {
1933
+ _tag: "Success",
1934
+ data: {
1935
+ ...subscription,
1936
+ items: subscription.items.map((item) => ({ ...item })),
1937
+ discounts: subscription.discounts.map((d3) => ({ ...d3 }))
1938
+ }
1939
+ };
1940
+ },
1425
1941
  async getDefaultSubscriptionId() {
1426
1942
  var _a;
1427
1943
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1437,6 +1953,26 @@ function createMockSubscriptionAdapter(options = {}) {
1437
1953
  }
1438
1954
  };
1439
1955
  }
1956
+ function normalizeInstrumentType(type) {
1957
+ return type.replace(/-/g, "_");
1958
+ }
1959
+ function mapPaymentMethod(rawPm) {
1960
+ if (!rawPm) return null;
1961
+ if (typeof rawPm === "string") {
1962
+ return { id: rawPm };
1963
+ }
1964
+ return {
1965
+ id: rawPm.id ?? "",
1966
+ ...rawPm.instrument != null ? {
1967
+ instrument: {
1968
+ ...rawPm.instrument,
1969
+ type: normalizeInstrumentType(rawPm.instrument.type)
1970
+ }
1971
+ } : {},
1972
+ ...rawPm.active != null ? { active: rawPm.active } : {},
1973
+ ...rawPm.isRecurring != null ? { isRecurring: rawPm.isRecurring } : {}
1974
+ };
1975
+ }
1440
1976
  function mapSubscription(raw) {
1441
1977
  var _a, _b;
1442
1978
  const status = raw.status === "merged" ? "canceled" : raw.status;
@@ -1445,6 +1981,7 @@ function mapSubscription(raw) {
1445
1981
  return {
1446
1982
  id: raw.id,
1447
1983
  customerId: "",
1984
+ serial: raw.serial,
1448
1985
  items: (raw.items ?? []).map(
1449
1986
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1450
1987
  (item) => ({
@@ -1458,37 +1995,50 @@ function mapSubscription(raw) {
1458
1995
  },
1459
1996
  nextDeliveryDate: item.nextDeliveryDate ? new Date(item.nextDeliveryDate) : null,
1460
1997
  billingPolicy: item.billingPolicy ?? raw.billingPolicy ?? null,
1461
- deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? null
1998
+ deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? null,
1999
+ // Map human-readable titles from the v1 SubscriptionItemResource
2000
+ title: item.title,
2001
+ variantTitle: item.subtitle ?? void 0,
2002
+ // recurringCycleLimit === 1 means the item charges exactly once (one-time upsell)
2003
+ isOneTime: item.recurringCycleLimit === 1
1462
2004
  })
1463
2005
  ),
1464
2006
  discounts: (raw.discounts ?? []).map(
1465
2007
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1466
- (d2) => {
2008
+ (d3) => {
1467
2009
  var _a2, _b2, _c;
1468
2010
  return {
1469
- id: d2.id,
1470
- type: ((_a2 = d2.value) == null ? void 0 : _a2.type) === "fixed-amount" || d2.type === "fixed_amount" ? "fixed_amount" : "percentage",
1471
- value: ((_b2 = d2.value) == null ? void 0 : _b2.amount) ?? ((_c = d2.value) == null ? void 0 : _c.percentage) ?? d2.value ?? 0,
1472
- code: d2.title ?? d2.code ?? "",
1473
- description: d2.description ?? ""
2011
+ id: d3.id,
2012
+ type: ((_a2 = d3.value) == null ? void 0 : _a2.type) === "fixed-amount" || d3.type === "fixed_amount" ? "fixed_amount" : "percentage",
2013
+ value: ((_b2 = d3.value) == null ? void 0 : _b2.amount) ?? ((_c = d3.value) == null ? void 0 : _c.percentage) ?? d3.value ?? 0,
2014
+ code: d3.title ?? d3.code ?? "",
2015
+ description: d3.description ?? ""
1474
2016
  };
1475
2017
  }
1476
2018
  ),
1477
2019
  status,
1478
2020
  nextDeliveryDate: raw.nextBillingDate ? new Date(raw.nextBillingDate) : raw.nextDeliveryDate ? new Date(raw.nextDeliveryDate) : null,
2021
+ // Map nextBillingDate as the raw ISO string for ProductSelect skip() and other consumers
2022
+ nextBillingDate: raw.nextBillingDate ?? null,
2023
+ // Map customerPaymentMethod — note: arrives as bare id (not expanded) since the
2024
+ // subscriptions endpoint does not support ?expand=paymentMethod; instrument digits
2025
+ // remain a data gap pending backend API extension.
2026
+ customerPaymentMethod: mapPaymentMethod(raw.paymentMethod),
1479
2027
  frequency,
1480
2028
  createdAt: raw.createdAt,
1481
- updatedAt: raw.updatedAt
2029
+ updatedAt: raw.updatedAt,
2030
+ billingPolicy: raw.billingPolicy ?? null,
2031
+ deliveryPolicy: raw.deliveryPolicy ?? null
1482
2032
  };
1483
2033
  }
1484
2034
  function createApiSubscriptionAdapter(fetcher) {
1485
- return {
2035
+ const adapter = {
1486
2036
  async search(options) {
1487
2037
  var _a;
1488
2038
  try {
1489
2039
  const params = new URLSearchParams();
1490
2040
  if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
1491
- const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k2, v2]) => `${k2}:'${v2}'`).join(" AND ");
2041
+ const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k, v2]) => `${k}:'${v2}'`).join(" AND ");
1492
2042
  if (q2) params.set("query", q2);
1493
2043
  }
1494
2044
  if (options == null ? void 0 : options.pagination) {
@@ -1558,6 +2108,60 @@ function createApiSubscriptionAdapter(fetcher) {
1558
2108
  return { _tag: "Failure", error: e2 };
1559
2109
  }
1560
2110
  },
2111
+ async updateItem({ subscriptionId, lineId, update }) {
2112
+ try {
2113
+ const body = {
2114
+ ...update.variantId !== void 0 ? { productVariantId: update.variantId } : {},
2115
+ ...update.quantity !== void 0 ? { quantity: update.quantity } : {},
2116
+ ...update.billingPolicy !== void 0 ? { billingPolicy: update.billingPolicy } : {},
2117
+ ...update.shippingMethodHandle !== void 0 ? { shippingMethodHandle: update.shippingMethodHandle } : {}
2118
+ };
2119
+ const res = await fetcher(
2120
+ `/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
2121
+ {
2122
+ method: "PUT",
2123
+ headers: { "Content-Type": "application/json" },
2124
+ body: JSON.stringify(body)
2125
+ }
2126
+ );
2127
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2128
+ return { _tag: "Success", data: void 0 };
2129
+ } catch (e2) {
2130
+ return { _tag: "Failure", error: e2 };
2131
+ }
2132
+ },
2133
+ async skipLineItem({ subscriptionId, lineId, nextBillingDate }) {
2134
+ try {
2135
+ const res = await fetcher(
2136
+ `/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
2137
+ {
2138
+ method: "PUT",
2139
+ headers: { "Content-Type": "application/json" },
2140
+ body: JSON.stringify({ nextBillingDate })
2141
+ }
2142
+ );
2143
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2144
+ return { _tag: "Success", data: void 0 };
2145
+ } catch (e2) {
2146
+ return { _tag: "Failure", error: e2 };
2147
+ }
2148
+ },
2149
+ async updateBoxItems({ subscriptionId, parentId, items, shippingMethodHandle }) {
2150
+ try {
2151
+ const res = await fetcher(
2152
+ `/customer/subscriptions/${subscriptionId}/update-box-products`,
2153
+ {
2154
+ method: "POST",
2155
+ headers: { "Content-Type": "application/json" },
2156
+ body: JSON.stringify({ parentId, items, shippingMethodHandle })
2157
+ }
2158
+ );
2159
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2160
+ return { _tag: "Success", data: void 0 };
2161
+ } catch (e2) {
2162
+ return { _tag: "Failure", error: e2 };
2163
+ }
2164
+ },
1561
2165
  async addDiscount({ subscriptionId, code }) {
1562
2166
  try {
1563
2167
  const res = await fetcher(
@@ -1695,16 +2299,18 @@ function createApiSubscriptionAdapter(fetcher) {
1695
2299
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1696
2300
  const data = await res.json();
1697
2301
  const products = data.map((p2) => {
1698
- var _a, _b, _c, _d, _e;
2302
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1699
2303
  return {
1700
2304
  id: p2.id,
1701
2305
  variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
1702
2306
  title: p2.title ?? "",
1703
2307
  imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
1704
2308
  price: {
1705
- amount: String(((_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.price) ?? 0),
1706
- currencyCode: p2.currencyCode ?? ""
1707
- }
2309
+ amount: String(((_f = (_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.currentPrice) == null ? void 0 : _f.amount) ?? 0),
2310
+ currencyCode: ((_i = (_h = (_g = p2.variants) == null ? void 0 : _g[0]) == null ? void 0 : _h.currentPrice) == null ? void 0 : _i.currencyCode) ?? ""
2311
+ },
2312
+ // recurring comes from the upsell rule on variants[0]; present in PreparedProductSchema
2313
+ recurring: (_k = (_j = p2.variants) == null ? void 0 : _j[0]) == null ? void 0 : _k.recurring
1708
2314
  };
1709
2315
  });
1710
2316
  return { _tag: "Success", data: products };
@@ -1732,8 +2338,70 @@ function createApiSubscriptionAdapter(fetcher) {
1732
2338
  } catch (e2) {
1733
2339
  return { _tag: "Failure", error: e2 };
1734
2340
  }
2341
+ },
2342
+ // Legacy endpoint — no /customer/v1 equivalent exists yet.
2343
+ async getLastOrder({ subscriptionId }) {
2344
+ try {
2345
+ const res = await fetcher(
2346
+ `/customer/subscriptions/${subscriptionId}/last-order`
2347
+ );
2348
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2349
+ const data = await res.json();
2350
+ if (!data) return { _tag: "Success", data: null };
2351
+ return {
2352
+ _tag: "Success",
2353
+ data: { id: data.id, createdAt: data.createdAt }
2354
+ };
2355
+ } catch (e2) {
2356
+ return { _tag: "Failure", error: e2 };
2357
+ }
2358
+ },
2359
+ // Legacy endpoints, split by stage (see SubscriptionService.renewNow docs):
2360
+ // retry → POST /customer/subscriptions/{id}/retry
2361
+ // renewalId → POST /customer/renewals/{renewalId}/renew
2362
+ // default → POST /customer/subscriptions/{id}/order-now
2363
+ async renewNow({ subscriptionId, renewalId, retry }) {
2364
+ try {
2365
+ const url = retry ? `/customer/subscriptions/${subscriptionId}/retry` : renewalId ? `/customer/renewals/${renewalId}/renew` : `/customer/subscriptions/${subscriptionId}/order-now`;
2366
+ const res = await fetcher(url, { method: "POST" });
2367
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2368
+ const body = res.status === 204 ? null : await res.json();
2369
+ return {
2370
+ _tag: "Success",
2371
+ data: {
2372
+ nextActionUrl: (body == null ? void 0 : body.nextActionUrl) ?? void 0,
2373
+ result: (body == null ? void 0 : body.result) ?? "success"
2374
+ }
2375
+ };
2376
+ } catch (e2) {
2377
+ return { _tag: "Failure", error: e2 };
2378
+ }
2379
+ },
2380
+ // Legacy endpoint — POST /plan returns 204; re-fetch to return the updated subscription.
2381
+ async changeFrequency({ subscriptionId, plan }) {
2382
+ try {
2383
+ const res = await fetcher(
2384
+ `/customer/subscriptions/${subscriptionId}/plan`,
2385
+ {
2386
+ method: "POST",
2387
+ headers: { "Content-Type": "application/json" },
2388
+ body: JSON.stringify({ plan })
2389
+ }
2390
+ );
2391
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2392
+ const refreshed = await adapter.getById(subscriptionId);
2393
+ if (refreshed._tag === "Failure") return refreshed;
2394
+ if (refreshed.data) return { _tag: "Success", data: refreshed.data };
2395
+ return {
2396
+ _tag: "Failure",
2397
+ error: "Subscription not found after frequency change"
2398
+ };
2399
+ } catch (e2) {
2400
+ return { _tag: "Failure", error: e2 };
2401
+ }
1735
2402
  }
1736
2403
  };
2404
+ return adapter;
1737
2405
  }
1738
2406
  const SubscriptionServiceContext = createContext("services/subscription");
1739
2407
  function getCurrentSubscriptionId() {
@@ -1758,57 +2426,82 @@ function getCurrentSubscriptionId() {
1758
2426
  function createSubscriptionService(adapter) {
1759
2427
  const current = d(null);
1760
2428
  const hasPendingBilling = d(false);
1761
- const discountsChangedAtSignal = d(0);
1762
- const itemsChangedAtSignal = d(0);
1763
- async function refreshCurrent(subscriptionId) {
1764
- const result = await adapter.getById(subscriptionId);
1765
- if (result._tag === "Success" && result.data != null) {
1766
- current.value = result.data;
1767
- }
1768
- }
1769
- async function refreshAfterDiscountChange(subscriptionId) {
1770
- await refreshCurrent(subscriptionId);
1771
- discountsChangedAtSignal.value = discountsChangedAtSignal.value + 1;
2429
+ const discountsChangedAt = d(0);
2430
+ const itemsChangedAt = d(0);
2431
+ const lastOrder = d(null);
2432
+ async function refreshAfterDiscountChange() {
2433
+ await reload();
2434
+ discountsChangedAt.value = discountsChangedAt.value + 1;
1772
2435
  }
1773
- async function refreshAfterItemChange(subscriptionId) {
1774
- await refreshCurrent(subscriptionId);
1775
- itemsChangedAtSignal.value = itemsChangedAtSignal.value + 1;
2436
+ async function refreshAfterItemChange() {
2437
+ await reload();
2438
+ itemsChangedAt.value = itemsChangedAt.value + 1;
1776
2439
  }
1777
2440
  function subscriptionIdFromCurrent() {
1778
2441
  var _a;
1779
2442
  return ((_a = current.value) == null ? void 0 : _a.id) ?? null;
1780
2443
  }
1781
- return {
2444
+ async function reload() {
2445
+ var _a, _b;
2446
+ const id = (_a = current.value) == null ? void 0 : _a.id;
2447
+ if (!id) return;
2448
+ const [subResult, lastOrderResult] = await Promise.all([
2449
+ adapter.getById(id),
2450
+ adapter.getLastOrder({ subscriptionId: id })
2451
+ ]);
2452
+ if (((_b = current.value) == null ? void 0 : _b.id) !== id) return;
2453
+ if (subResult._tag === "Success") current.value = subResult.data;
2454
+ if (lastOrderResult._tag === "Success") lastOrder.value = lastOrderResult.data;
2455
+ }
2456
+ const service = {
1782
2457
  current,
1783
2458
  hasPendingBilling,
1784
- discountsChangedAt: discountsChangedAtSignal,
1785
- itemsChangedAt: itemsChangedAtSignal,
1786
- async search(options) {
1787
- const result = await adapter.search(options);
2459
+ discountsChangedAt,
2460
+ itemsChangedAt,
2461
+ lastOrder,
2462
+ search: adapter.search,
2463
+ // Prefer the adapter's rich cross-subscription list (legacy endpoint, active-first).
2464
+ // Fall back to a single `search` page for adapters that don't implement it
2465
+ // (e.g. the editor mock) so the cross-subscription views still render.
2466
+ listAll: adapter.listAll ? adapter.listAll.bind(adapter) : async () => {
2467
+ const result = await adapter.search();
2468
+ if (result._tag !== "Success") return result;
2469
+ return { _tag: "Success", data: result.data.items };
2470
+ },
2471
+ getById: adapter.getById,
2472
+ getCurrentSubscriptionId,
2473
+ addItem: async (subscriptionId, item) => {
2474
+ const result = await adapter.addItem({ subscriptionId, item });
1788
2475
  if (result._tag === "Success") {
1789
- current.value = result.data.items[0] ?? null;
2476
+ await refreshAfterItemChange();
1790
2477
  }
1791
2478
  return result;
1792
2479
  },
1793
- async getById(id) {
1794
- const result = await adapter.getById(id);
1795
- if (result._tag === "Success" && result.data) {
1796
- current.value = result.data;
2480
+ removeItem: async (subscriptionId, itemId) => {
2481
+ const result = await adapter.removeItem({ subscriptionId, itemId });
2482
+ if (result._tag === "Success") {
2483
+ await refreshAfterItemChange();
1797
2484
  }
1798
2485
  return result;
1799
2486
  },
1800
- getCurrentSubscriptionId,
1801
- addItem: async (subscriptionId, item) => {
1802
- const result = await adapter.addItem({ subscriptionId, item });
2487
+ updateItem: async (subscriptionId, lineId, update) => {
2488
+ const result = await adapter.updateItem({ subscriptionId, lineId, update });
1803
2489
  if (result._tag === "Success") {
1804
- await refreshAfterItemChange(subscriptionId);
2490
+ await refreshAfterItemChange();
1805
2491
  }
1806
2492
  return result;
1807
2493
  },
1808
- removeItem: async (subscriptionId, itemId) => {
1809
- const result = await adapter.removeItem({ subscriptionId, itemId });
2494
+ skipLineItem: async (subscriptionId, lineId, nextBillingDate) => {
2495
+ const result = await adapter.skipLineItem({ subscriptionId, lineId, nextBillingDate });
1810
2496
  if (result._tag === "Success") {
1811
- await refreshAfterItemChange(subscriptionId);
2497
+ await refreshAfterItemChange();
2498
+ }
2499
+ return result;
2500
+ },
2501
+ updateBoxItems: async (subscriptionId, params) => {
2502
+ const result = await adapter.updateBoxItems({ subscriptionId, ...params });
2503
+ if (result._tag === "Success") {
2504
+ await refreshAfterItemChange();
1812
2505
  }
1813
2506
  return result;
1814
2507
  },
@@ -1822,7 +2515,7 @@ function createSubscriptionService(adapter) {
1822
2515
  }
1823
2516
  const result = await adapter.addDiscount({ subscriptionId: id, code });
1824
2517
  if (result._tag === "Success") {
1825
- await refreshAfterDiscountChange(id);
2518
+ await refreshAfterDiscountChange();
1826
2519
  }
1827
2520
  return result;
1828
2521
  },
@@ -1839,7 +2532,7 @@ function createSubscriptionService(adapter) {
1839
2532
  discountId
1840
2533
  });
1841
2534
  if (result._tag === "Success") {
1842
- await refreshAfterDiscountChange(id);
2535
+ await refreshAfterDiscountChange();
1843
2536
  }
1844
2537
  return result;
1845
2538
  },
@@ -1848,11 +2541,15 @@ function createSubscriptionService(adapter) {
1848
2541
  pause: (subscriptionId) => adapter.pause({ subscriptionId }),
1849
2542
  reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
1850
2543
  cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
2544
+ renewNow: (params) => adapter.renewNow(params),
2545
+ changeFrequency: (subscriptionId, plan) => adapter.changeFrequency({ subscriptionId, plan }),
2546
+ reload,
1851
2547
  getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
1852
2548
  getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
1853
2549
  getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
1854
2550
  addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 })
1855
2551
  };
2552
+ return service;
1856
2553
  }
1857
2554
  const DISCOUNT_REJECTION_REASONS = [
1858
2555
  "INVALID_CODE",
@@ -2119,35 +2816,40 @@ export {
2119
2816
  AuthenticationError,
2120
2817
  AuthenticationErrorReason,
2121
2818
  B as BlockWrapperEvent,
2122
- C as ContextProvideEvent,
2123
- a as ContextRequestEvent,
2819
+ m as ContextProvideEvent,
2820
+ p as ContextRequestEvent,
2124
2821
  CustomerServiceContext,
2125
- D as DEFAULT_GLOBAL_STYLES,
2822
+ D2 as DEFAULT_GLOBAL_STYLES,
2126
2823
  DISCOUNT_REJECTION_REASONS,
2127
2824
  LoginServiceContext,
2128
2825
  OrdersServiceContext,
2826
+ OverlayServiceContext,
2129
2827
  ProductServiceContext,
2130
2828
  RouterServiceContext,
2131
2829
  SchedulesServiceContext,
2132
2830
  S as SelectedBlockContext,
2831
+ SettingsServiceContext,
2832
+ ShopServiceContext,
2133
2833
  u as Signal,
2134
2834
  StateContext,
2135
2835
  SubscriptionServiceContext,
2136
- T as ThemeStateContext,
2137
- b as TranslationContext,
2836
+ a2 as ThemeStateContext,
2837
+ T as TranslationContext,
2138
2838
  W as WorkflowServiceContext,
2139
- e as attachEmptyTracking,
2140
- f as backfillInstanceDefaults,
2839
+ q as __recordDevtoolsInstance,
2840
+ _ as __recordDevtoolsPropSetter,
2841
+ t as attachEmptyTracking,
2842
+ b as backfillInstanceDefaults,
2141
2843
  w as computed,
2142
2844
  createApiCustomerAdapter,
2143
2845
  createApiLoginAdapter,
2144
2846
  createApiProductAdapter,
2145
2847
  createApiSchedulesAdapter,
2146
2848
  createApiSubscriptionAdapter,
2147
- g as createBlockInstance,
2148
- h as createBlockInstanceFromJSON,
2149
- i as createBlockInstanceFromObject,
2150
- j as createCeRenderer,
2849
+ createBlockInstance,
2850
+ v as createBlockInstanceFromJSON,
2851
+ f as createBlockInstanceFromObject,
2852
+ x as createCeRenderer,
2151
2853
  createContext,
2152
2854
  createCustomerService,
2153
2855
  createLoginService,
@@ -2160,36 +2862,42 @@ export {
2160
2862
  createMockSubscriptionAdapter,
2161
2863
  createMockWorkflowApiAdapter,
2162
2864
  createOrdersService,
2865
+ createOverlayService,
2163
2866
  createProductService,
2164
2867
  createRouterService,
2165
2868
  createSchedulesService,
2166
- k as createSelectedBlock,
2869
+ y as createSelectedBlock,
2870
+ createSettingsService,
2871
+ createShopService,
2167
2872
  createState,
2168
2873
  createSubscriptionService,
2169
- l as createThemeState,
2170
- m as createTranslationService,
2171
- n as createWorkflowApiAdapter,
2172
- o as createWorkflowService,
2173
- p as defineBlock,
2174
- q as defineBlockRuntime,
2874
+ c as createThemeState,
2875
+ b2 as createTranslationService,
2876
+ d2 as createWorkflowApiAdapter,
2877
+ e as createWorkflowService,
2878
+ defineBlock,
2879
+ z as defineBlockRuntime,
2880
+ defineOverlayWrapper,
2175
2881
  E as effect,
2176
- s as getDefaultBlockForAction,
2177
- t as getDefinedBlocks,
2178
- v as hasDefaultBlockForAction,
2179
- x as hasRenderedContent,
2180
- y as indexOverrides,
2181
- z as injectContext,
2182
- A as isEditorPreview,
2183
- F as isStubDefinition,
2882
+ g as getDefaultBlockForAction,
2883
+ getDefinedBlocks,
2884
+ A as getDevtoolsBlockState,
2885
+ h as hasDefaultBlockForAction,
2886
+ D as hasRenderedContent,
2887
+ i2 as indexOverrides,
2888
+ i as injectContext,
2889
+ F as isEditorPreview,
2890
+ a as isStubDefinition,
2184
2891
  loadBlockRegistry,
2185
2892
  loginService,
2186
- G as onRegisterBlock,
2187
- H as provideContext,
2893
+ o as onRegisterBlock,
2894
+ G as provideContext,
2188
2895
  registerBlock,
2189
- I as serializeBlocks,
2896
+ j as serializeBlocks,
2897
+ H as setDevtoolsBlockProp,
2190
2898
  d as signal,
2191
- J as subscribeContext,
2192
- K as untracked,
2899
+ s as subscribeContext,
2900
+ n as untracked,
2193
2901
  waitForDevBlocksUrl,
2194
- L as withWrapper
2902
+ w2 as withWrapper
2195
2903
  };