@juo/blocks 1.15.0 → 2.0.0-alpha.1

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 (171) hide show
  1. package/dist/{ExtensionRoot-C3lVJEBl.js → ExtensionRoot-DRpD5EcC.js} +24 -6
  2. package/dist/block-BjJztStr.js +993 -0
  3. package/dist/{block-VhmfGB3N.js → block-DnhzyZ1H.js} +38 -3
  4. package/dist/block.d.ts +56 -0
  5. package/dist/block.d.ts.map +1 -1
  6. package/dist/{bridge-xiKEzCGR.js → bridge-Mz0CqG6E.js} +39 -30
  7. package/dist/core.js +2429 -399
  8. package/dist/css-runtime-B7tZrBIp.js +749 -0
  9. package/dist/devtools/hook.d.ts +0 -5
  10. package/dist/devtools/hook.d.ts.map +1 -1
  11. package/dist/devtools/index.d.ts +0 -1
  12. package/dist/devtools/index.d.ts.map +1 -1
  13. package/dist/devtools/protocol.d.ts +15 -1
  14. package/dist/devtools/protocol.d.ts.map +1 -1
  15. package/dist/devtools.js +42 -9
  16. package/dist/editor/bridge.d.ts +7 -0
  17. package/dist/editor/bridge.d.ts.map +1 -1
  18. package/dist/editor/components.d.ts.map +1 -1
  19. package/dist/editor/main.d.ts +2 -1
  20. package/dist/editor/main.d.ts.map +1 -1
  21. package/dist/editor/messages.d.ts +13 -2
  22. package/dist/editor/messages.d.ts.map +1 -1
  23. package/dist/editor/overlays.d.ts +14 -0
  24. package/dist/editor/overlays.d.ts.map +1 -0
  25. package/dist/editor/overlays.test.d.ts +2 -0
  26. package/dist/editor/overlays.test.d.ts.map +1 -0
  27. package/dist/editor.js +52 -33
  28. package/dist/{gridstack-adapter-CDWbSpbt.js → gridstack-adapter-BGKGC-eO.js} +2 -2
  29. package/dist/main.d.ts +3 -1
  30. package/dist/main.d.ts.map +1 -1
  31. package/dist/{morph-n4LMxOYo.js → morph-CT5hc5Qp.js} +1 -1
  32. package/dist/overlay-wrapper.d.ts +69 -0
  33. package/dist/overlay-wrapper.d.ts.map +1 -0
  34. package/dist/overlay-wrapper.test.d.ts +2 -0
  35. package/dist/overlay-wrapper.test.d.ts.map +1 -0
  36. package/dist/overlays/OverlayService.d.ts +34 -0
  37. package/dist/overlays/OverlayService.d.ts.map +1 -0
  38. package/dist/overlays/OverlayService.test.d.ts +2 -0
  39. package/dist/overlays/OverlayService.test.d.ts.map +1 -0
  40. package/dist/preact/block.d.ts.map +1 -1
  41. package/dist/preact/context.d.ts.map +1 -1
  42. package/dist/preact/context.test.d.ts +2 -0
  43. package/dist/preact/context.test.d.ts.map +1 -0
  44. package/dist/preact/signals.d.ts +19 -0
  45. package/dist/preact/signals.d.ts.map +1 -1
  46. package/dist/preact/useContextSubscription.test.d.ts +2 -0
  47. package/dist/preact/useContextSubscription.test.d.ts.map +1 -0
  48. package/dist/preact.js +33 -7
  49. package/dist/{project-gridstack-CM783oKI.js → project-gridstack-PxN_DIfP.js} +1 -1
  50. package/dist/react/block.d.ts.map +1 -1
  51. package/dist/react/context.d.ts.map +1 -1
  52. package/dist/react/context.test.d.ts +2 -0
  53. package/dist/react/context.test.d.ts.map +1 -0
  54. package/dist/react/signals.d.ts +19 -0
  55. package/dist/react/signals.d.ts.map +1 -1
  56. package/dist/react/useContextSubscription.test.d.ts +2 -0
  57. package/dist/react/useContextSubscription.test.d.ts.map +1 -0
  58. package/dist/react.js +40 -8
  59. package/dist/services/customer/adapter.d.ts +8 -0
  60. package/dist/services/customer/adapter.d.ts.map +1 -0
  61. package/dist/services/customer/customerService.d.ts +3 -2
  62. package/dist/services/customer/customerService.d.ts.map +1 -1
  63. package/dist/services/customer/index.d.ts +1 -0
  64. package/dist/services/customer/index.d.ts.map +1 -1
  65. package/dist/services/customer/types.d.ts +4 -1
  66. package/dist/services/customer/types.d.ts.map +1 -1
  67. package/dist/services/index.d.ts +4 -1
  68. package/dist/services/index.d.ts.map +1 -1
  69. package/dist/services/login/adapter.d.ts +33 -0
  70. package/dist/services/login/adapter.d.ts.map +1 -0
  71. package/dist/services/login/index.d.ts +3 -1
  72. package/dist/services/login/index.d.ts.map +1 -1
  73. package/dist/services/login/loginService.d.ts +6 -2
  74. package/dist/services/login/loginService.d.ts.map +1 -1
  75. package/dist/services/order/adapter.d.ts +10 -0
  76. package/dist/services/order/adapter.d.ts.map +1 -0
  77. package/dist/services/order/index.d.ts +4 -0
  78. package/dist/services/order/index.d.ts.map +1 -0
  79. package/dist/services/order/orderService.d.ts +6 -0
  80. package/dist/services/order/orderService.d.ts.map +1 -0
  81. package/dist/services/order/orderService.test.d.ts +2 -0
  82. package/dist/services/order/orderService.test.d.ts.map +1 -0
  83. package/dist/services/{orders → order}/types.d.ts +3 -3
  84. package/dist/services/order/types.d.ts.map +1 -0
  85. package/dist/services/product/adapter.d.ts +27 -2
  86. package/dist/services/product/adapter.d.ts.map +1 -1
  87. package/dist/services/product/adapter.test.d.ts +2 -0
  88. package/dist/services/product/adapter.test.d.ts.map +1 -0
  89. package/dist/services/product/index.d.ts +1 -1
  90. package/dist/services/product/index.d.ts.map +1 -1
  91. package/dist/services/product/productService.d.ts.map +1 -1
  92. package/dist/services/product/types.d.ts +68 -0
  93. package/dist/services/product/types.d.ts.map +1 -1
  94. package/dist/services/schedules/adapter.d.ts +94 -0
  95. package/dist/services/schedules/adapter.d.ts.map +1 -0
  96. package/dist/services/schedules/adapter.test.d.ts +2 -0
  97. package/dist/services/schedules/adapter.test.d.ts.map +1 -0
  98. package/dist/services/schedules/apiSchedulesAdapter.test.d.ts +2 -0
  99. package/dist/services/schedules/apiSchedulesAdapter.test.d.ts.map +1 -0
  100. package/dist/services/schedules/index.d.ts +5 -0
  101. package/dist/services/schedules/index.d.ts.map +1 -0
  102. package/dist/services/schedules/schedulesService.d.ts +11 -0
  103. package/dist/services/schedules/schedulesService.d.ts.map +1 -0
  104. package/dist/services/schedules/schedulesService.test.d.ts +2 -0
  105. package/dist/services/schedules/schedulesService.test.d.ts.map +1 -0
  106. package/dist/services/schedules/types.d.ts +290 -0
  107. package/dist/services/schedules/types.d.ts.map +1 -0
  108. package/dist/services/settings/index.d.ts +3 -0
  109. package/dist/services/settings/index.d.ts.map +1 -0
  110. package/dist/services/settings/settingsService.d.ts +7 -0
  111. package/dist/services/settings/settingsService.d.ts.map +1 -0
  112. package/dist/services/settings/settingsService.test.d.ts +2 -0
  113. package/dist/services/settings/settingsService.test.d.ts.map +1 -0
  114. package/dist/services/settings/types.d.ts +35 -0
  115. package/dist/services/settings/types.d.ts.map +1 -0
  116. package/dist/services/shop/index.d.ts +3 -0
  117. package/dist/services/shop/index.d.ts.map +1 -0
  118. package/dist/services/shop/shopService.d.ts +12 -0
  119. package/dist/services/shop/shopService.d.ts.map +1 -0
  120. package/dist/services/shop/shopService.test.d.ts +2 -0
  121. package/dist/services/shop/shopService.test.d.ts.map +1 -0
  122. package/dist/services/shop/types.d.ts +7 -0
  123. package/dist/services/shop/types.d.ts.map +1 -0
  124. package/dist/services/subscription/adapter.d.ts +77 -2
  125. package/dist/services/subscription/adapter.d.ts.map +1 -1
  126. package/dist/services/subscription/adapter.test.d.ts +2 -0
  127. package/dist/services/subscription/adapter.test.d.ts.map +1 -0
  128. package/dist/services/subscription/index.d.ts +1 -1
  129. package/dist/services/subscription/index.d.ts.map +1 -1
  130. package/dist/services/subscription/subscriptionService.d.ts +1 -6
  131. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  132. package/dist/services/subscription/types.d.ts +220 -9
  133. package/dist/services/subscription/types.d.ts.map +1 -1
  134. package/dist/services/subscription/types.test.d.ts +2 -0
  135. package/dist/services/subscription/types.test.d.ts.map +1 -0
  136. package/dist/shared/context.d.ts +10 -3
  137. package/dist/shared/context.d.ts.map +1 -1
  138. package/dist/shared/touchSignals.d.ts +17 -0
  139. package/dist/shared/touchSignals.d.ts.map +1 -0
  140. package/dist/shared/touchSignals.test.d.ts +2 -0
  141. package/dist/shared/touchSignals.test.d.ts.map +1 -0
  142. package/dist/theme-state.d.ts +2 -1
  143. package/dist/theme-state.d.ts.map +1 -1
  144. package/dist/theme-state.params.test.d.ts +2 -0
  145. package/dist/theme-state.params.test.d.ts.map +1 -0
  146. package/dist/theme-state.translations.test.d.ts +2 -0
  147. package/dist/theme-state.translations.test.d.ts.map +1 -0
  148. package/dist/utils/index.d.ts +6 -0
  149. package/dist/utils/index.d.ts.map +1 -1
  150. package/dist/vue/block.d.ts.map +1 -1
  151. package/dist/vue/context.d.ts +1 -0
  152. package/dist/vue/context.d.ts.map +1 -1
  153. package/dist/vue.js +28 -15
  154. package/dist/web-components/ExtensionRoot.d.ts +1 -0
  155. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  156. package/dist/web-components-editor.js +6 -5
  157. package/dist/web-components-runtime.js +3 -2
  158. package/package.json +1 -1
  159. package/dist/css-runtime-ClH0MEYr.js +0 -1570
  160. package/dist/devtools/instrumentation.d.ts +0 -47
  161. package/dist/devtools/instrumentation.d.ts.map +0 -1
  162. package/dist/index-JSv6UH_o.js +0 -169
  163. package/dist/services/orders/adapter.d.ts +0 -8
  164. package/dist/services/orders/adapter.d.ts.map +0 -1
  165. package/dist/services/orders/index.d.ts +0 -4
  166. package/dist/services/orders/index.d.ts.map +0 -1
  167. package/dist/services/orders/ordersService.d.ts +0 -6
  168. package/dist/services/orders/ordersService.d.ts.map +0 -1
  169. package/dist/services/orders/ordersService.test.d.ts +0 -2
  170. package/dist/services/orders/ordersService.test.d.ts.map +0 -1
  171. package/dist/services/orders/types.d.ts.map +0 -1
@@ -0,0 +1,749 @@
1
+ import { e as createContext, f as d, E, r, g as createBlockInstanceFromObject, h as createBlockInstance, j as getDefinedBlocks, k as serializeBlocks, l as setLayoutSystemEnabled, o as onRegisterBlock } from "./block-BjJztStr.js";
2
+ import { reportBlockError } from "./observability.js";
3
+ const DEFAULT_GLOBAL_STYLES = {
4
+ volume: "comfort",
5
+ style: "ghost",
6
+ corners: "round",
7
+ buttonCorners: "round",
8
+ thumbnailCorners: "circle",
9
+ theme: "preset",
10
+ themeType: "neutral",
11
+ colors: {
12
+ accent: "#000000",
13
+ secondary: "#000000",
14
+ tint: "#111111",
15
+ callout: "#F5F5F5",
16
+ success: "#287a25",
17
+ error: "#a93c3c",
18
+ information: "#0075a3",
19
+ warning: "#8a5e00",
20
+ background: "#FFFFFF"
21
+ }
22
+ };
23
+ const ThemeStateContext = createContext("theme-state");
24
+ function normalizeLocale(locale) {
25
+ return locale.trim().toLowerCase().split("-")[0] || "en";
26
+ }
27
+ function toStringRecord$1(input) {
28
+ if (input == null) return {};
29
+ return Object.fromEntries(
30
+ Object.entries(input).filter(([, value]) => typeof value === "string")
31
+ );
32
+ }
33
+ function parseBlockLocaleFile(file) {
34
+ if (file == null) {
35
+ return { defaults: {}, modes: {} };
36
+ }
37
+ const entries = Object.entries(file).filter(
38
+ ([key, value]) => key !== "overrides" && typeof value === "string"
39
+ );
40
+ const topLevel = Object.fromEntries(entries);
41
+ const overrides = toStringRecord$1(file.overrides);
42
+ return {
43
+ defaults: { ...topLevel, ...overrides },
44
+ modes: {
45
+ ...Object.fromEntries(
46
+ Object.keys(topLevel).map((key) => [key, "default"])
47
+ ),
48
+ ...Object.fromEntries(
49
+ Object.keys(overrides).map((key) => [key, "override"])
50
+ )
51
+ }
52
+ };
53
+ }
54
+ function indexOverrides(overrides) {
55
+ const indexed = {
56
+ theme: {},
57
+ blocks: {}
58
+ };
59
+ for (const item of overrides) {
60
+ if (item.scope.kind === "theme") {
61
+ indexed.theme[item.key] = item.value;
62
+ continue;
63
+ }
64
+ if (indexed.blocks[item.scope.blockId] == null) {
65
+ indexed.blocks[item.scope.blockId] = {};
66
+ }
67
+ indexed.blocks[item.scope.blockId][item.key] = item.value;
68
+ }
69
+ return indexed;
70
+ }
71
+ function createThemeState(deps) {
72
+ var _a;
73
+ const surfaces = {
74
+ page: {
75
+ blocks: d([]),
76
+ layout: d(null)
77
+ },
78
+ overlay: {
79
+ blocks: d([]),
80
+ layout: d(null)
81
+ }
82
+ };
83
+ const locale = d("en");
84
+ const catalogs = d(null);
85
+ const globalStyles = d(
86
+ deps.initialGlobalStyles ?? DEFAULT_GLOBAL_STYLES
87
+ );
88
+ function setGlobalStyles(styles) {
89
+ globalStyles.value = styles;
90
+ }
91
+ function setInstanceTranslationOverride(blockId, key, value) {
92
+ const current = catalogs.value;
93
+ if (current == null) return;
94
+ catalogs.value = {
95
+ ...current,
96
+ blocks: {
97
+ ...current.blocks,
98
+ overrides: {
99
+ ...current.blocks.overrides,
100
+ [blockId]: { ...current.blocks.overrides[blockId], [key]: value }
101
+ }
102
+ }
103
+ };
104
+ }
105
+ E(() => {
106
+ setLayoutSystemEnabled(globalStyles.value.layoutEngine === "grid-v1");
107
+ });
108
+ async function collectBlockDefaults(loc) {
109
+ const nextDefaults = {};
110
+ const nextModes = {};
111
+ for (const block of getDefinedBlocks()) {
112
+ if (block.locales == null) continue;
113
+ let file = null;
114
+ try {
115
+ file = await block.locales.load(loc);
116
+ } catch {
117
+ file = null;
118
+ }
119
+ const parsed = parseBlockLocaleFile(file);
120
+ nextDefaults[block.name] = parsed.defaults;
121
+ nextModes[block.name] = parsed.modes;
122
+ }
123
+ return { defaults: nextDefaults, modes: nextModes };
124
+ }
125
+ async function setLocale(nextLocaleRaw) {
126
+ var _a2;
127
+ const nextLocale = normalizeLocale(nextLocaleRaw);
128
+ const [blockData, loadedOverrides] = await Promise.all([
129
+ collectBlockDefaults(nextLocale),
130
+ ((_a2 = deps.translations) == null ? void 0 : _a2.resolveTranslations(nextLocale).catch(() => [])) ?? Promise.resolve([])
131
+ ]);
132
+ const overrides = loadedOverrides.filter(
133
+ (item) => normalizeLocale(item.locale) === nextLocale
134
+ );
135
+ const indexed = indexOverrides(overrides);
136
+ catalogs.value = {
137
+ theme: {
138
+ defaults: {},
139
+ overrides: indexed.theme
140
+ },
141
+ blocks: {
142
+ defaults: blockData.defaults,
143
+ modes: blockData.modes,
144
+ overrides: indexed.blocks
145
+ }
146
+ };
147
+ locale.value = nextLocale;
148
+ }
149
+ async function resolve(surface, path, params) {
150
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
151
+ r(() => {
152
+ surfaces[surface].blocks.value = [];
153
+ surfaces[surface].layout.value = null;
154
+ });
155
+ const stored = await deps.resolve(surface, path);
156
+ if (stored != null) {
157
+ const instances = stored.blocks.flatMap((block) => {
158
+ try {
159
+ return [createBlockInstanceFromObject(block)];
160
+ } catch (error) {
161
+ reportBlockError(error, {
162
+ site: "theme-state.resolve.hydrate",
163
+ extra: {
164
+ surface,
165
+ path,
166
+ blockType: typeof (block == null ? void 0 : block.type) === "string" ? block.type : "(unknown)"
167
+ }
168
+ });
169
+ return [];
170
+ }
171
+ });
172
+ if (surface === "overlay") {
173
+ for (const instance of instances) {
174
+ if (typeof instance.type !== "string" || !instance.type.startsWith("overlay:")) {
175
+ continue;
176
+ }
177
+ try {
178
+ const canonical = createBlockInstance(instance.type);
179
+ instance.props = {
180
+ ...instance.props ?? {},
181
+ layout: (_a2 = canonical.props) == null ? void 0 : _a2.layout,
182
+ canAbort: (_b = canonical.props) == null ? void 0 : _b.canAbort
183
+ };
184
+ } catch (error) {
185
+ reportBlockError(error, {
186
+ site: "theme-state.resolve.overlay-layout",
187
+ extra: { surface, path, blockType: instance.type }
188
+ });
189
+ }
190
+ }
191
+ }
192
+ if (params != null) {
193
+ for (const instance of instances) {
194
+ const content = (_c = instance.slots) == null ? void 0 : _c.content;
195
+ const child = Array.isArray(content) ? content[0] : void 0;
196
+ if (child != null) {
197
+ child.props = { ...child.props ?? {}, ...params };
198
+ }
199
+ }
200
+ }
201
+ r(() => {
202
+ surfaces[surface].blocks.value = instances;
203
+ surfaces[surface].layout.value = stored.layout ?? null;
204
+ });
205
+ return stored;
206
+ }
207
+ const blockToUse = surface === "page" ? (_e = (_d = deps.routerService) == null ? void 0 : _d.getPages().find((p) => p.path === path)) == null ? void 0 : _e.block : (_f = getDefinedBlocks().find((b) => b.name === path)) == null ? void 0 : _f.name;
208
+ if (blockToUse != null) {
209
+ const instance = createBlockInstance(blockToUse);
210
+ if (params != null) {
211
+ const content = (_g = instance.slots) == null ? void 0 : _g.content;
212
+ const child = Array.isArray(content) ? content[0] : void 0;
213
+ if (child != null) {
214
+ child.props = { ...child.props ?? {}, ...params };
215
+ }
216
+ }
217
+ surfaces[surface].blocks.value = [instance];
218
+ const serialized = serializeBlocks([instance]);
219
+ (_h = deps.upsertState) == null ? void 0 : _h.call(deps, surface, path, serialized);
220
+ return { blocks: serialized };
221
+ }
222
+ return { blocks: [] };
223
+ }
224
+ onRegisterBlock(async (_, block) => {
225
+ if (block.locales == null || catalogs.value == null) return;
226
+ const localeAtLoadStart = locale.value;
227
+ let file = null;
228
+ try {
229
+ file = await block.locales.load(localeAtLoadStart);
230
+ } catch {
231
+ file = null;
232
+ }
233
+ if (catalogs.value == null || locale.value !== localeAtLoadStart) return;
234
+ const parsed = parseBlockLocaleFile(file);
235
+ const current = catalogs.value;
236
+ catalogs.value = {
237
+ ...current,
238
+ blocks: {
239
+ ...current.blocks,
240
+ defaults: {
241
+ ...current.blocks.defaults,
242
+ [block.name]: parsed.defaults
243
+ },
244
+ modes: {
245
+ ...current.blocks.modes,
246
+ [block.name]: parsed.modes
247
+ }
248
+ }
249
+ };
250
+ });
251
+ (_a = deps.routerService) == null ? void 0 : _a.subscribe(({ path }) => {
252
+ resolve("page", path);
253
+ });
254
+ return {
255
+ page: surfaces.page,
256
+ overlay: surfaces.overlay,
257
+ locales: { locale, catalogs, setLocale },
258
+ globalStyles,
259
+ setGlobalStyles,
260
+ setInstanceTranslationOverride,
261
+ resolve
262
+ };
263
+ }
264
+ const TranslationContext = createContext("translation");
265
+ function toStringRecord(input) {
266
+ if (input == null) return {};
267
+ return Object.fromEntries(
268
+ Object.entries(input).filter(([, value]) => typeof value === "string")
269
+ );
270
+ }
271
+ function createTranslationService(locales, options = {}) {
272
+ const loadedThemeDefaults = d({});
273
+ if (options.loadDefaultTranslations) {
274
+ let loadVersion = 0;
275
+ E(() => {
276
+ const locale = locales.locale.value;
277
+ const currentVersion = ++loadVersion;
278
+ void options.loadDefaultTranslations(locale).then((result) => toStringRecord(result)).catch(() => ({})).then((result) => {
279
+ if (currentVersion !== loadVersion) return;
280
+ loadedThemeDefaults.value = result;
281
+ });
282
+ });
283
+ }
284
+ return {
285
+ locale: locales.locale,
286
+ resolve(blockType, blockId, key) {
287
+ var _a, _b, _c;
288
+ const data = locales.catalogs.value;
289
+ const themeDefault = loadedThemeDefaults.value[key] ?? (data == null ? void 0 : data.theme.defaults[key]);
290
+ if (data == null) {
291
+ return themeDefault ?? key;
292
+ }
293
+ if (blockId && ((_a = data.blocks.overrides[blockId]) == null ? void 0 : _a[key]) !== void 0) {
294
+ return data.blocks.overrides[blockId][key];
295
+ }
296
+ const blockDefault = blockType != null ? (_b = data.blocks.defaults[blockType]) == null ? void 0 : _b[key] : void 0;
297
+ const mode = (blockType != null ? (_c = data.blocks.modes[blockType]) == null ? void 0 : _c[key] : void 0) ?? "override";
298
+ if (blockDefault !== void 0 && mode === "override") {
299
+ return blockDefault;
300
+ }
301
+ if (data.theme.overrides[key] !== void 0) {
302
+ return data.theme.overrides[key];
303
+ }
304
+ if (themeDefault !== void 0) {
305
+ return themeDefault;
306
+ }
307
+ if (blockDefault !== void 0) {
308
+ return blockDefault;
309
+ }
310
+ return key;
311
+ }
312
+ };
313
+ }
314
+ const GRID_V1_ENGINE_ID = "grid-v1";
315
+ const PAGE_ROOT_SLOT = "content";
316
+ const DEFAULT_GRID = { cols: 12, gap: 16, rowUnit: 40 };
317
+ const MAX_BLOCKS_PER_ROW = 3;
318
+ const DEFAULT_BREAKPOINTS = [
319
+ { id: "desktop", cols: 12 },
320
+ { id: "mobile", cols: 1, query: { maxWidth: 600 } }
321
+ ];
322
+ function sharesRowBand$1(a, b) {
323
+ return a.r < b.r + b.h && a.r + a.h > b.r;
324
+ }
325
+ function minFillCols(cols) {
326
+ return Math.max(1, Math.ceil(Math.max(1, cols) / MAX_BLOCKS_PER_ROW));
327
+ }
328
+ function clampRect(rect, cols) {
329
+ const w = Math.max(1, Math.min(rect.w, cols));
330
+ const c = Math.max(0, Math.min(rect.c, cols - w));
331
+ const h = Math.max(1, rect.h);
332
+ const r2 = Math.max(0, rect.r);
333
+ return { ...rect, c, r: r2, w, h };
334
+ }
335
+ function rectsOverlap(a, b) {
336
+ return a.c < b.c + b.w && a.c + a.w > b.c && a.r < b.r + b.h && a.r + a.h > b.r;
337
+ }
338
+ function readingOrder(items) {
339
+ return Object.keys(items).sort((idA, idB) => {
340
+ const a = items[idA];
341
+ const b = items[idB];
342
+ if (a.r !== b.r) return a.r - b.r;
343
+ return a.c - b.c;
344
+ });
345
+ }
346
+ function compactItems(items, cols) {
347
+ const columnBottoms = new Array(Math.max(1, cols)).fill(0);
348
+ const compacted = {};
349
+ for (const id of readingOrder(items)) {
350
+ const rect = clampRect(items[id], cols);
351
+ let top = 0;
352
+ for (let c = rect.c; c < rect.c + rect.w; c++) {
353
+ top = Math.max(top, columnBottoms[c] ?? 0);
354
+ }
355
+ compacted[id] = { ...rect, r: top };
356
+ for (let c = rect.c; c < rect.c + rect.w; c++) {
357
+ columnBottoms[c] = top + rect.h;
358
+ }
359
+ }
360
+ return compacted;
361
+ }
362
+ function rowBandBounds(items, target, cols, excludeId) {
363
+ let left = 0;
364
+ let right = Math.max(1, cols);
365
+ for (const [id, rect] of Object.entries(items)) {
366
+ if (id === excludeId) continue;
367
+ const sharesRow = rect.r < target.r + target.h && rect.r + rect.h > target.r;
368
+ if (!sharesRow) continue;
369
+ const rectRight = rect.c + rect.w;
370
+ if (rectRight <= target.c) {
371
+ left = Math.max(left, rectRight);
372
+ } else if (rect.c >= target.c + target.w) {
373
+ right = Math.min(right, rect.c);
374
+ }
375
+ }
376
+ return { left, right };
377
+ }
378
+ function fillSegmentBounds(target, nonFill, cols) {
379
+ let left = 0;
380
+ let right = Math.max(1, cols);
381
+ for (const rect of nonFill) {
382
+ if (!sharesRowBand$1(rect, target)) continue;
383
+ const rectRight = rect.c + rect.w;
384
+ if (rectRight <= target.c) {
385
+ left = Math.max(left, rectRight);
386
+ } else if (rect.c >= target.c) {
387
+ right = Math.min(right, rect.c);
388
+ } else {
389
+ left = Math.max(left, rectRight);
390
+ }
391
+ }
392
+ return { left, right: Math.max(left, right) };
393
+ }
394
+ function applyFillExpansion(items, cols) {
395
+ const next = {};
396
+ for (const id of readingOrder(items)) {
397
+ next[id] = items[id];
398
+ }
399
+ const fillIds = readingOrder(next).filter((id) => next[id].fill === true);
400
+ if (fillIds.length === 0) return next;
401
+ const nonFill = Object.values(next).filter((rect) => rect.fill !== true);
402
+ const groups = [];
403
+ for (const id of fillIds) {
404
+ const rect = next[id];
405
+ const seg = fillSegmentBounds(rect, nonFill, cols);
406
+ const group = groups.find(
407
+ (g) => g.left === seg.left && g.right === seg.right && g.members.some((memberId) => sharesRowBand$1(next[memberId], rect))
408
+ );
409
+ if (group) group.members.push(id);
410
+ else groups.push({ left: seg.left, right: seg.right, members: [id] });
411
+ }
412
+ const minCols = minFillCols(cols);
413
+ const overflow = [];
414
+ for (const group of groups) {
415
+ const span = Math.max(1, group.right - group.left);
416
+ const fit = Math.min(group.members.length, Math.floor(span / minCols));
417
+ if (fit <= 0) {
418
+ overflow.push(...group.members);
419
+ continue;
420
+ }
421
+ const staying = group.members.slice(0, fit);
422
+ overflow.push(...group.members.slice(fit));
423
+ const base = Math.floor(span / fit);
424
+ const remainder = span - base * fit;
425
+ let pos = group.left;
426
+ staying.forEach((id, index) => {
427
+ const w = base + (index < remainder ? 1 : 0);
428
+ next[id] = { ...next[id], c: pos, w: Math.max(1, w) };
429
+ pos += w;
430
+ });
431
+ }
432
+ if (overflow.length === 0) return next;
433
+ for (const id of overflow) {
434
+ const rect = next[id];
435
+ let bandBottom = rect.r;
436
+ for (const [otherId, other] of Object.entries(next)) {
437
+ if (otherId === id || overflow.includes(otherId)) continue;
438
+ if (sharesRowBand$1(other, rect)) {
439
+ bandBottom = Math.max(bandBottom, other.r + other.h);
440
+ }
441
+ }
442
+ next[id] = { ...next[id], c: 0, r: bandBottom, w: cols };
443
+ }
444
+ return compactItems(next, cols);
445
+ }
446
+ function findFreeRect(items, size, cols) {
447
+ const w = Math.max(1, Math.min(size.w, cols));
448
+ const h = Math.max(1, size.h);
449
+ const existing = Object.values(items);
450
+ for (let r2 = 0; ; r2++) {
451
+ for (let c = 0; c <= cols - w; c++) {
452
+ const candidate = { c, r: r2, w, h };
453
+ if (!existing.some((rect) => rectsOverlap(candidate, rect))) {
454
+ return candidate;
455
+ }
456
+ }
457
+ }
458
+ }
459
+ function deriveLayout(base, target) {
460
+ const cols = target.cols;
461
+ const items = {};
462
+ let r2 = 0;
463
+ for (const id of readingOrder(base.items)) {
464
+ const h = Math.max(1, base.items[id].h);
465
+ items[id] = clampRect({ c: 0, r: r2, w: cols, h }, cols);
466
+ r2 += h;
467
+ }
468
+ return { grid: { ...base.grid, cols }, items };
469
+ }
470
+ function resolveLayout(doc, breakpointId) {
471
+ var _a;
472
+ const present = doc.layouts[breakpointId];
473
+ if (present) return present;
474
+ const baseId = (_a = doc.breakpoints[0]) == null ? void 0 : _a.id;
475
+ const baseLayout = baseId ? doc.layouts[baseId] : void 0;
476
+ const target = doc.breakpoints.find((b) => b.id === breakpointId);
477
+ if (!baseLayout || !target) {
478
+ return { grid: { ...DEFAULT_GRID, cols: (target == null ? void 0 : target.cols) ?? 1 }, items: {} };
479
+ }
480
+ return deriveLayout(baseLayout, target);
481
+ }
482
+ function classifyRowDividers(items, blockIds) {
483
+ const leaderBlockIds = /* @__PURE__ */ new Set();
484
+ const rowBlockIds = /* @__PURE__ */ new Set();
485
+ const placed = blockIds.filter((id) => items[id] != null);
486
+ if (placed.length === 0) return { leaderBlockIds, rowBlockIds };
487
+ const rects = placed.map((id) => items[id]);
488
+ const minRow = Math.min(...rects.map((rect) => rect.r));
489
+ const boundaryIsCrossed = (boundary) => rects.some((rect) => rect.r < boundary && rect.r + rect.h > boundary);
490
+ const ordered = [...placed].sort((a, b) => {
491
+ const ra = items[a];
492
+ const rb = items[b];
493
+ return ra.r - rb.r || ra.c - rb.c;
494
+ });
495
+ let lastLeaderRow = null;
496
+ for (const id of ordered) {
497
+ const { r: r2 } = items[id];
498
+ if (r2 <= minRow || boundaryIsCrossed(r2)) continue;
499
+ rowBlockIds.add(id);
500
+ if (r2 !== lastLeaderRow) {
501
+ leaderBlockIds.add(id);
502
+ lastLeaderRow = r2;
503
+ }
504
+ }
505
+ return { leaderBlockIds, rowBlockIds };
506
+ }
507
+ function containerRule(scope, grid) {
508
+ return `${scope}{display:grid;grid-template-columns:repeat(${grid.cols},minmax(0,1fr));--juo-layout-cols:${grid.cols};--juo-layout-gap:var(--juo-layout-spacing,${grid.gap}px);column-gap:var(--juo-layout-gap);row-gap:0;margin-block-end:calc(-1 * var(--juo-layout-gap));}`;
509
+ }
510
+ function baseSpacingRule(scope) {
511
+ return `${scope} > [data-block-id]{margin-block-end:var(--juo-layout-gap);}`;
512
+ }
513
+ function collapseRule(scope) {
514
+ return `${scope} > [data-empty],${scope} > :has(> [data-empty]){margin-block-end:0;}`;
515
+ }
516
+ function itemRule(scope, blockId, rect, divider) {
517
+ return `${scope} > [data-block-id="${blockId}"]{grid-column:${rect.c + 1}/span ${rect.w};grid-row:${rect.r + 1}/span ${rect.h};--juo-layout-c:${rect.c};--juo-divider-row:${divider.row ? 1 : 0};--juo-divider-line:${divider.line ? 1 : 0};}`;
518
+ }
519
+ function breakpointCss(scope, layout, domOrder) {
520
+ const { leaderBlockIds, rowBlockIds } = classifyRowDividers(
521
+ layout.items,
522
+ domOrder
523
+ );
524
+ const rules = [containerRule(scope, layout.grid)];
525
+ for (const blockId of Object.keys(layout.items)) {
526
+ rules.push(
527
+ itemRule(scope, blockId, layout.items[blockId], {
528
+ row: rowBlockIds.has(blockId),
529
+ line: leaderBlockIds.has(blockId)
530
+ })
531
+ );
532
+ }
533
+ return rules.join("");
534
+ }
535
+ function sharesRowBand(a, b) {
536
+ return a.r < b.r + b.h && a.r + a.h > b.r;
537
+ }
538
+ function nonEmptySubsets(ids) {
539
+ const out = [];
540
+ for (let mask = 1; mask < 1 << ids.length; mask++) {
541
+ const subset = [];
542
+ for (let i = 0; i < ids.length; i++) {
543
+ if (mask & 1 << i) subset.push(ids[i]);
544
+ }
545
+ out.push(subset);
546
+ }
547
+ return out;
548
+ }
549
+ function reclaimSelector(scope, fillId, emptyMates, domIndex) {
550
+ const fillIdx = domIndex.get(fillId) ?? 0;
551
+ const byDom = (a, b) => (domIndex.get(a) ?? 0) - (domIndex.get(b) ?? 0);
552
+ const before = emptyMates.filter((id) => (domIndex.get(id) ?? 0) < fillIdx).sort(byDom);
553
+ const after = emptyMates.filter((id) => (domIndex.get(id) ?? 0) > fillIdx).sort(byDom);
554
+ const emptyBefore = (id) => `[data-block-id="${id}"]:is([data-empty],:has(> [data-empty]))`;
555
+ const emptyAfterHas = (id) => `~ [data-block-id="${id}"][data-empty],~ [data-block-id="${id}"] > [data-empty]`;
556
+ let sel = "";
557
+ for (const id of before) sel += `${emptyBefore(id)} ~ `;
558
+ sel += `[data-block-id="${fillId}"]`;
559
+ for (const id of after) sel += `:has(${emptyAfterHas(id)})`;
560
+ return `${scope} > ${sel}`;
561
+ }
562
+ function reclaimCss(scope, layout, domOrder) {
563
+ const items = layout.items;
564
+ const cols = layout.grid.cols;
565
+ const domIndex = new Map(domOrder.map((id, index) => [id, index]));
566
+ const rules = [];
567
+ for (const [fillId, fillRect] of Object.entries(items)) {
568
+ if (fillRect.fill !== true) continue;
569
+ const mateIds = Object.entries(items).filter(([id, rect]) => id !== fillId && sharesRowBand(rect, fillRect)).map(([id]) => id);
570
+ if (mateIds.length === 0 || mateIds.length > 4) continue;
571
+ for (const emptyMates of nonEmptySubsets(mateIds)) {
572
+ const remaining = {};
573
+ for (const [id, rect] of Object.entries(items)) {
574
+ if (id === fillId || emptyMates.includes(id)) continue;
575
+ remaining[id] = rect;
576
+ }
577
+ const { left, right } = rowBandBounds(remaining, fillRect, cols);
578
+ if (left >= fillRect.c && right <= fillRect.c + fillRect.w) continue;
579
+ const selector = reclaimSelector(scope, fillId, emptyMates, domIndex);
580
+ rules.push(
581
+ `${selector}{grid-column:${left + 1}/span ${Math.max(1, right - left)};--juo-layout-c:${left};}`
582
+ );
583
+ }
584
+ }
585
+ return rules.join("");
586
+ }
587
+ function projectToCss(doc, opts) {
588
+ const base = doc.breakpoints[0];
589
+ if (!base) return "";
590
+ const baseLayout = resolveLayout(doc, base.id);
591
+ const domOrder = opts.domOrder ?? Object.keys(baseLayout.items);
592
+ const parts = [
593
+ breakpointCss(opts.scope, baseLayout, domOrder),
594
+ baseSpacingRule(opts.scope),
595
+ collapseRule(opts.scope),
596
+ reclaimCss(opts.scope, baseLayout, domOrder)
597
+ ];
598
+ for (const bp of doc.breakpoints.slice(1)) {
599
+ if (!bp.query) continue;
600
+ parts.push(
601
+ `@container (max-width:${bp.query.maxWidth}px){` + breakpointCss(opts.scope, resolveLayout(doc, bp.id), domOrder) + `}`
602
+ );
603
+ }
604
+ return parts.join("");
605
+ }
606
+ function createDefaultLayoutDocument(blockIds) {
607
+ const items = {};
608
+ blockIds.forEach((id, index) => {
609
+ items[id] = { c: 0, r: index, w: DEFAULT_GRID.cols, h: 1 };
610
+ });
611
+ return {
612
+ version: 1,
613
+ engine: GRID_V1_ENGINE_ID,
614
+ breakpoints: structuredClone([...DEFAULT_BREAKPOINTS]),
615
+ layouts: {
616
+ [DEFAULT_BREAKPOINTS[0].id]: { grid: { ...DEFAULT_GRID }, items }
617
+ }
618
+ };
619
+ }
620
+ function colsForBreakpoint(doc, breakpointId, layout) {
621
+ var _a;
622
+ return ((_a = doc.breakpoints.find((b) => b.id === breakpointId)) == null ? void 0 : _a.cols) ?? layout.grid.cols;
623
+ }
624
+ function reconcileBreakpointLayout(layout, blockIds, cols) {
625
+ const known = new Set(blockIds);
626
+ for (const id of Object.keys(layout.items)) {
627
+ if (!known.has(id)) delete layout.items[id];
628
+ }
629
+ for (const id of blockIds) {
630
+ if (!layout.items[id]) {
631
+ layout.items[id] = findFreeRect(layout.items, { w: cols, h: 1 }, cols);
632
+ }
633
+ }
634
+ }
635
+ function reconcileLayout(doc, blockIds) {
636
+ var _a;
637
+ if (!doc) return createDefaultLayoutDocument(blockIds);
638
+ const next = structuredClone(doc);
639
+ const baseId = (_a = next.breakpoints[0]) == null ? void 0 : _a.id;
640
+ if (!baseId) return createDefaultLayoutDocument(blockIds);
641
+ for (const def of DEFAULT_BREAKPOINTS) {
642
+ if (!next.breakpoints.some((b) => b.id === def.id)) {
643
+ next.breakpoints.push(structuredClone(def));
644
+ }
645
+ }
646
+ next.layouts[baseId] = next.layouts[baseId] ?? {
647
+ grid: { ...DEFAULT_GRID },
648
+ items: {}
649
+ };
650
+ for (const breakpointId of Object.keys(next.layouts)) {
651
+ const layout = next.layouts[breakpointId];
652
+ if (!layout) continue;
653
+ reconcileBreakpointLayout(
654
+ layout,
655
+ blockIds,
656
+ colsForBreakpoint(next, breakpointId, layout)
657
+ );
658
+ }
659
+ return next;
660
+ }
661
+ function compactLayoutDocument(doc) {
662
+ if (!doc) return doc;
663
+ const next = structuredClone(doc);
664
+ for (const breakpointId of Object.keys(next.layouts)) {
665
+ const layout = next.layouts[breakpointId];
666
+ if (!layout) continue;
667
+ layout.items = compactItems(
668
+ layout.items,
669
+ colsForBreakpoint(next, breakpointId, layout)
670
+ );
671
+ }
672
+ return next;
673
+ }
674
+ function expandFillLayoutDocument(doc) {
675
+ if (!doc) return doc;
676
+ const next = structuredClone(doc);
677
+ for (const breakpointId of Object.keys(next.layouts)) {
678
+ const layout = next.layouts[breakpointId];
679
+ if (!layout) continue;
680
+ layout.items = applyFillExpansion(
681
+ layout.items,
682
+ colsForBreakpoint(next, breakpointId, layout)
683
+ );
684
+ }
685
+ return next;
686
+ }
687
+ const LAYOUT_SCOPE_ATTR = "data-juo-layout";
688
+ function layoutScopeSelector(scopeId) {
689
+ return `[${LAYOUT_SCOPE_ATTR}="${scopeId}"]`;
690
+ }
691
+ function buildLayoutCss(layout, blockIds, scopeId) {
692
+ const reconciled = reconcileLayout(layout, blockIds);
693
+ return projectToCss(reconciled, {
694
+ scope: layoutScopeSelector(scopeId),
695
+ domOrder: blockIds
696
+ });
697
+ }
698
+ function buildGridLayout(layout, blockIds, scopeId) {
699
+ var _a, _b;
700
+ const scope = layoutScopeSelector(scopeId);
701
+ const reconciled = reconcileLayout(layout, blockIds);
702
+ const baseId = (_a = reconciled.breakpoints[0]) == null ? void 0 : _a.id;
703
+ const layoutItems = (baseId != null ? (_b = reconciled.layouts[baseId]) == null ? void 0 : _b.items : null) ?? {};
704
+ const { leaderBlockIds, rowBlockIds } = classifyRowDividers(
705
+ layoutItems,
706
+ blockIds
707
+ );
708
+ const fullWidthBlockIds = /* @__PURE__ */ new Set();
709
+ for (const [id, rect] of Object.entries(layoutItems)) {
710
+ if (rect.fill === true) fullWidthBlockIds.add(id);
711
+ }
712
+ return {
713
+ css: projectToCss(reconciled, { scope, domOrder: blockIds }),
714
+ dividerBlockIds: leaderBlockIds,
715
+ dividerRowBlockIds: rowBlockIds,
716
+ fullWidthBlockIds
717
+ };
718
+ }
719
+ export {
720
+ DEFAULT_GRID as D,
721
+ GRID_V1_ENGINE_ID as G,
722
+ LAYOUT_SCOPE_ATTR as L,
723
+ MAX_BLOCKS_PER_ROW as M,
724
+ PAGE_ROOT_SLOT as P,
725
+ TranslationContext as T,
726
+ ThemeStateContext as a,
727
+ buildGridLayout as b,
728
+ reconcileLayout as c,
729
+ clampRect as d,
730
+ applyFillExpansion as e,
731
+ compactItems as f,
732
+ findFreeRect as g,
733
+ DEFAULT_BREAKPOINTS as h,
734
+ DEFAULT_GLOBAL_STYLES as i,
735
+ buildLayoutCss as j,
736
+ classifyRowDividers as k,
737
+ compactLayoutDocument as l,
738
+ createDefaultLayoutDocument as m,
739
+ createThemeState as n,
740
+ createTranslationService as o,
741
+ deriveLayout as p,
742
+ expandFillLayoutDocument as q,
743
+ resolveLayout as r,
744
+ indexOverrides as s,
745
+ layoutScopeSelector as t,
746
+ projectToCss as u,
747
+ readingOrder as v,
748
+ rectsOverlap as w
749
+ };