@riverbankcms/sdk 0.72.0 → 0.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{PreviewEditorSidebar-44T64SAR.mjs → PreviewEditorSidebar-U2IHCBYN.mjs} +3 -3
- package/dist/{PreviewEditorUI-4WKHZTXW.mjs → PreviewEditorUI-ZGH2RQNP.mjs} +3 -3
- package/dist/SdkPreviewModeRuntime-MTUGBTLQ.mjs +8 -0
- package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -10
- package/dist/_dts/api/src/cache-tags.d.ts +22 -0
- package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
- package/dist/_dts/api/src/endpoints.d.ts +24 -24
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
- package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -1
- package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
- package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
- package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
- package/dist/_dts/blocks/src/client/events.d.ts +4 -0
- package/dist/_dts/blocks/src/client/form.d.ts +2 -0
- package/dist/_dts/blocks/src/client/header.d.ts +1 -0
- package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
- package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
- package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
- package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +6 -6
- package/dist/_dts/blocks/src/system/node/fragments/backgroundLayer.d.ts +15 -1
- package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +11 -0
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/header/enhanceHeaderSection.d.ts +13 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +6 -0
- package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
- package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/accordion.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/bookingForm.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/carousel.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/cart.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/checkout.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCalendar.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCombined.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/eventDetails.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/eventListing.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/eventRegistration.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/form.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/headerSection.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/locationMap.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/newsletterForm.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/productDetail.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/productList.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/enhancers/shop.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/islands/hydrateBlocksIslands.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/islands/propsDecoder.d.ts +7 -0
- package/dist/_dts/sdk/src/rendering/islands/types.d.ts +9 -0
- package/dist/_dts/sdk/src/rendering/server.d.ts +3 -0
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
- package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +7 -7
- package/dist/_dts/theme-core/src/buttons/types.d.ts +20 -20
- package/dist/_dts/theme-core/src/cards/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/header/navDropdownSizing.d.ts +7 -0
- package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
- package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +156 -156
- package/dist/_dts/theme-core/src/navigation/types.d.ts +1 -1
- package/dist/_dts/theme-core/src/palette/variants/types.d.ts +4 -4
- package/dist/_dts/theme-core/src/schema.d.ts +178 -178
- package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +8 -8
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +5 -5
- package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -2
- package/dist/{chunk-G4NLITC2.mjs → chunk-BGMNDF6T.mjs} +7 -7
- package/dist/{chunk-3YNCQG5N.mjs → chunk-GFE74WRD.mjs} +457 -98
- package/dist/{chunk-HV745JYE.mjs → chunk-RWXQBRQZ.mjs} +1 -1
- package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
- package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
- package/dist/{chunk-KWQPAJYS.mjs → chunk-ZSHFGFUG.mjs} +2 -2
- package/dist/cli/index.mjs +3498 -3826
- package/dist/client/accordion-T2UD2ZTH.mjs +120 -0
- package/dist/client/altcha-LIGLPZS5.mjs +2755 -0
- package/dist/client/bookingForm-GUP75FKN.mjs +3022 -0
- package/dist/client/bookings.mjs +32 -10
- package/dist/client/carousel-2NQA6V57.mjs +47 -0
- package/dist/client/cart-5TFIAFDS.mjs +18 -0
- package/dist/client/checkout-TP4WAHZE.mjs +18 -0
- package/dist/client/chunk-2PHQZ666.mjs +383 -0
- package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
- package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
- package/dist/client/chunk-CY2ZTSE5.mjs +204 -0
- package/dist/client/chunk-F7LHOKEH.mjs +146 -0
- package/dist/client/chunk-FU2QRZMX.mjs +7617 -0
- package/dist/client/chunk-I2MMZO53.mjs +6 -0
- package/dist/client/chunk-II7O4XN3.mjs +2206 -0
- package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
- package/dist/client/chunk-N7PBWBWQ.mjs +26 -0
- package/dist/client/chunk-NWOUL6JY.mjs +1378 -0
- package/dist/client/chunk-OJPZEZU2.mjs +31 -0
- package/dist/client/chunk-PMAIXMAB.mjs +1960 -0
- package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
- package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
- package/dist/client/chunk-VUAOE3AG.mjs +5592 -0
- package/dist/client/chunk-WJXXNDSE.mjs +245 -0
- package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
- package/dist/client/chunk-ZLMS67RR.mjs +106 -0
- package/dist/client/client.mjs +51865 -52071
- package/dist/client/courseRegistration-5DPU6PDY.mjs +1737 -0
- package/dist/client/eventCalendar-F3GZGTEF.mjs +40 -0
- package/dist/client/eventCombined-BQOB6QMY.mjs +37 -0
- package/dist/client/eventDetails-PEM2EJWE.mjs +25 -0
- package/dist/client/eventListing-YMIQPVME.mjs +40 -0
- package/dist/client/eventRegistration-4I6ZNDUF.mjs +40 -0
- package/dist/client/form-ZJVAYZ6G.mjs +300 -0
- package/dist/client/headerSection-TOT5MGTF.mjs +729 -0
- package/dist/client/hooks.mjs +91 -42
- package/dist/client/locationMap-J66NZREU.mjs +227 -0
- package/dist/client/newsletterForm-ET2XUMRO.mjs +208 -0
- package/dist/client/productDetail-C2XIH7C5.mjs +18 -0
- package/dist/client/productList-T2AZLFTP.mjs +18 -0
- package/dist/client/rendering/client.mjs +12796 -18295
- package/dist/client/rendering/islands.mjs +108 -44022
- package/dist/client/rendering.mjs +45141 -45346
- package/dist/client/shop-UZ6IUZXD.mjs +20 -0
- package/dist/preview-next/before-render.mjs +37 -25
- package/dist/preview-next/client/runtime.mjs +5 -5
- package/dist/preview-next/middleware.mjs +37 -25
- package/dist/{sdk-runtime-NGDWSWOS.mjs → sdk-runtime-JCUQM63Y.mjs} +6 -6
- package/dist/server/components.mjs +472 -276
- package/dist/server/config-validation.mjs +91 -42
- package/dist/server/config.mjs +91 -42
- package/dist/server/data.mjs +91 -42
- package/dist/server/index.mjs +45 -33
- package/dist/server/next.mjs +468 -272
- package/dist/server/page-converter.mjs +41 -17
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +556 -275
- package/dist/server/rendering.mjs +474 -278
- package/dist/server/routing.mjs +99 -43
- package/dist/server/server.mjs +92 -43
- package/dist/server/theme-bridge.mjs +29 -0
- package/dist/styles/index.css +16 -0
- package/package.json +2 -1
- package/dist/SdkPreviewModeRuntime-FO6V7YVY.mjs +0 -8
|
@@ -0,0 +1,1960 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
4
|
+
function r(e) {
|
|
5
|
+
var t, f, n = "";
|
|
6
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
7
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
8
|
+
var o = e.length;
|
|
9
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
10
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
11
|
+
return n;
|
|
12
|
+
}
|
|
13
|
+
function clsx() {
|
|
14
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
var clsx_default = clsx;
|
|
18
|
+
|
|
19
|
+
// ../core/src/branded.ts
|
|
20
|
+
var asMediaAssetId = (id) => id;
|
|
21
|
+
var asFormId = (id) => id;
|
|
22
|
+
var asPassId = (id) => id;
|
|
23
|
+
var asCustomerPassId = (id) => id;
|
|
24
|
+
var asAppointmentServiceId = (id) => id;
|
|
25
|
+
var asAppointmentResourceId = (id) => id;
|
|
26
|
+
|
|
27
|
+
// ../core/src/date-math.ts
|
|
28
|
+
function addDaysToDate(date, dayCount) {
|
|
29
|
+
const next = new Date(date);
|
|
30
|
+
next.setUTCDate(next.getUTCDate() + dayCount);
|
|
31
|
+
return next;
|
|
32
|
+
}
|
|
33
|
+
function addDaysToIso(isoString, dayCount) {
|
|
34
|
+
const date = new Date(isoString);
|
|
35
|
+
if (!Number.isFinite(date.getTime())) {
|
|
36
|
+
return isoString;
|
|
37
|
+
}
|
|
38
|
+
return addDaysToDate(date, dayCount).toISOString();
|
|
39
|
+
}
|
|
40
|
+
function subtractDaysFromIso(isoString, dayCount) {
|
|
41
|
+
return addDaysToIso(isoString, -dayCount);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ../core/src/booking-flexible-balance.ts
|
|
45
|
+
function clampFlexibleBalanceConfiguredAmount(amountCents, totalAmountCents) {
|
|
46
|
+
return Math.max(0, Math.min(amountCents, totalAmountCents));
|
|
47
|
+
}
|
|
48
|
+
function resolveFlexibleBalanceInitialPaymentCents(input) {
|
|
49
|
+
return clampFlexibleBalanceConfiguredAmount(
|
|
50
|
+
input.config.upfrontAmountCents,
|
|
51
|
+
input.totalAmountCents
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
function resolveFlexibleBalanceDueAt(input) {
|
|
55
|
+
switch (input.dueDateRule.kind) {
|
|
56
|
+
case "relative_to_start_date":
|
|
57
|
+
return subtractDaysFromIso(
|
|
58
|
+
input.bookingStartAt,
|
|
59
|
+
input.dueDateRule.daysBeforeStart
|
|
60
|
+
);
|
|
61
|
+
case "fixed_calendar_date":
|
|
62
|
+
return input.dueDateRule.dueAt;
|
|
63
|
+
default:
|
|
64
|
+
return assertNever(input.dueDateRule);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function assertNever(value) {
|
|
68
|
+
throw new Error(`Unexpected value: ${String(value)}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ../core/src/booking-instalments.ts
|
|
72
|
+
function isDepositBearingBookingInstalmentPlan(plan) {
|
|
73
|
+
switch (plan.kind) {
|
|
74
|
+
case "deposit_plus_one_remainder":
|
|
75
|
+
case "deposit_plus_scheduled_instalments":
|
|
76
|
+
return true;
|
|
77
|
+
case "equal_scheduled_instalments":
|
|
78
|
+
return false;
|
|
79
|
+
default:
|
|
80
|
+
return assertNever2(plan);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getBookingInstalmentDepositRefundability(plan) {
|
|
84
|
+
return isDepositBearingBookingInstalmentPlan(plan) ? plan.depositRefundability : null;
|
|
85
|
+
}
|
|
86
|
+
function clampConfiguredAmount(amountCents, totalAmountCents) {
|
|
87
|
+
return Math.max(0, Math.min(amountCents, totalAmountCents));
|
|
88
|
+
}
|
|
89
|
+
function splitAmountWithRemainderInFirst(totalAmountCents, partCount) {
|
|
90
|
+
if (partCount <= 0) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
const baseAmountCents = Math.floor(totalAmountCents / partCount);
|
|
94
|
+
const remainderCents = totalAmountCents - baseAmountCents * partCount;
|
|
95
|
+
return Array.from({ length: partCount }, (_, index) => index === 0 ? baseAmountCents + remainderCents : baseAmountCents);
|
|
96
|
+
}
|
|
97
|
+
function addIntervalPreservingMonthAnchor(isoString, intervalCount, intervalUnit) {
|
|
98
|
+
const date = new Date(isoString);
|
|
99
|
+
if (!Number.isFinite(date.getTime())) {
|
|
100
|
+
return isoString;
|
|
101
|
+
}
|
|
102
|
+
switch (intervalUnit) {
|
|
103
|
+
case "day":
|
|
104
|
+
date.setUTCDate(date.getUTCDate() + intervalCount);
|
|
105
|
+
return date.toISOString();
|
|
106
|
+
case "week":
|
|
107
|
+
date.setUTCDate(date.getUTCDate() + intervalCount * 7);
|
|
108
|
+
return date.toISOString();
|
|
109
|
+
case "month":
|
|
110
|
+
return addMonthsPreservingAnchorDay(date, intervalCount).toISOString();
|
|
111
|
+
default:
|
|
112
|
+
return assertNever2(intervalUnit);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function getBookingInstalmentPlanIntervalCount(plan) {
|
|
116
|
+
switch (plan.kind) {
|
|
117
|
+
case "deposit_plus_one_remainder":
|
|
118
|
+
return plan.remainderDueCount;
|
|
119
|
+
case "deposit_plus_scheduled_instalments":
|
|
120
|
+
case "equal_scheduled_instalments":
|
|
121
|
+
return plan.intervalCount;
|
|
122
|
+
default:
|
|
123
|
+
return assertNever2(plan);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function omitZeroAmountFutureRows(rows) {
|
|
127
|
+
if (rows.length <= 1) {
|
|
128
|
+
return rows;
|
|
129
|
+
}
|
|
130
|
+
const [firstRow, ...futureRows] = rows;
|
|
131
|
+
if (!firstRow) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
return [
|
|
135
|
+
firstRow,
|
|
136
|
+
...futureRows.filter((row) => row.amountCents > 0)
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
function addMonthsPreservingAnchorDay(date, intervalCount) {
|
|
140
|
+
const anchorDay = date.getUTCDate();
|
|
141
|
+
const nextMonth = new Date(Date.UTC(
|
|
142
|
+
date.getUTCFullYear(),
|
|
143
|
+
date.getUTCMonth() + intervalCount,
|
|
144
|
+
1,
|
|
145
|
+
date.getUTCHours(),
|
|
146
|
+
date.getUTCMinutes(),
|
|
147
|
+
date.getUTCSeconds(),
|
|
148
|
+
date.getUTCMilliseconds()
|
|
149
|
+
));
|
|
150
|
+
const lastDayOfTargetMonth = new Date(Date.UTC(
|
|
151
|
+
nextMonth.getUTCFullYear(),
|
|
152
|
+
nextMonth.getUTCMonth() + 1,
|
|
153
|
+
0
|
|
154
|
+
)).getUTCDate();
|
|
155
|
+
nextMonth.setUTCDate(Math.min(anchorDay, lastDayOfTargetMonth));
|
|
156
|
+
return nextMonth;
|
|
157
|
+
}
|
|
158
|
+
function assertNever2(value) {
|
|
159
|
+
throw new Error(`Unexpected value: ${String(value)}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ../core/src/result.ts
|
|
163
|
+
function ok(value) {
|
|
164
|
+
return { ok: true, value };
|
|
165
|
+
}
|
|
166
|
+
function err(error) {
|
|
167
|
+
return { ok: false, error };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ../core/src/booking-date-time.ts
|
|
171
|
+
var DEFAULT_LOCALE = "en-US";
|
|
172
|
+
var FALLBACK_TIMEZONE = "UTC";
|
|
173
|
+
var LOCAL_DATE_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/u;
|
|
174
|
+
function isValidTimeZone(timeZone) {
|
|
175
|
+
try {
|
|
176
|
+
new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
|
|
177
|
+
return true;
|
|
178
|
+
} catch {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function getSafeTimeZone(timeZone) {
|
|
183
|
+
const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
|
|
184
|
+
return normalized && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
|
|
185
|
+
}
|
|
186
|
+
function parseStrictBookingTimeZone(timeZone) {
|
|
187
|
+
const normalized = timeZone.trim();
|
|
188
|
+
if (!normalized || !isValidTimeZone(normalized)) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
return normalized;
|
|
192
|
+
}
|
|
193
|
+
function formatParseError(error) {
|
|
194
|
+
switch (error.reason) {
|
|
195
|
+
case "invalid_starts_at":
|
|
196
|
+
return `Expected a valid UTC/offset-aware ISO datetime in startsAt, received "${error.value}"`;
|
|
197
|
+
case "invalid_ends_at":
|
|
198
|
+
return `Expected a valid UTC/offset-aware ISO datetime in endsAt, received "${error.value ?? ""}"`;
|
|
199
|
+
case "invalid_time_zone":
|
|
200
|
+
return `Expected a valid IANA timezone in timeZone, received "${error.value}"`;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function formatToPartsLookup(date, locale, timeZone, format) {
|
|
204
|
+
return new Map(
|
|
205
|
+
new Intl.DateTimeFormat(locale, {
|
|
206
|
+
...format,
|
|
207
|
+
timeZone
|
|
208
|
+
}).formatToParts(date).map((part) => [part.type, part.value])
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
function getZonedDateTimeParts(date, timeZone) {
|
|
212
|
+
const parts = formatToPartsLookup(date, "en-GB", timeZone, {
|
|
213
|
+
year: "numeric",
|
|
214
|
+
month: "2-digit",
|
|
215
|
+
day: "2-digit",
|
|
216
|
+
hour: "2-digit",
|
|
217
|
+
minute: "2-digit",
|
|
218
|
+
second: "2-digit",
|
|
219
|
+
hour12: false
|
|
220
|
+
});
|
|
221
|
+
const read = (type) => Number(parts.get(type) ?? "");
|
|
222
|
+
return {
|
|
223
|
+
year: read("year"),
|
|
224
|
+
month: read("month"),
|
|
225
|
+
day: read("day"),
|
|
226
|
+
hour: read("hour"),
|
|
227
|
+
minute: read("minute"),
|
|
228
|
+
second: read("second")
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function formatDateKey(date) {
|
|
232
|
+
const year = String(date.year).padStart(4, "0");
|
|
233
|
+
const month = String(date.month).padStart(2, "0");
|
|
234
|
+
const day = String(date.day).padStart(2, "0");
|
|
235
|
+
return `${year}-${month}-${day}`;
|
|
236
|
+
}
|
|
237
|
+
function toBookingTimeZone(timeZone) {
|
|
238
|
+
return getSafeTimeZone(timeZone);
|
|
239
|
+
}
|
|
240
|
+
var DEFAULT_BOOKING_TIME_ZONE = FALLBACK_TIMEZONE;
|
|
241
|
+
function resolveBookingTimeZoneId(...candidates) {
|
|
242
|
+
for (const candidate of candidates) {
|
|
243
|
+
const normalized = typeof candidate === "string" ? candidate.trim() : "";
|
|
244
|
+
if (normalized && isValidTimeZone(normalized)) {
|
|
245
|
+
return normalized;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return FALLBACK_TIMEZONE;
|
|
249
|
+
}
|
|
250
|
+
function parseUtcIsoDateTimeString(value) {
|
|
251
|
+
const normalized = value.trim();
|
|
252
|
+
const hasUtcSuffix = normalized.endsWith("Z");
|
|
253
|
+
const hasExplicitOffset = /[+-]\d{2}:\d{2}$/u.test(normalized);
|
|
254
|
+
if (!hasUtcSuffix && !hasExplicitOffset) {
|
|
255
|
+
return err("missing-timezone-offset");
|
|
256
|
+
}
|
|
257
|
+
const date = new Date(normalized);
|
|
258
|
+
if (Number.isNaN(date.getTime())) {
|
|
259
|
+
return err("invalid-date-time");
|
|
260
|
+
}
|
|
261
|
+
return ok(date.toISOString());
|
|
262
|
+
}
|
|
263
|
+
function toUtcIsoDateTimeString(value) {
|
|
264
|
+
const parsed = parseUtcIsoDateTimeString(value);
|
|
265
|
+
if (!parsed.ok) {
|
|
266
|
+
const message = parsed.error === "missing-timezone-offset" ? `Expected an offset-aware ISO datetime, received "${value}"` : `Expected a valid ISO datetime, received "${value}"`;
|
|
267
|
+
throw new Error(message);
|
|
268
|
+
}
|
|
269
|
+
return parsed.value;
|
|
270
|
+
}
|
|
271
|
+
function parseScheduledBookingDateTime(input) {
|
|
272
|
+
try {
|
|
273
|
+
const startsAt = toUtcIsoDateTimeString(input.startsAt);
|
|
274
|
+
const timeZone = parseStrictBookingTimeZone(input.timeZone);
|
|
275
|
+
if (!timeZone) {
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
field: "timeZone",
|
|
279
|
+
reason: "invalid_time_zone",
|
|
280
|
+
value: input.timeZone
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
ok: true,
|
|
285
|
+
value: {
|
|
286
|
+
startsAt,
|
|
287
|
+
timeZone,
|
|
288
|
+
locale: input.locale
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
} catch {
|
|
292
|
+
return {
|
|
293
|
+
ok: false,
|
|
294
|
+
field: "startsAt",
|
|
295
|
+
reason: "invalid_starts_at",
|
|
296
|
+
value: input.startsAt
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function parseScheduledBookingDateRange(input) {
|
|
301
|
+
const start = parseScheduledBookingDateTime(input);
|
|
302
|
+
if (!start.ok) {
|
|
303
|
+
return start;
|
|
304
|
+
}
|
|
305
|
+
if (input.endsAt == null) {
|
|
306
|
+
return {
|
|
307
|
+
ok: true,
|
|
308
|
+
value: start.value
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
return {
|
|
313
|
+
ok: true,
|
|
314
|
+
value: {
|
|
315
|
+
...start.value,
|
|
316
|
+
endsAt: toUtcIsoDateTimeString(input.endsAt)
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
} catch {
|
|
320
|
+
return {
|
|
321
|
+
ok: false,
|
|
322
|
+
field: "endsAt",
|
|
323
|
+
reason: "invalid_ends_at",
|
|
324
|
+
value: input.endsAt
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function toScheduledBookingDateTime(input) {
|
|
329
|
+
const result = parseScheduledBookingDateTime(input);
|
|
330
|
+
if (result.ok) {
|
|
331
|
+
return result.value;
|
|
332
|
+
}
|
|
333
|
+
throw new Error(formatParseError(result));
|
|
334
|
+
}
|
|
335
|
+
function toScheduledBookingDateRange(input) {
|
|
336
|
+
const result = parseScheduledBookingDateRange(input);
|
|
337
|
+
if (result.ok) {
|
|
338
|
+
return result.value;
|
|
339
|
+
}
|
|
340
|
+
throw new Error(formatParseError(result));
|
|
341
|
+
}
|
|
342
|
+
function formatBookingInstant(isoString, options) {
|
|
343
|
+
const date = new Date(isoString);
|
|
344
|
+
if (Number.isNaN(date.getTime())) {
|
|
345
|
+
return isoString;
|
|
346
|
+
}
|
|
347
|
+
return new Intl.DateTimeFormat(options.locale ?? DEFAULT_LOCALE, {
|
|
348
|
+
...options.format,
|
|
349
|
+
timeZone: getSafeTimeZone(options.timeZone)
|
|
350
|
+
}).format(date);
|
|
351
|
+
}
|
|
352
|
+
function formatBookingDate(input, format = {
|
|
353
|
+
weekday: "long",
|
|
354
|
+
year: "numeric",
|
|
355
|
+
month: "long",
|
|
356
|
+
day: "numeric"
|
|
357
|
+
}) {
|
|
358
|
+
return formatBookingInstant(input.startsAt, {
|
|
359
|
+
locale: input.locale,
|
|
360
|
+
timeZone: input.timeZone,
|
|
361
|
+
format
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function formatBookingTime(input, format = {
|
|
365
|
+
hour: "numeric",
|
|
366
|
+
minute: "2-digit",
|
|
367
|
+
hour12: true
|
|
368
|
+
}) {
|
|
369
|
+
return formatBookingInstant(input.startsAt, {
|
|
370
|
+
locale: input.locale,
|
|
371
|
+
timeZone: input.timeZone,
|
|
372
|
+
format
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function formatBookingDateTime(input, format = {
|
|
376
|
+
weekday: "short",
|
|
377
|
+
month: "short",
|
|
378
|
+
day: "numeric",
|
|
379
|
+
hour: "numeric",
|
|
380
|
+
minute: "2-digit"
|
|
381
|
+
}) {
|
|
382
|
+
return formatBookingInstant(input.startsAt, {
|
|
383
|
+
locale: input.locale,
|
|
384
|
+
timeZone: input.timeZone,
|
|
385
|
+
format
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
function formatBookingDateParts(input, options) {
|
|
389
|
+
return {
|
|
390
|
+
date: formatBookingDate(
|
|
391
|
+
input,
|
|
392
|
+
options?.dateFormat ?? {
|
|
393
|
+
weekday: "short",
|
|
394
|
+
month: "short",
|
|
395
|
+
day: "numeric",
|
|
396
|
+
year: "numeric"
|
|
397
|
+
}
|
|
398
|
+
),
|
|
399
|
+
time: formatBookingTime(
|
|
400
|
+
input,
|
|
401
|
+
options?.timeFormat ?? {
|
|
402
|
+
hour: "numeric",
|
|
403
|
+
minute: "2-digit",
|
|
404
|
+
hour12: true
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
function getBookingLocalDateKey(input) {
|
|
410
|
+
return formatDateKey(getLocalScheduleDate(new Date(input.startsAt), input.timeZone));
|
|
411
|
+
}
|
|
412
|
+
function parseBookingLocalDate(value) {
|
|
413
|
+
const match = LOCAL_DATE_PATTERN.exec(value.trim());
|
|
414
|
+
if (!match?.groups) {
|
|
415
|
+
throw new Error(`Invalid booking date format: "${value}" (expected YYYY-MM-DD)`);
|
|
416
|
+
}
|
|
417
|
+
const year = Number(match.groups.year);
|
|
418
|
+
const month = Number(match.groups.month);
|
|
419
|
+
const day = Number(match.groups.day);
|
|
420
|
+
const candidate = new Date(Date.UTC(year, month - 1, day, 12, 0, 0));
|
|
421
|
+
if (Number.isNaN(candidate.getTime()) || candidate.getUTCFullYear() !== year || candidate.getUTCMonth() + 1 !== month || candidate.getUTCDate() !== day) {
|
|
422
|
+
throw new Error(`Invalid booking date format: "${value}" (expected YYYY-MM-DD)`);
|
|
423
|
+
}
|
|
424
|
+
return { year, month, day };
|
|
425
|
+
}
|
|
426
|
+
function getLocalScheduleDate(date, timeZone) {
|
|
427
|
+
const parts = getZonedDateTimeParts(date, getSafeTimeZone(timeZone));
|
|
428
|
+
return { year: parts.year, month: parts.month, day: parts.day };
|
|
429
|
+
}
|
|
430
|
+
function formatLocalScheduleDate(date) {
|
|
431
|
+
return formatDateKey(date);
|
|
432
|
+
}
|
|
433
|
+
function addLocalScheduleDays(date, days) {
|
|
434
|
+
const utcDate = new Date(Date.UTC(date.year, date.month - 1, date.day + days, 12, 0, 0));
|
|
435
|
+
return {
|
|
436
|
+
year: utcDate.getUTCFullYear(),
|
|
437
|
+
month: utcDate.getUTCMonth() + 1,
|
|
438
|
+
day: utcDate.getUTCDate()
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ../core/src/location.ts
|
|
443
|
+
function normalizeLocationAddressText(value) {
|
|
444
|
+
if (typeof value !== "string") {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
const trimmed = value.trim();
|
|
448
|
+
return trimmed ? trimmed : null;
|
|
449
|
+
}
|
|
450
|
+
function hasLocationCoordinates(value) {
|
|
451
|
+
return typeof value?.lat === "number" && typeof value?.lng === "number";
|
|
452
|
+
}
|
|
453
|
+
function toLocationCoordinates(value) {
|
|
454
|
+
if (!hasLocationCoordinates(value)) {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
lat: value.lat,
|
|
459
|
+
lng: value.lng
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ../core/src/planner.ts
|
|
464
|
+
var systemPlanningClock = {
|
|
465
|
+
now: () => Date.now()
|
|
466
|
+
};
|
|
467
|
+
function resolvePlanningNowDate(input = {}) {
|
|
468
|
+
if (input.now !== void 0) {
|
|
469
|
+
return input.now;
|
|
470
|
+
}
|
|
471
|
+
return new Date((input.clock ?? systemPlanningClock).now());
|
|
472
|
+
}
|
|
473
|
+
function resolvePlanningDateInput(input = {}) {
|
|
474
|
+
if (input instanceof Date) {
|
|
475
|
+
return input;
|
|
476
|
+
}
|
|
477
|
+
return resolvePlanningNowDate(input);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// ../media-core/src/typeGuards.ts
|
|
481
|
+
function isRecord(value) {
|
|
482
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
483
|
+
}
|
|
484
|
+
function asRecord(value) {
|
|
485
|
+
return isRecord(value) ? value : void 0;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// ../media-core/src/url.ts
|
|
489
|
+
var DEFAULT_BASE_PATH = "/api/img";
|
|
490
|
+
var RELATIVE_STORAGE_PATH_PREFIXES = [
|
|
491
|
+
"originals/",
|
|
492
|
+
"variants/",
|
|
493
|
+
"imports/"
|
|
494
|
+
];
|
|
495
|
+
function isRelativeDirectImageStoragePath(storagePath) {
|
|
496
|
+
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
|
|
497
|
+
}
|
|
498
|
+
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
499
|
+
return storagePath.startsWith("sites/");
|
|
500
|
+
}
|
|
501
|
+
function encodeStoragePath(storagePath) {
|
|
502
|
+
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
503
|
+
}
|
|
504
|
+
function resolveDirectImagePathTarget(target) {
|
|
505
|
+
switch (target.kind) {
|
|
506
|
+
case "relative":
|
|
507
|
+
return `sites/${target.siteId}/${target.storagePath}`;
|
|
508
|
+
case "site-scoped":
|
|
509
|
+
case "bucket-scoped":
|
|
510
|
+
return target.storagePath;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function buildDirectImageUrl(supabaseUrl, target, storageBucket = "media", options) {
|
|
514
|
+
const baseUrl = supabaseUrl.replace(/\/$/, "");
|
|
515
|
+
const resolvedPath = resolveDirectImagePathTarget(target);
|
|
516
|
+
const encodedPath = encodeStoragePath(resolvedPath);
|
|
517
|
+
const sourcePath = target.storagePath;
|
|
518
|
+
const isSvg = sourcePath.toLowerCase().endsWith(".svg");
|
|
519
|
+
if (options && !isSvg && (options.width || options.height)) {
|
|
520
|
+
const params = new URLSearchParams();
|
|
521
|
+
if (options.width) params.set("width", String(options.width));
|
|
522
|
+
if (options.height) params.set("height", String(options.height));
|
|
523
|
+
if (options.quality) params.set("quality", String(options.quality));
|
|
524
|
+
if (options.resize) params.set("resize", options.resize);
|
|
525
|
+
return `${baseUrl}/storage/v1/render/image/public/${storageBucket}/${encodedPath}?${params.toString()}`;
|
|
526
|
+
}
|
|
527
|
+
return `${baseUrl}/storage/v1/object/public/${storageBucket}/${encodedPath}`;
|
|
528
|
+
}
|
|
529
|
+
function getDirectImageUrlForRelativePath(supabaseUrl, storagePath, siteId, storageBucket = "media", options) {
|
|
530
|
+
return buildDirectImageUrl(
|
|
531
|
+
supabaseUrl,
|
|
532
|
+
{ kind: "relative", storagePath, siteId },
|
|
533
|
+
storageBucket,
|
|
534
|
+
options
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
function getDirectImageUrlForSiteScopedPath(supabaseUrl, storagePath, storageBucket = "media", options) {
|
|
538
|
+
return buildDirectImageUrl(
|
|
539
|
+
supabaseUrl,
|
|
540
|
+
{ kind: "site-scoped", storagePath },
|
|
541
|
+
storageBucket,
|
|
542
|
+
options
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
function getDirectImageUrlForBucketPath(supabaseUrl, storagePath, storageBucket = "media", options) {
|
|
546
|
+
return buildDirectImageUrl(
|
|
547
|
+
supabaseUrl,
|
|
548
|
+
{ kind: "bucket-scoped", storagePath },
|
|
549
|
+
storageBucket,
|
|
550
|
+
options
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
function getDirectImageUrlForStoragePath(supabaseUrl, storagePath, storageBucket = "media", siteId, options) {
|
|
554
|
+
if (isRelativeDirectImageStoragePath(storagePath) && siteId) {
|
|
555
|
+
return getDirectImageUrlForRelativePath(supabaseUrl, storagePath, siteId, storageBucket, options);
|
|
556
|
+
}
|
|
557
|
+
if (isSiteScopedDirectImageStoragePath(storagePath)) {
|
|
558
|
+
return getDirectImageUrlForSiteScopedPath(supabaseUrl, storagePath, storageBucket, options);
|
|
559
|
+
}
|
|
560
|
+
return getDirectImageUrl(supabaseUrl, storagePath, storageBucket, siteId, options);
|
|
561
|
+
}
|
|
562
|
+
function getDirectImageUrl(supabaseUrl, storagePath, storageBucket = "media", siteId, options) {
|
|
563
|
+
if (isSiteScopedDirectImageStoragePath(storagePath)) {
|
|
564
|
+
if (siteId && true) {
|
|
565
|
+
console.warn(
|
|
566
|
+
`[media-core] storagePath "${storagePath}" already contains site prefix. Using path as-is for backward compatibility. After migration, paths should be relative (e.g., "originals/2024/12/img.jpg").`
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
return getDirectImageUrlForSiteScopedPath(supabaseUrl, storagePath, storageBucket, options);
|
|
570
|
+
}
|
|
571
|
+
if (siteId && isRelativeDirectImageStoragePath(storagePath)) {
|
|
572
|
+
return getDirectImageUrlForRelativePath(supabaseUrl, storagePath, siteId, storageBucket, options);
|
|
573
|
+
}
|
|
574
|
+
return getDirectImageUrlForBucketPath(supabaseUrl, storagePath, storageBucket, options);
|
|
575
|
+
}
|
|
576
|
+
var formatNumber = (value) => Number.isInteger(value) ? value.toString() : value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
|
|
577
|
+
var ORDER = [
|
|
578
|
+
"w",
|
|
579
|
+
"h",
|
|
580
|
+
"fit",
|
|
581
|
+
"rect",
|
|
582
|
+
"q",
|
|
583
|
+
"autoFormat",
|
|
584
|
+
"or"
|
|
585
|
+
];
|
|
586
|
+
var getImageUrl = (asset, params = {}, basePath = DEFAULT_BASE_PATH) => {
|
|
587
|
+
const trimmedBase = basePath.endsWith("/") ? basePath.slice(0, Math.max(basePath.length - 1, 0)) : basePath;
|
|
588
|
+
const path = `${trimmedBase}/${encodeURIComponent(asset.id)}`;
|
|
589
|
+
const searchParams = new URLSearchParams();
|
|
590
|
+
if (params.w !== void 0) searchParams.set("w", formatNumber(params.w));
|
|
591
|
+
if (params.h !== void 0) searchParams.set("h", formatNumber(params.h));
|
|
592
|
+
if (params.fit !== void 0) searchParams.set("fit", params.fit);
|
|
593
|
+
if (params.rect) searchParams.set("rect", params.rect.map(formatNumber).join(","));
|
|
594
|
+
if (params.q !== void 0) searchParams.set("q", formatNumber(params.q));
|
|
595
|
+
if (params.autoFormat) searchParams.append("auto", "format");
|
|
596
|
+
if (params.or !== void 0) searchParams.set("or", String(params.or));
|
|
597
|
+
const sorted = new URLSearchParams();
|
|
598
|
+
ORDER.forEach((key) => {
|
|
599
|
+
if (key === "autoFormat") {
|
|
600
|
+
if (params.autoFormat) sorted.append("auto", "format");
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const value = searchParams.get(key);
|
|
604
|
+
if (value !== null) sorted.set(key, value);
|
|
605
|
+
});
|
|
606
|
+
const query = sorted.toString();
|
|
607
|
+
return query ? `${path}?${query}` : path;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// ../media-core/src/transformRect.ts
|
|
611
|
+
function isValidTransformRectStructure(rect) {
|
|
612
|
+
if (!Array.isArray(rect) || rect.length !== 4) return false;
|
|
613
|
+
const [left, top, width, height] = rect;
|
|
614
|
+
return Number.isFinite(left) && Number.isFinite(top) && Number.isFinite(width) && Number.isFinite(height) && left >= 0 && top >= 0 && width > 0 && height > 0;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// ../media-core/src/aspectTransforms.ts
|
|
618
|
+
var DEFAULT_RECT_EPSILON = 0.5;
|
|
619
|
+
function parseAspectRatioValue(value) {
|
|
620
|
+
if (typeof value === "number") {
|
|
621
|
+
return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
622
|
+
}
|
|
623
|
+
if (typeof value !== "string") return void 0;
|
|
624
|
+
const normalized = value.trim();
|
|
625
|
+
if (!normalized) return void 0;
|
|
626
|
+
if (normalized === "auto") return void 0;
|
|
627
|
+
if (normalized.includes(":") || normalized.includes("/")) {
|
|
628
|
+
const delimiter = normalized.includes(":") ? ":" : "/";
|
|
629
|
+
const [wRaw, hRaw] = normalized.split(delimiter);
|
|
630
|
+
const width = Number(wRaw?.trim());
|
|
631
|
+
const height = Number(hRaw?.trim());
|
|
632
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
633
|
+
return void 0;
|
|
634
|
+
}
|
|
635
|
+
return width / height;
|
|
636
|
+
}
|
|
637
|
+
const numeric = Number(normalized);
|
|
638
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return void 0;
|
|
639
|
+
return numeric;
|
|
640
|
+
}
|
|
641
|
+
var MAX_ASPECT_DISTANCE = 0.25;
|
|
642
|
+
function resolveMediaTransformForAspect(transform, targetAspect) {
|
|
643
|
+
if (!transform) return {};
|
|
644
|
+
const base = {
|
|
645
|
+
rect: transform.rect,
|
|
646
|
+
hotspot: transform.hotspot,
|
|
647
|
+
rotation: transform.rotation
|
|
648
|
+
};
|
|
649
|
+
const target = parseAspectRatioValue(targetAspect);
|
|
650
|
+
const crops = transform.aspectCrops;
|
|
651
|
+
if (!target || !crops || Object.keys(crops).length === 0) {
|
|
652
|
+
return base;
|
|
653
|
+
}
|
|
654
|
+
let best = null;
|
|
655
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
656
|
+
for (const [key, candidate] of Object.entries(crops)) {
|
|
657
|
+
const candidateAspect = parseAspectRatioValue(candidate.aspect ?? key);
|
|
658
|
+
if (!candidateAspect) continue;
|
|
659
|
+
const distance = Math.abs(Math.log(candidateAspect / target));
|
|
660
|
+
if (distance < bestDistance) {
|
|
661
|
+
best = candidate;
|
|
662
|
+
bestDistance = distance;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (!best) return base;
|
|
666
|
+
if (bestDistance > MAX_ASPECT_DISTANCE) return base;
|
|
667
|
+
return {
|
|
668
|
+
rect: best.rect ?? base.rect,
|
|
669
|
+
hotspot: best.hotspot ?? base.hotspot,
|
|
670
|
+
rotation: best.rotation ?? base.rotation
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
function isValidTransformRect(rect) {
|
|
674
|
+
return isValidTransformRectStructure(rect);
|
|
675
|
+
}
|
|
676
|
+
function isExplicitRectCrop(rect, sourceWidth, sourceHeight, epsilon = DEFAULT_RECT_EPSILON) {
|
|
677
|
+
if (!isValidTransformRect(rect)) return false;
|
|
678
|
+
const hasSourceDimensions = typeof sourceWidth === "number" && Number.isFinite(sourceWidth) && sourceWidth > 0 && typeof sourceHeight === "number" && Number.isFinite(sourceHeight) && sourceHeight > 0;
|
|
679
|
+
if (!hasSourceDimensions) {
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
const [x, y, width, height] = rect;
|
|
683
|
+
const isFullFrame = Math.abs(x) <= epsilon && Math.abs(y) <= epsilon && Math.abs(width - sourceWidth) <= epsilon && Math.abs(height - sourceHeight) <= epsilon;
|
|
684
|
+
return !isFullFrame;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// ../media-core/src/deliveryContracts.ts
|
|
688
|
+
var DEFAULT_MEDIA_WIDTH_CANDIDATES = [
|
|
689
|
+
320,
|
|
690
|
+
480,
|
|
691
|
+
640,
|
|
692
|
+
768,
|
|
693
|
+
960,
|
|
694
|
+
1200,
|
|
695
|
+
1536,
|
|
696
|
+
1920,
|
|
697
|
+
2560
|
|
698
|
+
];
|
|
699
|
+
function normalizeWidthCandidates(candidates, max = 2560) {
|
|
700
|
+
const source = (candidates ?? DEFAULT_MEDIA_WIDTH_CANDIDATES).filter((value) => Number.isFinite(value) && value > 0);
|
|
701
|
+
const uniqueSorted = [...new Set(source.map((value) => Math.round(value)))].filter((value) => value > 0 && value <= max).sort((a, b) => a - b);
|
|
702
|
+
if (uniqueSorted.length > 0) {
|
|
703
|
+
return uniqueSorted;
|
|
704
|
+
}
|
|
705
|
+
return DEFAULT_MEDIA_WIDTH_CANDIDATES.filter((value) => value <= max);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ../media-core/src/rotation.ts
|
|
709
|
+
function rotateNormalizedPoint(point, rotation) {
|
|
710
|
+
const x = point.x;
|
|
711
|
+
const y = point.y;
|
|
712
|
+
switch (rotation) {
|
|
713
|
+
case 90:
|
|
714
|
+
return { x: 1 - y, y: x };
|
|
715
|
+
case 180:
|
|
716
|
+
return { x: 1 - x, y: 1 - y };
|
|
717
|
+
case 270:
|
|
718
|
+
return { x: y, y: 1 - x };
|
|
719
|
+
default:
|
|
720
|
+
return { x, y };
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// ../blocks/src/system/media/slotContracts.ts
|
|
725
|
+
var DEFAULT_MIN_SOURCE_WIDTH = 1200;
|
|
726
|
+
var LARGE_MIN_SOURCE_WIDTH = 1400;
|
|
727
|
+
var SECTION_BACKGROUND_MIN_SOURCE_WIDTH = 1920;
|
|
728
|
+
var SECTION_BACKGROUND_MIN_SOURCE_HEIGHT = 900;
|
|
729
|
+
var TEAM_MEMBER_MIN_SOURCE_WIDTH = 1e3;
|
|
730
|
+
var DEFAULT_DELIVERY_MAX_WIDTH = 2560;
|
|
731
|
+
var DEFAULT_MARQUEE_IMAGE_PX = 256;
|
|
732
|
+
function normalizeSlotPath(path) {
|
|
733
|
+
return path.split(".").map((segment) => /^\d+$/.test(segment) ? "[]" : segment).join(".");
|
|
734
|
+
}
|
|
735
|
+
function asString(value) {
|
|
736
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
737
|
+
}
|
|
738
|
+
function asFiniteNumber(value) {
|
|
739
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
740
|
+
return value;
|
|
741
|
+
}
|
|
742
|
+
function asPositiveIntArray(value) {
|
|
743
|
+
if (!Array.isArray(value)) return void 0;
|
|
744
|
+
const numbers = value.map((entry) => asFiniteNumber(entry)).filter((entry) => entry !== void 0 && entry > 0).map((entry) => Math.round(entry));
|
|
745
|
+
return numbers.length > 0 ? numbers : void 0;
|
|
746
|
+
}
|
|
747
|
+
function getValueAtPath(values, path) {
|
|
748
|
+
const segments = path.split(".").filter((segment) => segment.length > 0);
|
|
749
|
+
let current = values;
|
|
750
|
+
for (const segment of segments) {
|
|
751
|
+
if (Array.isArray(current)) {
|
|
752
|
+
const numericIndex = Number.parseInt(segment, 10);
|
|
753
|
+
if (!Number.isFinite(numericIndex)) return void 0;
|
|
754
|
+
const next2 = current[numericIndex];
|
|
755
|
+
if (next2 === void 0) return void 0;
|
|
756
|
+
current = next2;
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
const record = asRecord(current);
|
|
760
|
+
if (!record) return void 0;
|
|
761
|
+
const next = record[segment];
|
|
762
|
+
if (next === void 0) return void 0;
|
|
763
|
+
current = next;
|
|
764
|
+
}
|
|
765
|
+
return current;
|
|
766
|
+
}
|
|
767
|
+
function resolveSiblingAspectRatio(fieldPath, values) {
|
|
768
|
+
if (!values) return void 0;
|
|
769
|
+
const lastDotIndex = fieldPath.lastIndexOf(".");
|
|
770
|
+
if (lastDotIndex < 0) {
|
|
771
|
+
return asString(values.aspectRatio);
|
|
772
|
+
}
|
|
773
|
+
const parentPath = fieldPath.slice(0, lastDotIndex);
|
|
774
|
+
const parentValue = getValueAtPath(values, parentPath);
|
|
775
|
+
const parentRecord = asRecord(parentValue);
|
|
776
|
+
return asString(parentRecord?.aspectRatio);
|
|
777
|
+
}
|
|
778
|
+
function getMinSourceConstraints(aspectRatio, minSourceWidth) {
|
|
779
|
+
const parsedAspect = parseAspectRatioValue(aspectRatio);
|
|
780
|
+
if (!parsedAspect) {
|
|
781
|
+
return { minSourceWidth };
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
minSourceWidth,
|
|
785
|
+
minSourceHeight: Math.max(1, Math.round(minSourceWidth / parsedAspect))
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
function resolveColumnsGridCols(content) {
|
|
789
|
+
const items = Array.isArray(content.columns) ? content.columns : [];
|
|
790
|
+
const count = Math.min(4, Math.max(1, items.length || 1));
|
|
791
|
+
const configuredDesktopColumnsRaw = typeof content.desktopColumns === "string" ? content.desktopColumns : "auto";
|
|
792
|
+
const configuredDesktopColumnsMap = {
|
|
793
|
+
"2": 2,
|
|
794
|
+
"3": 3,
|
|
795
|
+
"4": 4
|
|
796
|
+
};
|
|
797
|
+
const desktopColumns = configuredDesktopColumnsMap[configuredDesktopColumnsRaw] ?? count;
|
|
798
|
+
if (desktopColumns <= 1) {
|
|
799
|
+
return { base: 1 };
|
|
800
|
+
}
|
|
801
|
+
if (desktopColumns === 2) {
|
|
802
|
+
return { base: 1, md: 2 };
|
|
803
|
+
}
|
|
804
|
+
if (desktopColumns === 3) {
|
|
805
|
+
return { base: 1, md: 2, lg: 3 };
|
|
806
|
+
}
|
|
807
|
+
return { base: 1, md: 2, lg: 3, xl: 4 };
|
|
808
|
+
}
|
|
809
|
+
function formatVw(value) {
|
|
810
|
+
const rounded = Math.round(value * 100) / 100;
|
|
811
|
+
return `${Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(2)}vw`;
|
|
812
|
+
}
|
|
813
|
+
function fractionToVw(numerator, denominator) {
|
|
814
|
+
if (!Number.isFinite(numerator) || !Number.isFinite(denominator) || denominator <= 0) {
|
|
815
|
+
return "100vw";
|
|
816
|
+
}
|
|
817
|
+
const clampedNumerator = Math.max(1, Math.min(numerator, denominator));
|
|
818
|
+
return formatVw(clampedNumerator / denominator * 100);
|
|
819
|
+
}
|
|
820
|
+
function resolveColumnsDeliveryContract(fieldPath, values) {
|
|
821
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
822
|
+
if (!values) {
|
|
823
|
+
return {
|
|
824
|
+
strategy: "columnsAuto",
|
|
825
|
+
sizes: "100vw",
|
|
826
|
+
widthCandidates: defaultCandidates
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
const match = fieldPath.match(/^columns\.(\d+)\.media$/);
|
|
830
|
+
const matchIndex = match?.[1];
|
|
831
|
+
const columnIndex = typeof matchIndex === "string" ? Number.parseInt(matchIndex, 10) : void 0;
|
|
832
|
+
const columns = Array.isArray(values.columns) ? values.columns : [];
|
|
833
|
+
const columnValue = columnIndex !== void 0 ? asRecord(columns[columnIndex]) : void 0;
|
|
834
|
+
const rawSpan = asString(columnValue?.desktopSpan);
|
|
835
|
+
const desktopSpan = rawSpan === "2" || rawSpan === "3" || rawSpan === "4" ? Number.parseInt(rawSpan, 10) : 1;
|
|
836
|
+
const cols = resolveColumnsGridCols(values);
|
|
837
|
+
const mobileCols = cols.base;
|
|
838
|
+
const mdCols = cols.md ?? mobileCols;
|
|
839
|
+
const lgCols = cols.lg ?? mdCols;
|
|
840
|
+
const xlCols = cols.xl ?? lgCols;
|
|
841
|
+
const sizes = [
|
|
842
|
+
`(min-width: 1280px) ${fractionToVw(desktopSpan, xlCols)}`,
|
|
843
|
+
`(min-width: 1024px) ${fractionToVw(desktopSpan, lgCols)}`,
|
|
844
|
+
`(min-width: 768px) ${fractionToVw(1, mdCols)}`,
|
|
845
|
+
fractionToVw(1, mobileCols)
|
|
846
|
+
].join(", ");
|
|
847
|
+
return {
|
|
848
|
+
strategy: "columnsAuto",
|
|
849
|
+
sizes,
|
|
850
|
+
widthCandidates: defaultCandidates
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function parseSlidesToShow(value, fallback) {
|
|
854
|
+
const asText = asString(value);
|
|
855
|
+
if (!asText) return fallback;
|
|
856
|
+
const parsed = Number.parseInt(asText, 10);
|
|
857
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
858
|
+
return parsed;
|
|
859
|
+
}
|
|
860
|
+
function resolveMarqueeImageSizePixels(values) {
|
|
861
|
+
const size = asString(values?.marqueeImageSize) ?? "md";
|
|
862
|
+
if (size === "sm") return 200;
|
|
863
|
+
if (size === "lg") return 320;
|
|
864
|
+
if (size === "xl") return 400;
|
|
865
|
+
return DEFAULT_MARQUEE_IMAGE_PX;
|
|
866
|
+
}
|
|
867
|
+
function resolveMarqueeMinSourceWidth(values) {
|
|
868
|
+
const pixels = resolveMarqueeImageSizePixels(values);
|
|
869
|
+
return Math.max(600, Math.round(pixels * 3));
|
|
870
|
+
}
|
|
871
|
+
function resolveImageGalleryDeliveryContract(values) {
|
|
872
|
+
const variant = asString(values?.variant) ?? "grid";
|
|
873
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
874
|
+
if (variant === "carousel") {
|
|
875
|
+
const mobile = parseSlidesToShow(values?.slidesToShow, 1);
|
|
876
|
+
const tablet = parseSlidesToShow(values?.slidesToShowTablet, mobile);
|
|
877
|
+
const desktop = parseSlidesToShow(values?.slidesToShowDesktop, tablet);
|
|
878
|
+
return {
|
|
879
|
+
strategy: "imageGalleryVariant",
|
|
880
|
+
sizes: [
|
|
881
|
+
`(min-width: 1280px) ${fractionToVw(1, desktop)}`,
|
|
882
|
+
`(min-width: 768px) ${fractionToVw(1, tablet)}`,
|
|
883
|
+
fractionToVw(1, mobile)
|
|
884
|
+
].join(", "),
|
|
885
|
+
widthCandidates: defaultCandidates
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
if (variant === "marquee") {
|
|
889
|
+
const marqueePixels = resolveMarqueeImageSizePixels(values);
|
|
890
|
+
return {
|
|
891
|
+
strategy: "imageGalleryVariant",
|
|
892
|
+
sizes: `${marqueePixels}px`,
|
|
893
|
+
widthCandidates: defaultCandidates
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
return {
|
|
897
|
+
strategy: "imageGalleryVariant",
|
|
898
|
+
sizes: "(min-width: 1280px) 31vw, (min-width: 768px) 47vw, 96vw",
|
|
899
|
+
widthCandidates: defaultCandidates
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
function parseRatioToken(value) {
|
|
903
|
+
const raw = asString(value);
|
|
904
|
+
if (!raw) return null;
|
|
905
|
+
const [numRaw, denomRaw] = raw.split("/").map((part) => part.trim());
|
|
906
|
+
const numerator = Number(numRaw);
|
|
907
|
+
const denominator = Number(denomRaw);
|
|
908
|
+
if (!Number.isFinite(numerator) || !Number.isFinite(denominator)) return null;
|
|
909
|
+
if (numerator <= 0 || denominator <= 0) return null;
|
|
910
|
+
return { numerator, denominator };
|
|
911
|
+
}
|
|
912
|
+
function resolveResponsiveTwoColumnImageSizes(values) {
|
|
913
|
+
const ratio = parseRatioToken(values?.ratio) ?? { numerator: 1, denominator: 2 };
|
|
914
|
+
return fractionToVw(ratio.numerator, ratio.denominator);
|
|
915
|
+
}
|
|
916
|
+
function parseColumnsCount(raw, fallback) {
|
|
917
|
+
const cols = typeof raw === "number" ? raw : typeof raw === "string" ? Number.parseInt(raw, 10) : fallback;
|
|
918
|
+
const safe = Number.isFinite(cols) ? cols : fallback;
|
|
919
|
+
return Math.max(1, Math.min(6, safe));
|
|
920
|
+
}
|
|
921
|
+
function resolveTeamMembersDeliveryContract(values) {
|
|
922
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
923
|
+
const variant = asString(values?.variant) ?? "grid";
|
|
924
|
+
if (variant === "stack") {
|
|
925
|
+
const ratio = parseRatioToken(values?.imageColSize) ?? { numerator: 1, denominator: 3 };
|
|
926
|
+
const desktop = fractionToVw(ratio.numerator, ratio.denominator);
|
|
927
|
+
return {
|
|
928
|
+
strategy: "default",
|
|
929
|
+
sizes: `(min-width: 768px) ${desktop}, 100vw`,
|
|
930
|
+
widthCandidates: defaultCandidates
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
const clamped = parseColumnsCount(values?.columns, 3);
|
|
934
|
+
return {
|
|
935
|
+
strategy: "default",
|
|
936
|
+
sizes: fractionToVw(1, clamped),
|
|
937
|
+
widthCandidates: defaultCandidates
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
function resolveMediaTextDeliveryContract(values) {
|
|
941
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
942
|
+
const desktop = resolveResponsiveTwoColumnImageSizes(values);
|
|
943
|
+
return {
|
|
944
|
+
strategy: "default",
|
|
945
|
+
sizes: `(min-width: 768px) ${desktop}, 100vw`,
|
|
946
|
+
widthCandidates: defaultCandidates
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
function resolveCollectionDeliveryContract(values) {
|
|
950
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
951
|
+
const layout = asString(values?.layout) ?? "grid";
|
|
952
|
+
if (layout !== "grid") {
|
|
953
|
+
return { strategy: "default", sizes: "100vw", widthCandidates: defaultCandidates };
|
|
954
|
+
}
|
|
955
|
+
const clamped = parseColumnsCount(values?.columns, 3);
|
|
956
|
+
return {
|
|
957
|
+
strategy: "default",
|
|
958
|
+
sizes: fractionToVw(1, clamped),
|
|
959
|
+
widthCandidates: defaultCandidates
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
function resolveSmallLogoDeliveryContract() {
|
|
963
|
+
const defaultCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
964
|
+
return {
|
|
965
|
+
strategy: "default",
|
|
966
|
+
sizes: "256px",
|
|
967
|
+
widthCandidates: defaultCandidates
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
function resolveDefaultDeliveryContract(slotPath) {
|
|
971
|
+
const widthCandidates = normalizeWidthCandidates(void 0, DEFAULT_DELIVERY_MAX_WIDTH);
|
|
972
|
+
if (slotPath.endsWith("_sectionStyles.background.image")) {
|
|
973
|
+
return {
|
|
974
|
+
strategy: "default",
|
|
975
|
+
sizes: "100vw",
|
|
976
|
+
widthCandidates,
|
|
977
|
+
maxCssWidth: DEFAULT_DELIVERY_MAX_WIDTH
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
return {
|
|
981
|
+
strategy: "default",
|
|
982
|
+
sizes: "100vw",
|
|
983
|
+
widthCandidates
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
function parseMediaDeliveryConfig(value) {
|
|
987
|
+
const record = asRecord(value);
|
|
988
|
+
if (!record) return void 0;
|
|
989
|
+
const strategyValue = asString(record.strategy);
|
|
990
|
+
const strategy = strategyValue === "default" || strategyValue === "columnsAuto" || strategyValue === "imageGalleryVariant" ? strategyValue : void 0;
|
|
991
|
+
const strategyOptions = asRecord(record.strategyOptions);
|
|
992
|
+
const parsed = {};
|
|
993
|
+
const sizes = asString(record.sizes);
|
|
994
|
+
if (sizes) parsed.sizes = sizes;
|
|
995
|
+
const widthCandidates = asPositiveIntArray(record.widthCandidates);
|
|
996
|
+
if (widthCandidates) parsed.widthCandidates = widthCandidates;
|
|
997
|
+
const maxCssWidth = asFiniteNumber(record.maxCssWidth);
|
|
998
|
+
if (maxCssWidth !== void 0) parsed.maxCssWidth = maxCssWidth;
|
|
999
|
+
const maxCssHeight = asFiniteNumber(record.maxCssHeight);
|
|
1000
|
+
if (maxCssHeight !== void 0) parsed.maxCssHeight = maxCssHeight;
|
|
1001
|
+
if (strategy) parsed.strategy = strategy;
|
|
1002
|
+
if (strategyOptions) parsed.strategyOptions = strategyOptions;
|
|
1003
|
+
return parsed;
|
|
1004
|
+
}
|
|
1005
|
+
function resolveFieldUiDeliveryConfig(fieldUi, variant) {
|
|
1006
|
+
const ui = asRecord(fieldUi);
|
|
1007
|
+
if (!ui) return void 0;
|
|
1008
|
+
const defaultConfig = parseMediaDeliveryConfig(ui.mediaDelivery);
|
|
1009
|
+
const byVariant = asRecord(ui.mediaDeliveryByVariant);
|
|
1010
|
+
const variantConfig = variant ? parseMediaDeliveryConfig(byVariant?.[variant]) : void 0;
|
|
1011
|
+
if (!defaultConfig && !variantConfig) return void 0;
|
|
1012
|
+
return {
|
|
1013
|
+
...defaultConfig,
|
|
1014
|
+
...variantConfig,
|
|
1015
|
+
strategyOptions: {
|
|
1016
|
+
...defaultConfig?.strategyOptions ?? {},
|
|
1017
|
+
...variantConfig?.strategyOptions ?? {}
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
function mergeDelivery(base, override) {
|
|
1022
|
+
if (!override) return base;
|
|
1023
|
+
const maxCssWidth = override.maxCssWidth ?? base.maxCssWidth;
|
|
1024
|
+
const cap = maxCssWidth && maxCssWidth > 0 ? Math.round(maxCssWidth) : DEFAULT_DELIVERY_MAX_WIDTH;
|
|
1025
|
+
const widthCandidates = normalizeWidthCandidates(
|
|
1026
|
+
override.widthCandidates ?? base.widthCandidates,
|
|
1027
|
+
cap
|
|
1028
|
+
);
|
|
1029
|
+
return {
|
|
1030
|
+
...base,
|
|
1031
|
+
...override,
|
|
1032
|
+
widthCandidates
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
function buildContract(edit, delivery) {
|
|
1036
|
+
return {
|
|
1037
|
+
edit,
|
|
1038
|
+
delivery
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
function resolveImageGalleryEditContract(slotPath, values) {
|
|
1042
|
+
if (slotPath !== "images.[].image") {
|
|
1043
|
+
return void 0;
|
|
1044
|
+
}
|
|
1045
|
+
const variant = asString(values?.variant) ?? "grid";
|
|
1046
|
+
if (variant === "marquee") {
|
|
1047
|
+
const aspectRatio = "1/1";
|
|
1048
|
+
const minSourceWidth = resolveMarqueeMinSourceWidth(values);
|
|
1049
|
+
return {
|
|
1050
|
+
mode: "fixed-aspect",
|
|
1051
|
+
aspectRatio,
|
|
1052
|
+
...getMinSourceConstraints(aspectRatio, minSourceWidth)
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
if (variant === "masonry") {
|
|
1056
|
+
return {
|
|
1057
|
+
mode: "original-aspect",
|
|
1058
|
+
minSourceWidth: DEFAULT_MIN_SOURCE_WIDTH
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
const configuredAspect = asString(values?.aspectRatio);
|
|
1062
|
+
if (!configuredAspect || configuredAspect === "auto") {
|
|
1063
|
+
return {
|
|
1064
|
+
mode: "original-aspect",
|
|
1065
|
+
minSourceWidth: DEFAULT_MIN_SOURCE_WIDTH
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
return {
|
|
1069
|
+
mode: "fixed-aspect",
|
|
1070
|
+
aspectRatio: configuredAspect,
|
|
1071
|
+
...getMinSourceConstraints(configuredAspect, DEFAULT_MIN_SOURCE_WIDTH)
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
function resolveEditContract(blockKind, fieldPath, slotPath, values, fieldAspectRatio) {
|
|
1075
|
+
const normalizedFieldAspect = asString(fieldAspectRatio);
|
|
1076
|
+
if (slotPath.endsWith("_sectionStyles.background.image")) {
|
|
1077
|
+
return {
|
|
1078
|
+
mode: "original-aspect",
|
|
1079
|
+
minSourceWidth: SECTION_BACKGROUND_MIN_SOURCE_WIDTH,
|
|
1080
|
+
minSourceHeight: SECTION_BACKGROUND_MIN_SOURCE_HEIGHT
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
if (blockKind === "block.image-gallery") {
|
|
1084
|
+
const imageGalleryContract = resolveImageGalleryEditContract(slotPath, values);
|
|
1085
|
+
if (imageGalleryContract) return imageGalleryContract;
|
|
1086
|
+
}
|
|
1087
|
+
if (blockKind === "block.team-members" && slotPath === "members.[].photo") {
|
|
1088
|
+
return {
|
|
1089
|
+
mode: "fixed-aspect",
|
|
1090
|
+
aspectRatio: "1/1",
|
|
1091
|
+
...getMinSourceConstraints("1/1", TEAM_MEMBER_MIN_SOURCE_WIDTH)
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
if (blockKind === "block.media-text" && slotPath === "images.[].image") {
|
|
1095
|
+
const blockAspectRatio = asString(values?.aspectRatio);
|
|
1096
|
+
if (blockAspectRatio && blockAspectRatio !== "auto") {
|
|
1097
|
+
return {
|
|
1098
|
+
mode: "fixed-aspect",
|
|
1099
|
+
aspectRatio: blockAspectRatio,
|
|
1100
|
+
...getMinSourceConstraints(blockAspectRatio, LARGE_MIN_SOURCE_WIDTH)
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
return {
|
|
1104
|
+
mode: "original-aspect",
|
|
1105
|
+
minSourceWidth: LARGE_MIN_SOURCE_WIDTH
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
const siblingAspectRatio = resolveSiblingAspectRatio(fieldPath, values);
|
|
1109
|
+
if (siblingAspectRatio && siblingAspectRatio !== "auto") {
|
|
1110
|
+
return {
|
|
1111
|
+
mode: "fixed-aspect",
|
|
1112
|
+
aspectRatio: siblingAspectRatio,
|
|
1113
|
+
...getMinSourceConstraints(siblingAspectRatio, DEFAULT_MIN_SOURCE_WIDTH)
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
if (siblingAspectRatio === "auto") {
|
|
1117
|
+
return {
|
|
1118
|
+
mode: "original-aspect",
|
|
1119
|
+
minSourceWidth: DEFAULT_MIN_SOURCE_WIDTH
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
if (!normalizedFieldAspect || normalizedFieldAspect === "auto") {
|
|
1123
|
+
return {
|
|
1124
|
+
mode: "original-aspect",
|
|
1125
|
+
minSourceWidth: DEFAULT_MIN_SOURCE_WIDTH
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
return {
|
|
1129
|
+
mode: "fixed-aspect",
|
|
1130
|
+
aspectRatio: normalizedFieldAspect,
|
|
1131
|
+
...getMinSourceConstraints(normalizedFieldAspect, DEFAULT_MIN_SOURCE_WIDTH)
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
function resolveStrategyDelivery(blockKind, fieldPath, slotPath, values) {
|
|
1135
|
+
if (blockKind === "block.columns" && slotPath === "columns.[].media") {
|
|
1136
|
+
return resolveColumnsDeliveryContract(fieldPath, values);
|
|
1137
|
+
}
|
|
1138
|
+
if (blockKind === "block.image-gallery" && slotPath === "images.[].image") {
|
|
1139
|
+
return resolveImageGalleryDeliveryContract(values);
|
|
1140
|
+
}
|
|
1141
|
+
if (blockKind === "block.team-members" && slotPath === "members.[].photo") {
|
|
1142
|
+
return resolveTeamMembersDeliveryContract(values);
|
|
1143
|
+
}
|
|
1144
|
+
if (blockKind === "block.media-text" && slotPath === "images.[].image") {
|
|
1145
|
+
return resolveMediaTextDeliveryContract(values);
|
|
1146
|
+
}
|
|
1147
|
+
if (blockKind === "block.collection" && slotPath.startsWith("items.[].")) {
|
|
1148
|
+
return resolveCollectionDeliveryContract(values);
|
|
1149
|
+
}
|
|
1150
|
+
if (blockKind === "block.site-header" && slotPath === "logo") {
|
|
1151
|
+
return resolveSmallLogoDeliveryContract();
|
|
1152
|
+
}
|
|
1153
|
+
if (blockKind === "block.site-footer" && slotPath === "logo") {
|
|
1154
|
+
return resolveSmallLogoDeliveryContract();
|
|
1155
|
+
}
|
|
1156
|
+
return void 0;
|
|
1157
|
+
}
|
|
1158
|
+
function resolveMediaSlotContract({
|
|
1159
|
+
blockKind,
|
|
1160
|
+
fieldPath,
|
|
1161
|
+
values,
|
|
1162
|
+
fieldAspectRatio,
|
|
1163
|
+
fieldUi
|
|
1164
|
+
}) {
|
|
1165
|
+
const slotPath = normalizeSlotPath(fieldPath);
|
|
1166
|
+
const variant = asString(values?.variant);
|
|
1167
|
+
const edit = resolveEditContract(blockKind, fieldPath, slotPath, values, fieldAspectRatio);
|
|
1168
|
+
const defaultDelivery = resolveDefaultDeliveryContract(slotPath);
|
|
1169
|
+
const fieldDelivery = resolveFieldUiDeliveryConfig(fieldUi, variant);
|
|
1170
|
+
const strategyDelivery = resolveStrategyDelivery(blockKind, fieldPath, slotPath, values);
|
|
1171
|
+
const mergedField = mergeDelivery(defaultDelivery, fieldDelivery);
|
|
1172
|
+
const merged = mergeDelivery(mergedField, strategyDelivery);
|
|
1173
|
+
return buildContract(edit, merged);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// ../theme-core/src/tokens/colorTokenParts.ts
|
|
1177
|
+
function parseOpacityPercent(source) {
|
|
1178
|
+
const trimmed = source.trim();
|
|
1179
|
+
if (!trimmed) return null;
|
|
1180
|
+
if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
|
|
1181
|
+
const value = Number(trimmed);
|
|
1182
|
+
if (!Number.isFinite(value)) return null;
|
|
1183
|
+
if (value < 0 || value > 100) return null;
|
|
1184
|
+
return value;
|
|
1185
|
+
}
|
|
1186
|
+
function parseColorTokenParts(source) {
|
|
1187
|
+
const trimmed = source.trim();
|
|
1188
|
+
if (trimmed.startsWith("raw:")) {
|
|
1189
|
+
return { kind: "raw", value: trimmed.slice(4) };
|
|
1190
|
+
}
|
|
1191
|
+
const [token, opacityRaw, extra] = trimmed.split("/");
|
|
1192
|
+
if (!token || extra !== void 0) {
|
|
1193
|
+
return { kind: "invalid", token: trimmed };
|
|
1194
|
+
}
|
|
1195
|
+
if (opacityRaw === void 0) {
|
|
1196
|
+
return { kind: "token", token, opacityPercent: null };
|
|
1197
|
+
}
|
|
1198
|
+
const opacityPercent = parseOpacityPercent(opacityRaw);
|
|
1199
|
+
if (opacityPercent === null) {
|
|
1200
|
+
return { kind: "invalid", token: trimmed };
|
|
1201
|
+
}
|
|
1202
|
+
return { kind: "token", token, opacityPercent };
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// ../theme-core/src/utils/colorStyles.ts
|
|
1206
|
+
var COLOR_VAR_PREFIX = "--tb-";
|
|
1207
|
+
function parseToken(source) {
|
|
1208
|
+
const parts = parseColorTokenParts(source);
|
|
1209
|
+
if (parts.kind === "raw") {
|
|
1210
|
+
return { token: source, raw: parts.value };
|
|
1211
|
+
}
|
|
1212
|
+
if (parts.kind === "invalid") {
|
|
1213
|
+
return { token: source };
|
|
1214
|
+
}
|
|
1215
|
+
return {
|
|
1216
|
+
token: parts.token,
|
|
1217
|
+
alpha: parts.opacityPercent === null ? void 0 : parts.opacityPercent / 100
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function rgbColorValue(token) {
|
|
1221
|
+
const { token: baseToken, alpha, raw } = parseToken(token);
|
|
1222
|
+
if (raw) {
|
|
1223
|
+
return raw;
|
|
1224
|
+
}
|
|
1225
|
+
const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
|
|
1226
|
+
if (alpha === void 0) {
|
|
1227
|
+
return `rgb(var(${cssVar}))`;
|
|
1228
|
+
}
|
|
1229
|
+
return `rgba(var(${cssVar}), ${alpha})`;
|
|
1230
|
+
}
|
|
1231
|
+
function backgroundColorStyle(token) {
|
|
1232
|
+
return { backgroundColor: rgbColorValue(token) };
|
|
1233
|
+
}
|
|
1234
|
+
function textColorStyle(token) {
|
|
1235
|
+
return { color: rgbColorValue(token) };
|
|
1236
|
+
}
|
|
1237
|
+
function borderColorStyle(token) {
|
|
1238
|
+
return { borderColor: rgbColorValue(token) };
|
|
1239
|
+
}
|
|
1240
|
+
function mergeStyles(...styles) {
|
|
1241
|
+
const merged = {};
|
|
1242
|
+
for (const style of styles) {
|
|
1243
|
+
if (!style) continue;
|
|
1244
|
+
Object.assign(merged, style);
|
|
1245
|
+
}
|
|
1246
|
+
return Object.keys(merged).length ? merged : void 0;
|
|
1247
|
+
}
|
|
1248
|
+
function buildMediaAssetIndex(assets) {
|
|
1249
|
+
if (!assets || assets.length === 0) return void 0;
|
|
1250
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1251
|
+
const byIdentifier = /* @__PURE__ */ new Map();
|
|
1252
|
+
for (const asset of assets) {
|
|
1253
|
+
if (!asset?.id) continue;
|
|
1254
|
+
byId.set(asset.id, asset);
|
|
1255
|
+
const identifier = typeof asset.identifier === "string" ? asset.identifier.trim() : "";
|
|
1256
|
+
if (identifier) byIdentifier.set(identifier, asset);
|
|
1257
|
+
}
|
|
1258
|
+
return { byId, byIdentifier };
|
|
1259
|
+
}
|
|
1260
|
+
var MAX_RENDER_DIMENSION = 4096;
|
|
1261
|
+
var MAX_SRCSET_WIDTH = 2560;
|
|
1262
|
+
var RELATIVE_IMG_PROXY_BASE_PATH = "/api/img";
|
|
1263
|
+
function normalizeSupabaseUrl(value) {
|
|
1264
|
+
return value?.replace(/\/$/, "");
|
|
1265
|
+
}
|
|
1266
|
+
function buildResolveImageUrlContext(input) {
|
|
1267
|
+
return {
|
|
1268
|
+
supabaseUrl: normalizeSupabaseUrl(input?.supabaseUrl),
|
|
1269
|
+
siteId: input?.siteId,
|
|
1270
|
+
mediaAssetIndex: input?.mediaAssetIndex ?? buildMediaAssetIndex(input?.mediaAssets)
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
function getValidSourceDimension(value) {
|
|
1274
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
1275
|
+
}
|
|
1276
|
+
function isExplicitCropProxyEnabled() {
|
|
1277
|
+
const raw = process.env.NEXT_PUBLIC_MEDIA_EXPLICIT_CROP_PROXY_ENABLED ?? process.env.MEDIA_EXPLICIT_CROP_PROXY_ENABLED;
|
|
1278
|
+
if (!raw) return true;
|
|
1279
|
+
const normalized = raw.trim().toLowerCase();
|
|
1280
|
+
return !(normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off");
|
|
1281
|
+
}
|
|
1282
|
+
function getRequestedDimension(value) {
|
|
1283
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
1284
|
+
return Math.min(MAX_RENDER_DIMENSION, Math.max(1, Math.round(value)));
|
|
1285
|
+
}
|
|
1286
|
+
function getPositiveAspectRatio(value) {
|
|
1287
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
|
|
1288
|
+
return value;
|
|
1289
|
+
}
|
|
1290
|
+
function getHeightForAspect(width, aspectRatio) {
|
|
1291
|
+
if (!aspectRatio) return void 0;
|
|
1292
|
+
return Math.max(1, Math.round(width / aspectRatio));
|
|
1293
|
+
}
|
|
1294
|
+
function mapResizeToFit(resize) {
|
|
1295
|
+
if (resize === "contain") return "clip";
|
|
1296
|
+
return "crop";
|
|
1297
|
+
}
|
|
1298
|
+
function shouldUseExplicitRectProxy(value, options, resolvedTransform, sourceWidth, sourceHeight) {
|
|
1299
|
+
if ("original" in options && options.original) return false;
|
|
1300
|
+
if (!isExplicitCropProxyEnabled()) return false;
|
|
1301
|
+
if (!value.assetId) return false;
|
|
1302
|
+
if (typeof resolvedTransform.rotation === "number" && resolvedTransform.rotation !== 0) return true;
|
|
1303
|
+
return isExplicitRectCrop(resolvedTransform.rect, sourceWidth, sourceHeight);
|
|
1304
|
+
}
|
|
1305
|
+
function buildProxyTransformParams(options, resolvedTransform) {
|
|
1306
|
+
const requestedWidth = "width" in options ? getRequestedDimension(options.width) : void 0;
|
|
1307
|
+
const requestedHeight = "height" in options ? getRequestedDimension(options.height) : void 0;
|
|
1308
|
+
const params = {
|
|
1309
|
+
w: requestedWidth,
|
|
1310
|
+
h: requestedHeight,
|
|
1311
|
+
q: "quality" in options ? options.quality : void 0,
|
|
1312
|
+
fit: mapResizeToFit("resize" in options ? options.resize : void 0),
|
|
1313
|
+
autoFormat: true
|
|
1314
|
+
};
|
|
1315
|
+
if (resolvedTransform.rect) {
|
|
1316
|
+
params.rect = resolvedTransform.rect;
|
|
1317
|
+
}
|
|
1318
|
+
if (resolvedTransform.rotation) {
|
|
1319
|
+
params.or = resolvedTransform.rotation;
|
|
1320
|
+
}
|
|
1321
|
+
return params;
|
|
1322
|
+
}
|
|
1323
|
+
function buildDirectTransformOptions(options) {
|
|
1324
|
+
if ("original" in options && options.original) return void 0;
|
|
1325
|
+
const requestedWidth = "width" in options ? getRequestedDimension(options.width) : void 0;
|
|
1326
|
+
const requestedHeight = "height" in options ? getRequestedDimension(options.height) : void 0;
|
|
1327
|
+
return {
|
|
1328
|
+
width: requestedWidth,
|
|
1329
|
+
height: requestedHeight,
|
|
1330
|
+
quality: "quality" in options ? options.quality : void 0,
|
|
1331
|
+
resize: "resize" in options ? options.resize : void 0
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
function resolveTransformResolution(value, targetAspectRatio) {
|
|
1335
|
+
return {
|
|
1336
|
+
resolvedTransform: resolveMediaTransformForAspect(value.transform, targetAspectRatio),
|
|
1337
|
+
sourceWidth: getValidSourceDimension(value.width),
|
|
1338
|
+
sourceHeight: getValidSourceDimension(value.height)
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
function buildCssRectStylePatch(value, rect) {
|
|
1342
|
+
const sourceWidth = getValidSourceDimension(value.width);
|
|
1343
|
+
const sourceHeight = getValidSourceDimension(value.height);
|
|
1344
|
+
if (sourceWidth === void 0 || sourceHeight === void 0 || rect[2] <= 0 || rect[3] <= 0) {
|
|
1345
|
+
return void 0;
|
|
1346
|
+
}
|
|
1347
|
+
const [x, y, width, height] = rect;
|
|
1348
|
+
const centerX = (x + width / 2) / sourceWidth;
|
|
1349
|
+
const centerY = (y + height / 2) / sourceHeight;
|
|
1350
|
+
const zoomX = sourceWidth / width;
|
|
1351
|
+
const zoomY = sourceHeight / height;
|
|
1352
|
+
const uniformZoom = Math.max(1, Math.min(64, Math.max(zoomX, zoomY)));
|
|
1353
|
+
return {
|
|
1354
|
+
objectPosition: `${centerX * 100}% ${centerY * 100}%`,
|
|
1355
|
+
transform: `scale(${uniformZoom})`,
|
|
1356
|
+
transformOrigin: "center"
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
function appendTransform(base, transform) {
|
|
1360
|
+
if (!base || base.length === 0) return transform;
|
|
1361
|
+
return `${base} ${transform}`;
|
|
1362
|
+
}
|
|
1363
|
+
function applyRectTransform(existingStyle, patch) {
|
|
1364
|
+
const next = { ...patch };
|
|
1365
|
+
if (patch.transform) {
|
|
1366
|
+
next.transform = appendTransform(existingStyle?.transform, patch.transform);
|
|
1367
|
+
}
|
|
1368
|
+
return next;
|
|
1369
|
+
}
|
|
1370
|
+
function getProxyImageUrl(value, options, transformAspectRatio, resolved) {
|
|
1371
|
+
if (!value.assetId) return void 0;
|
|
1372
|
+
const targetAspect = transformAspectRatio ?? resolveTargetAspectRatio(options);
|
|
1373
|
+
const { resolvedTransform, sourceWidth, sourceHeight } = resolved ?? resolveTransformResolution(value, targetAspect);
|
|
1374
|
+
if (!shouldUseExplicitRectProxy(value, options, resolvedTransform, sourceWidth, sourceHeight)) return void 0;
|
|
1375
|
+
const params = buildProxyTransformParams(options, resolvedTransform);
|
|
1376
|
+
const proxyBasePath = getImageProxyBasePath();
|
|
1377
|
+
const proxyUrl = getImageUrl({ id: asMediaAssetId(value.assetId) }, params, proxyBasePath);
|
|
1378
|
+
debugMediaNodeLog("resolve:proxy-img", { assetId: value.assetId, params, proxyBasePath, proxyUrl });
|
|
1379
|
+
return proxyUrl;
|
|
1380
|
+
}
|
|
1381
|
+
function resolveMediaStorageUrl(value, context, transformOptions) {
|
|
1382
|
+
const canonical = resolveMediaWithCanonicalAsset(value, context ?? void 0);
|
|
1383
|
+
if (!canonical.storagePath || canonical.storagePath.length === 0) return void 0;
|
|
1384
|
+
const supabaseUrl = context?.supabaseUrl?.replace(/\/$/, "") ?? getSupabaseUrl();
|
|
1385
|
+
const siteId = context?.siteId ?? getSiteId();
|
|
1386
|
+
const bucket = canonical.storageBucket ?? "media";
|
|
1387
|
+
if (isRelativeDirectImageStoragePath(canonical.storagePath) && !siteId) {
|
|
1388
|
+
console.warn(
|
|
1389
|
+
`[blocks] Relative storagePath "${canonical.storagePath}" requires siteId context. Media URL may be incorrect. Ensure siteId is set via runWithMediaContext or setContextSiteId.`
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
const directUrl = getDirectImageUrlForStoragePath(
|
|
1393
|
+
supabaseUrl,
|
|
1394
|
+
canonical.storagePath,
|
|
1395
|
+
bucket,
|
|
1396
|
+
siteId,
|
|
1397
|
+
transformOptions
|
|
1398
|
+
);
|
|
1399
|
+
debugMediaNodeLog("resolve:direct-supabase", {
|
|
1400
|
+
storagePath: canonical.storagePath,
|
|
1401
|
+
siteId,
|
|
1402
|
+
bucket,
|
|
1403
|
+
directUrl,
|
|
1404
|
+
transformOptions
|
|
1405
|
+
});
|
|
1406
|
+
return directUrl;
|
|
1407
|
+
}
|
|
1408
|
+
function getDirectImageUrlForValue(value, options, context) {
|
|
1409
|
+
return resolveMediaStorageUrl(value, context, buildDirectTransformOptions(options));
|
|
1410
|
+
}
|
|
1411
|
+
function resolveStorageImageUrl(value, options, context, transformAspectRatio, resolved) {
|
|
1412
|
+
const proxyUrl = getProxyImageUrl(value, options, transformAspectRatio, resolved);
|
|
1413
|
+
if (proxyUrl) return proxyUrl;
|
|
1414
|
+
const directUrl = getDirectImageUrlForValue(value, options, context);
|
|
1415
|
+
if (directUrl) return directUrl;
|
|
1416
|
+
return void 0;
|
|
1417
|
+
}
|
|
1418
|
+
var ImagePresets = {
|
|
1419
|
+
/** Small thumbnails (200px) - for block previews, lists */
|
|
1420
|
+
thumbnail: { width: 200, quality: 80, resize: "contain" },
|
|
1421
|
+
/** Card-sized images (600px) - for cards, grids */
|
|
1422
|
+
card: { width: 600, quality: 80, resize: "contain" },
|
|
1423
|
+
/** Hero images (1200px) - for above-fold content */
|
|
1424
|
+
hero: { width: 1200, quality: 85, resize: "contain" },
|
|
1425
|
+
/** Full-width images (1920px) - for backgrounds, large displays */
|
|
1426
|
+
full: { width: 1920, quality: 85, resize: "contain" }
|
|
1427
|
+
};
|
|
1428
|
+
var _serverStorage = null;
|
|
1429
|
+
var _serverStorageChecked = false;
|
|
1430
|
+
function getServerStorage() {
|
|
1431
|
+
if (typeof window !== "undefined") return null;
|
|
1432
|
+
if (_serverStorageChecked) return _serverStorage;
|
|
1433
|
+
_serverStorageChecked = true;
|
|
1434
|
+
try {
|
|
1435
|
+
const globalWithNonWebpackRequire = globalThis;
|
|
1436
|
+
const nonWebpackRequire = typeof globalWithNonWebpackRequire.__non_webpack_require__ === "function" ? globalWithNonWebpackRequire.__non_webpack_require__ : new Function("id", "return require(id)");
|
|
1437
|
+
const asyncHooks = nonWebpackRequire("async_hooks");
|
|
1438
|
+
const AsyncLocalStorage = asyncHooks.AsyncLocalStorage;
|
|
1439
|
+
if (AsyncLocalStorage) {
|
|
1440
|
+
_serverStorage = new AsyncLocalStorage();
|
|
1441
|
+
return _serverStorage;
|
|
1442
|
+
}
|
|
1443
|
+
return null;
|
|
1444
|
+
} catch {
|
|
1445
|
+
{
|
|
1446
|
+
console.warn("[blocks] AsyncLocalStorage not available - using module-level state");
|
|
1447
|
+
}
|
|
1448
|
+
return null;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
var RB_MEDIA_CONTEXT_KEY = /* @__PURE__ */ Symbol.for("riverbankcms.blocks.mediaContext");
|
|
1452
|
+
function getClientContextStore() {
|
|
1453
|
+
const g = globalThis;
|
|
1454
|
+
const existing = g[RB_MEDIA_CONTEXT_KEY];
|
|
1455
|
+
if (existing && typeof existing === "object") return existing;
|
|
1456
|
+
const next = {};
|
|
1457
|
+
g[RB_MEDIA_CONTEXT_KEY] = next;
|
|
1458
|
+
return next;
|
|
1459
|
+
}
|
|
1460
|
+
function getMediaContext() {
|
|
1461
|
+
const storage = getServerStorage();
|
|
1462
|
+
if (storage) {
|
|
1463
|
+
return storage.getStore() ?? {};
|
|
1464
|
+
}
|
|
1465
|
+
return getClientContextStore();
|
|
1466
|
+
}
|
|
1467
|
+
function setContextSupabaseUrl(url) {
|
|
1468
|
+
const normalizedUrl = normalizeSupabaseUrl(url);
|
|
1469
|
+
const storage = getServerStorage();
|
|
1470
|
+
if (storage) {
|
|
1471
|
+
const current = storage.getStore();
|
|
1472
|
+
if (current) {
|
|
1473
|
+
current.supabaseUrl = normalizedUrl;
|
|
1474
|
+
} else {
|
|
1475
|
+
if (storage.enterWith) {
|
|
1476
|
+
const next = { supabaseUrl: normalizedUrl };
|
|
1477
|
+
storage.enterWith(next);
|
|
1478
|
+
} else {
|
|
1479
|
+
getClientContextStore().supabaseUrl = normalizedUrl;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
} else {
|
|
1483
|
+
getClientContextStore().supabaseUrl = normalizedUrl;
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
function setContextSiteId(siteId) {
|
|
1487
|
+
const storage = getServerStorage();
|
|
1488
|
+
if (storage) {
|
|
1489
|
+
const current = storage.getStore();
|
|
1490
|
+
if (current) {
|
|
1491
|
+
current.siteId = siteId;
|
|
1492
|
+
} else {
|
|
1493
|
+
if (storage.enterWith) {
|
|
1494
|
+
const next = { siteId };
|
|
1495
|
+
storage.enterWith(next);
|
|
1496
|
+
} else {
|
|
1497
|
+
getClientContextStore().siteId = siteId;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
} else {
|
|
1501
|
+
getClientContextStore().siteId = siteId;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
function setContextMediaAssetIndex(index) {
|
|
1505
|
+
const storage = getServerStorage();
|
|
1506
|
+
if (storage) {
|
|
1507
|
+
const current = storage.getStore();
|
|
1508
|
+
if (current) {
|
|
1509
|
+
current.mediaAssetIndex = index;
|
|
1510
|
+
} else {
|
|
1511
|
+
if (storage.enterWith) {
|
|
1512
|
+
const next = { mediaAssetIndex: index };
|
|
1513
|
+
storage.enterWith(next);
|
|
1514
|
+
} else {
|
|
1515
|
+
getClientContextStore().mediaAssetIndex = index;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
} else {
|
|
1519
|
+
getClientContextStore().mediaAssetIndex = index;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
function setContextResolveImageUrlContext(context) {
|
|
1523
|
+
setContextSupabaseUrl(context?.supabaseUrl);
|
|
1524
|
+
setContextSiteId(context?.siteId);
|
|
1525
|
+
setContextMediaAssetIndex(context?.mediaAssetIndex);
|
|
1526
|
+
}
|
|
1527
|
+
function getCurrentResolveImageUrlContext() {
|
|
1528
|
+
const context = getMediaContext();
|
|
1529
|
+
if (!context.supabaseUrl && !context.siteId && !context.mediaAssetIndex) {
|
|
1530
|
+
return void 0;
|
|
1531
|
+
}
|
|
1532
|
+
return {
|
|
1533
|
+
supabaseUrl: context.supabaseUrl,
|
|
1534
|
+
siteId: context.siteId,
|
|
1535
|
+
mediaAssetIndex: context.mediaAssetIndex
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
function getSupabaseUrl() {
|
|
1539
|
+
const context = getMediaContext();
|
|
1540
|
+
if (context.supabaseUrl) {
|
|
1541
|
+
return context.supabaseUrl;
|
|
1542
|
+
}
|
|
1543
|
+
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
1544
|
+
if (!url) {
|
|
1545
|
+
throw new Error(
|
|
1546
|
+
"NEXT_PUBLIC_SUPABASE_URL is not configured. Set it to your Supabase project URL (e.g., https://xxx.supabase.co)"
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
return url.replace(/\/$/, "");
|
|
1550
|
+
}
|
|
1551
|
+
function resolveDashboardOrigin(raw) {
|
|
1552
|
+
if (!raw) return void 0;
|
|
1553
|
+
const trimmed = raw.trim();
|
|
1554
|
+
if (!trimmed) return void 0;
|
|
1555
|
+
const withoutTrailingSlash = trimmed.replace(/\/+$/, "");
|
|
1556
|
+
const withoutApiSuffix = withoutTrailingSlash.replace(/\/api\/?$/, "");
|
|
1557
|
+
const hasProtocol = /^https?:\/\//i.test(withoutApiSuffix);
|
|
1558
|
+
const normalized = hasProtocol ? withoutApiSuffix : `http://${withoutApiSuffix.replace(/^\/+/, "")}`;
|
|
1559
|
+
try {
|
|
1560
|
+
return new URL(normalized).origin;
|
|
1561
|
+
} catch {
|
|
1562
|
+
return void 0;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
function getImageProxyBasePath() {
|
|
1566
|
+
const dashboardOrigin = resolveDashboardOrigin(process.env.NEXT_PUBLIC_DASHBOARD_URL);
|
|
1567
|
+
if (!dashboardOrigin) return RELATIVE_IMG_PROXY_BASE_PATH;
|
|
1568
|
+
return `${dashboardOrigin}${RELATIVE_IMG_PROXY_BASE_PATH}`;
|
|
1569
|
+
}
|
|
1570
|
+
function getSiteId() {
|
|
1571
|
+
return getMediaContext().siteId;
|
|
1572
|
+
}
|
|
1573
|
+
function getMediaAssetIndex(context) {
|
|
1574
|
+
return context?.mediaAssetIndex ?? getMediaContext().mediaAssetIndex;
|
|
1575
|
+
}
|
|
1576
|
+
function resolveCanonicalMediaAsset(value, context) {
|
|
1577
|
+
const index = getMediaAssetIndex(context);
|
|
1578
|
+
if (!index) return void 0;
|
|
1579
|
+
if (value.assetId) {
|
|
1580
|
+
const hit = index.byId.get(value.assetId);
|
|
1581
|
+
if (hit) return hit;
|
|
1582
|
+
}
|
|
1583
|
+
const identifier = typeof value.identifier === "string" ? value.identifier.trim() : "";
|
|
1584
|
+
if (identifier) {
|
|
1585
|
+
const hit = index.byIdentifier.get(identifier);
|
|
1586
|
+
if (hit) return hit;
|
|
1587
|
+
}
|
|
1588
|
+
return void 0;
|
|
1589
|
+
}
|
|
1590
|
+
function resolveMediaWithCanonicalAsset(value, context) {
|
|
1591
|
+
const asset = resolveCanonicalMediaAsset(value, context);
|
|
1592
|
+
if (!asset) return value;
|
|
1593
|
+
return {
|
|
1594
|
+
...value,
|
|
1595
|
+
assetId: asset.id ?? value.assetId,
|
|
1596
|
+
identifier: typeof value.identifier === "string" && value.identifier.trim().length > 0 ? value.identifier : asset.identifier ?? value.identifier,
|
|
1597
|
+
storageBucket: asset.storageBucket ?? value.storageBucket,
|
|
1598
|
+
storagePath: asset.storagePath ?? value.storagePath,
|
|
1599
|
+
width: asset.width ?? value.width,
|
|
1600
|
+
height: asset.height ?? value.height
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
function resolveVideoPosterUrl(value, context) {
|
|
1604
|
+
if (value.type !== "video") return void 0;
|
|
1605
|
+
const poster = value.poster;
|
|
1606
|
+
if (!poster) return void 0;
|
|
1607
|
+
switch (poster.tag) {
|
|
1608
|
+
case "external-src":
|
|
1609
|
+
return poster.src;
|
|
1610
|
+
case "storage":
|
|
1611
|
+
return resolveMediaStorageUrl({
|
|
1612
|
+
type: "image",
|
|
1613
|
+
assetId: poster.assetId,
|
|
1614
|
+
storageBucket: poster.storageBucket,
|
|
1615
|
+
storagePath: poster.storagePath
|
|
1616
|
+
}, context);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
var debugMediaNodeLog = (...args) => {
|
|
1620
|
+
if (typeof window === "undefined") return;
|
|
1621
|
+
const debugFlag = Reflect.get(window, "__DEBUG_MEDIA_NODE__");
|
|
1622
|
+
if (debugFlag === true) console.log("[MediaNode]", ...args);
|
|
1623
|
+
};
|
|
1624
|
+
function resolveMediaNodeResponsiveImage(value, size, style, slot, context) {
|
|
1625
|
+
const styleAspectRatio = resolveStyleAspectRatio(style);
|
|
1626
|
+
const transformAspectRatio = styleAspectRatio ?? resolveTargetAspectRatio(size);
|
|
1627
|
+
const slotContract = resolveSlotContract(slot);
|
|
1628
|
+
const targetAspectRatioToken = slotContract?.edit.mode === "fixed-aspect" ? slotContract.edit.aspectRatio : void 0;
|
|
1629
|
+
const targetAspectRatio = parseAspectRatioValue(targetAspectRatioToken);
|
|
1630
|
+
const responsive = slotContract ? resolveImageSourceSetWithContext(
|
|
1631
|
+
value,
|
|
1632
|
+
{
|
|
1633
|
+
widthCandidates: slotContract.delivery.widthCandidates,
|
|
1634
|
+
sizes: slotContract.delivery.sizes,
|
|
1635
|
+
resize: "cover",
|
|
1636
|
+
quality: "quality" in size ? size.quality : 80,
|
|
1637
|
+
targetAspectRatio,
|
|
1638
|
+
defaultWidth: "width" in size && typeof size.width === "number" ? size.width : 640
|
|
1639
|
+
},
|
|
1640
|
+
context
|
|
1641
|
+
) : void 0;
|
|
1642
|
+
const imageUrl = responsive?.src ?? resolveImageUrlWithContext(value, size, context, transformAspectRatio);
|
|
1643
|
+
const resolvedTransform = resolveMediaTransformForAspect(value.transform, transformAspectRatio);
|
|
1644
|
+
const isProxy = typeof imageUrl === "string" && imageUrl.includes("/api/img/");
|
|
1645
|
+
return { transformAspectRatio, responsive, imageUrl, resolvedTransform, isProxy };
|
|
1646
|
+
}
|
|
1647
|
+
function resolveSlotContract(slot) {
|
|
1648
|
+
if (!slot.fieldPath) return void 0;
|
|
1649
|
+
const values = asRecord(slot.blockContent);
|
|
1650
|
+
if (!values) return void 0;
|
|
1651
|
+
return resolveMediaSlotContract({
|
|
1652
|
+
blockKind: slot.blockKind,
|
|
1653
|
+
fieldPath: slot.fieldPath,
|
|
1654
|
+
values,
|
|
1655
|
+
fieldAspectRatio: void 0,
|
|
1656
|
+
fieldUi: void 0
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
function resolveStyleAspectRatio(style) {
|
|
1660
|
+
const raw = style?.aspectRatio;
|
|
1661
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
1662
|
+
if (typeof raw === "string" && raw.trim().length > 0) return raw.trim();
|
|
1663
|
+
return void 0;
|
|
1664
|
+
}
|
|
1665
|
+
function renderVideo(value, className, style, context, options = {}) {
|
|
1666
|
+
if (value.type !== "video") return null;
|
|
1667
|
+
const src = resolvePublicMediaUrl(value, context);
|
|
1668
|
+
if (!src) return null;
|
|
1669
|
+
if (options.playback === "background") {
|
|
1670
|
+
const poster2 = resolveVideoPosterUrl(value, context);
|
|
1671
|
+
return /* @__PURE__ */ jsx(
|
|
1672
|
+
"video",
|
|
1673
|
+
{
|
|
1674
|
+
className,
|
|
1675
|
+
style,
|
|
1676
|
+
src,
|
|
1677
|
+
...poster2 ? { poster: poster2 } : {},
|
|
1678
|
+
autoPlay: true,
|
|
1679
|
+
muted: true,
|
|
1680
|
+
loop: true,
|
|
1681
|
+
playsInline: true,
|
|
1682
|
+
preload: "metadata",
|
|
1683
|
+
"aria-hidden": "true",
|
|
1684
|
+
"data-rb-background-video": "true"
|
|
1685
|
+
}
|
|
1686
|
+
);
|
|
1687
|
+
}
|
|
1688
|
+
const poster = resolveVideoPosterUrl(value, context);
|
|
1689
|
+
return /* @__PURE__ */ jsx(
|
|
1690
|
+
"video",
|
|
1691
|
+
{
|
|
1692
|
+
className,
|
|
1693
|
+
style,
|
|
1694
|
+
src,
|
|
1695
|
+
...poster ? { poster } : {},
|
|
1696
|
+
controls: true,
|
|
1697
|
+
controlsList: "nodownload",
|
|
1698
|
+
preload: "metadata",
|
|
1699
|
+
...value.alt ? { "aria-label": value.alt } : {}
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1702
|
+
}
|
|
1703
|
+
function resolvePublicMediaUrl(value, context) {
|
|
1704
|
+
return resolveMediaStorageUrl(value, context) ?? value.src;
|
|
1705
|
+
}
|
|
1706
|
+
function renderAudio(value, className, style, context) {
|
|
1707
|
+
if (value.type !== "audio") return null;
|
|
1708
|
+
const src = resolvePublicMediaUrl(value, context);
|
|
1709
|
+
if (!src) return null;
|
|
1710
|
+
return /* @__PURE__ */ jsx(
|
|
1711
|
+
"audio",
|
|
1712
|
+
{
|
|
1713
|
+
className,
|
|
1714
|
+
style,
|
|
1715
|
+
src,
|
|
1716
|
+
controls: true,
|
|
1717
|
+
controlsList: "nodownload",
|
|
1718
|
+
"aria-label": value.alt ?? "Audio"
|
|
1719
|
+
}
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
function computeMediaTransformStyle(value, style, targetAspectRatio, options) {
|
|
1723
|
+
const transform = options?.resolvedTransform ?? resolveMediaTransformForAspect(value.transform, targetAspectRatio);
|
|
1724
|
+
const rect = transform.rect;
|
|
1725
|
+
const hotspot = transform.hotspot;
|
|
1726
|
+
const rotation = transform.rotation;
|
|
1727
|
+
if (!rect && !hotspot && !rotation) return style;
|
|
1728
|
+
const stylePatch = {};
|
|
1729
|
+
const heuristicSuppressCss = Boolean(
|
|
1730
|
+
isExplicitCropProxyEnabled() && value.assetId && (typeof rotation === "number" && rotation !== 0 || isExplicitRectCrop(rect, getValidSourceDimension(value.width), getValidSourceDimension(value.height)))
|
|
1731
|
+
);
|
|
1732
|
+
const shouldSuppressCss = options?.isProxy ?? heuristicSuppressCss;
|
|
1733
|
+
if (rect && !shouldSuppressCss) {
|
|
1734
|
+
const rectPatch = buildCssRectStylePatch(value, rect);
|
|
1735
|
+
if (rectPatch) {
|
|
1736
|
+
const mergedRect = applyRectTransform(style, rectPatch);
|
|
1737
|
+
Object.assign(stylePatch, mergedRect);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
if (hotspot) {
|
|
1741
|
+
const effectiveObjectFit = stylePatch.objectFit ?? style?.objectFit;
|
|
1742
|
+
const shouldApplyHotspot = !effectiveObjectFit || effectiveObjectFit === "cover" || effectiveObjectFit === "contain";
|
|
1743
|
+
if (shouldApplyHotspot && stylePatch.objectPosition === void 0) {
|
|
1744
|
+
const resolved = shouldSuppressCss && rotation ? rotateNormalizedPoint({ x: hotspot.x, y: hotspot.y }, rotation) : { x: hotspot.x, y: hotspot.y };
|
|
1745
|
+
stylePatch.objectPosition = `${resolved.x * 100}% ${resolved.y * 100}%`;
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
if (rotation && !shouldSuppressCss) {
|
|
1749
|
+
const existingTransform = stylePatch.transform ?? style?.transform;
|
|
1750
|
+
stylePatch.transform = existingTransform ? `${existingTransform} rotate(${rotation}deg)` : `rotate(${rotation}deg)`;
|
|
1751
|
+
if (!stylePatch.transformOrigin) {
|
|
1752
|
+
stylePatch.transformOrigin = "center";
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
return mergeStyles(style, stylePatch);
|
|
1756
|
+
}
|
|
1757
|
+
function resolveTargetAspectRatio(size) {
|
|
1758
|
+
if ("original" in size) return void 0;
|
|
1759
|
+
if ("width" in size && "height" in size && typeof size.width === "number" && typeof size.height === "number") {
|
|
1760
|
+
return size.width / size.height;
|
|
1761
|
+
}
|
|
1762
|
+
return void 0;
|
|
1763
|
+
}
|
|
1764
|
+
function MediaPlaceholder({
|
|
1765
|
+
className,
|
|
1766
|
+
style
|
|
1767
|
+
}) {
|
|
1768
|
+
return /* @__PURE__ */ jsx(
|
|
1769
|
+
"div",
|
|
1770
|
+
{
|
|
1771
|
+
className: clsx_default("rb-flex rb-h-48 rb-w-full rb-items-center rb-justify-center", className),
|
|
1772
|
+
style: mergeStyles(backgroundColorStyle("surface"), style),
|
|
1773
|
+
children: /* @__PURE__ */ jsx("span", { className: "rb-caption", style: textColorStyle("mutedText"), children: "Image unavailable" })
|
|
1774
|
+
}
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
function resolveImageUrlWithContext(value, options, context, transformAspectRatio) {
|
|
1778
|
+
return resolveImageUrlWithContextInternal(value, options, context ?? void 0, transformAspectRatio);
|
|
1779
|
+
}
|
|
1780
|
+
function resolveImageUrlWithContextInternal(value, options, context, transformAspectRatio, resolved) {
|
|
1781
|
+
if (value.type !== "image") return void 0;
|
|
1782
|
+
const canonical = resolveMediaWithCanonicalAsset(value, context);
|
|
1783
|
+
debugMediaNodeLog("resolveImageUrl input", {
|
|
1784
|
+
assetId: canonical.assetId,
|
|
1785
|
+
storagePath: canonical.storagePath,
|
|
1786
|
+
src: canonical.src,
|
|
1787
|
+
type: canonical.type,
|
|
1788
|
+
options
|
|
1789
|
+
});
|
|
1790
|
+
if (canonical.storagePath && canonical.storagePath.length > 0) {
|
|
1791
|
+
const resolvedStorageUrl = resolveStorageImageUrl(canonical, options, context, transformAspectRatio, resolved);
|
|
1792
|
+
if (resolvedStorageUrl) {
|
|
1793
|
+
return resolvedStorageUrl;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
if (typeof canonical.src === "string" && canonical.src.length > 0) {
|
|
1797
|
+
debugMediaNodeLog("resolve:explicit-src", { src: canonical.src });
|
|
1798
|
+
return canonical.src;
|
|
1799
|
+
}
|
|
1800
|
+
const legacyUrl = typeof canonical === "object" && canonical !== null ? Reflect.get(canonical, "url") : void 0;
|
|
1801
|
+
debugMediaNodeLog("resolve:fallback-url", { fallbackUrl: typeof legacyUrl === "string" ? legacyUrl : null });
|
|
1802
|
+
return typeof legacyUrl === "string" ? legacyUrl : void 0;
|
|
1803
|
+
}
|
|
1804
|
+
function resolveImageSourceSetWithContext(value, options, context) {
|
|
1805
|
+
const normalizedContext = context ?? void 0;
|
|
1806
|
+
if (value.type !== "image") return void 0;
|
|
1807
|
+
const canonical = resolveMediaWithCanonicalAsset(value, normalizedContext);
|
|
1808
|
+
const widthCandidates = normalizeWidthCandidates(options.widthCandidates, MAX_SRCSET_WIDTH);
|
|
1809
|
+
if (widthCandidates.length === 0) return void 0;
|
|
1810
|
+
const targetAspectRatio = getPositiveAspectRatio(options.targetAspectRatio);
|
|
1811
|
+
const quality = options.quality;
|
|
1812
|
+
const resize = options.resize;
|
|
1813
|
+
const resolvedTransform = resolveMediaTransformForAspect(canonical.transform, targetAspectRatio);
|
|
1814
|
+
const sourceWidth = getValidSourceDimension(canonical.width);
|
|
1815
|
+
const sourceHeight = getValidSourceDimension(canonical.height);
|
|
1816
|
+
const hasExplicitRectCrop = isExplicitRectCrop(resolvedTransform.rect, sourceWidth, sourceHeight);
|
|
1817
|
+
const coverFactor = resolveCoverFactor({
|
|
1818
|
+
resize,
|
|
1819
|
+
targetAspectRatio,
|
|
1820
|
+
hasExplicitRectCrop,
|
|
1821
|
+
sourceWidth,
|
|
1822
|
+
sourceHeight
|
|
1823
|
+
});
|
|
1824
|
+
const shouldProxy = Boolean(
|
|
1825
|
+
isExplicitCropProxyEnabled() && canonical.assetId && (hasExplicitRectCrop || typeof resolvedTransform.rotation === "number" && resolvedTransform.rotation !== 0)
|
|
1826
|
+
);
|
|
1827
|
+
const effectiveSizes = coverFactor > 1 && typeof options.sizes === "string" && options.sizes.length > 0 ? scaleSizesAttribute(options.sizes, coverFactor) : options.sizes;
|
|
1828
|
+
const srcSetParts = widthCandidates.map((width) => {
|
|
1829
|
+
const height = shouldProxy && hasExplicitRectCrop ? getHeightForAspect(width, targetAspectRatio) : void 0;
|
|
1830
|
+
const effectiveResize = height ? resize : "contain";
|
|
1831
|
+
const url = resolveImageUrlWithContextInternal(
|
|
1832
|
+
canonical,
|
|
1833
|
+
height ? { width, height, resize: effectiveResize, quality } : { width, resize: effectiveResize, quality },
|
|
1834
|
+
normalizedContext,
|
|
1835
|
+
targetAspectRatio,
|
|
1836
|
+
{ resolvedTransform, sourceWidth, sourceHeight }
|
|
1837
|
+
);
|
|
1838
|
+
if (!url) return null;
|
|
1839
|
+
return `${url} ${width}w`;
|
|
1840
|
+
}).filter((entry) => entry !== null);
|
|
1841
|
+
if (srcSetParts.length === 0) return void 0;
|
|
1842
|
+
const fallbackWidth = widthCandidates[Math.min(2, widthCandidates.length - 1)];
|
|
1843
|
+
if (fallbackWidth === void 0) return void 0;
|
|
1844
|
+
const defaultWidth = options.defaultWidth ?? fallbackWidth;
|
|
1845
|
+
const scaledDefaultWidth = coverFactor > 1 ? Math.round(defaultWidth * coverFactor) : defaultWidth;
|
|
1846
|
+
const nearestWidth = widthCandidates.find((candidate) => candidate >= scaledDefaultWidth) ?? widthCandidates[widthCandidates.length - 1];
|
|
1847
|
+
if (nearestWidth === void 0) return void 0;
|
|
1848
|
+
const defaultHeight = shouldProxy && hasExplicitRectCrop ? getHeightForAspect(nearestWidth, targetAspectRatio) : void 0;
|
|
1849
|
+
const effectiveDefaultResize = defaultHeight ? resize : "contain";
|
|
1850
|
+
const src = resolveImageUrlWithContextInternal(
|
|
1851
|
+
canonical,
|
|
1852
|
+
defaultHeight ? { width: nearestWidth, height: defaultHeight, resize: effectiveDefaultResize, quality } : { width: nearestWidth, resize: effectiveDefaultResize, quality },
|
|
1853
|
+
normalizedContext,
|
|
1854
|
+
targetAspectRatio,
|
|
1855
|
+
{ resolvedTransform, sourceWidth, sourceHeight }
|
|
1856
|
+
);
|
|
1857
|
+
if (!src) return void 0;
|
|
1858
|
+
const fallbackSrc = shouldProxy ? getDirectImageUrlForValue(
|
|
1859
|
+
canonical,
|
|
1860
|
+
{ width: nearestWidth, resize: "contain", quality },
|
|
1861
|
+
normalizedContext
|
|
1862
|
+
) : void 0;
|
|
1863
|
+
return {
|
|
1864
|
+
src,
|
|
1865
|
+
srcSet: srcSetParts.join(", "),
|
|
1866
|
+
sizes: effectiveSizes,
|
|
1867
|
+
fallbackSrc
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
function resolveCoverFactor(input) {
|
|
1871
|
+
if (input.resize !== "cover") return 1;
|
|
1872
|
+
if (!input.targetAspectRatio) return 1;
|
|
1873
|
+
if (input.hasExplicitRectCrop) return 1;
|
|
1874
|
+
if (!input.sourceWidth || !input.sourceHeight) return 1;
|
|
1875
|
+
const sourceAspect = input.sourceWidth / input.sourceHeight;
|
|
1876
|
+
if (!Number.isFinite(sourceAspect) || sourceAspect <= 0) return 1;
|
|
1877
|
+
return sourceAspect > input.targetAspectRatio ? sourceAspect / input.targetAspectRatio : 1;
|
|
1878
|
+
}
|
|
1879
|
+
function scaleSizesAttribute(sizes, factor) {
|
|
1880
|
+
const parts = splitSizesAttributeList(sizes).map((part) => part.trim()).filter(Boolean);
|
|
1881
|
+
if (parts.length === 0) return sizes;
|
|
1882
|
+
return parts.map((part) => {
|
|
1883
|
+
const parsed = parseLeadingMediaCondition(part);
|
|
1884
|
+
if (parsed) {
|
|
1885
|
+
const scaled2 = scaleCssLengthExpression(parsed.length, factor);
|
|
1886
|
+
return scaled2 ? `${parsed.media} ${scaled2}` : part;
|
|
1887
|
+
}
|
|
1888
|
+
const scaled = scaleCssLengthExpression(part, factor);
|
|
1889
|
+
return scaled ?? part;
|
|
1890
|
+
}).join(", ");
|
|
1891
|
+
}
|
|
1892
|
+
function splitSizesAttributeList(sizes) {
|
|
1893
|
+
const out = [];
|
|
1894
|
+
let depth = 0;
|
|
1895
|
+
let start = 0;
|
|
1896
|
+
for (let i = 0; i < sizes.length; i++) {
|
|
1897
|
+
const ch = sizes[i];
|
|
1898
|
+
if (ch === "(") depth++;
|
|
1899
|
+
else if (ch === ")") depth = Math.max(0, depth - 1);
|
|
1900
|
+
else if (ch === "," && depth === 0) {
|
|
1901
|
+
out.push(sizes.slice(start, i));
|
|
1902
|
+
start = i + 1;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
out.push(sizes.slice(start));
|
|
1906
|
+
return out;
|
|
1907
|
+
}
|
|
1908
|
+
function parseLeadingMediaCondition(part) {
|
|
1909
|
+
const trimmed = part.trim();
|
|
1910
|
+
if (!trimmed.startsWith("(")) return null;
|
|
1911
|
+
let depth = 0;
|
|
1912
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
1913
|
+
const ch = trimmed[i];
|
|
1914
|
+
if (ch === "(") depth++;
|
|
1915
|
+
else if (ch === ")") {
|
|
1916
|
+
depth--;
|
|
1917
|
+
if (depth === 0) {
|
|
1918
|
+
const media = trimmed.slice(0, i + 1).trim();
|
|
1919
|
+
const length = trimmed.slice(i + 1).trim();
|
|
1920
|
+
if (!length) return null;
|
|
1921
|
+
return { media, length };
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
return null;
|
|
1926
|
+
}
|
|
1927
|
+
function scaleCssLengthExpression(token, factor) {
|
|
1928
|
+
const simple = scaleCssLengthToken(token, factor);
|
|
1929
|
+
if (simple) return simple;
|
|
1930
|
+
if (!/\d/.test(token)) return null;
|
|
1931
|
+
let didReplace = false;
|
|
1932
|
+
const scaled = token.replace(/(-?\d+(?:\.\d+)?)([a-z%]+)/gi, (_full, rawNum, unit) => {
|
|
1933
|
+
const raw = Number(rawNum);
|
|
1934
|
+
if (!Number.isFinite(raw)) return _full;
|
|
1935
|
+
didReplace = true;
|
|
1936
|
+
const value = raw * factor;
|
|
1937
|
+
if (!Number.isFinite(value)) return _full;
|
|
1938
|
+
if (unit.toLowerCase() === "px") return `${Math.round(value)}px`;
|
|
1939
|
+
const rounded = Math.round(value * 100) / 100;
|
|
1940
|
+
return `${rounded}${unit}`;
|
|
1941
|
+
});
|
|
1942
|
+
return didReplace ? scaled : null;
|
|
1943
|
+
}
|
|
1944
|
+
function scaleCssLengthToken(token, factor) {
|
|
1945
|
+
const match = token.match(/^(-?\d+(?:\.\d+)?)([a-z%]+)$/i);
|
|
1946
|
+
if (!match) return null;
|
|
1947
|
+
const raw = Number(match[1]);
|
|
1948
|
+
const unit = match[2];
|
|
1949
|
+
if (!unit) return null;
|
|
1950
|
+
if (!Number.isFinite(raw)) return null;
|
|
1951
|
+
const scaled = raw * factor;
|
|
1952
|
+
if (!Number.isFinite(scaled)) return null;
|
|
1953
|
+
if (unit.toLowerCase() === "px") {
|
|
1954
|
+
return `${Math.round(scaled)}px`;
|
|
1955
|
+
}
|
|
1956
|
+
const rounded = Math.round(scaled * 100) / 100;
|
|
1957
|
+
return `${rounded}${unit}`;
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
export { DEFAULT_BOOKING_TIME_ZONE, ImagePresets, MediaPlaceholder, addIntervalPreservingMonthAnchor, addLocalScheduleDays, asAppointmentResourceId, asAppointmentServiceId, asCustomerPassId, asFormId, asPassId, backgroundColorStyle, borderColorStyle, buildResolveImageUrlContext, clampConfiguredAmount, clsx_default, computeMediaTransformStyle, formatBookingDate, formatBookingDateParts, formatBookingDateTime, formatBookingInstant, formatBookingTime, formatLocalScheduleDate, getBookingInstalmentDepositRefundability, getBookingInstalmentPlanIntervalCount, getBookingLocalDateKey, getCurrentResolveImageUrlContext, mergeStyles, normalizeLocationAddressText, omitZeroAmountFutureRows, parseAspectRatioValue, parseBookingLocalDate, parseColorTokenParts, renderAudio, renderVideo, resolveBookingTimeZoneId, resolveFlexibleBalanceDueAt, resolveFlexibleBalanceInitialPaymentCents, resolveImageUrlWithContext, resolveMediaNodeResponsiveImage, resolvePlanningDateInput, rgbColorValue, setContextResolveImageUrlContext, splitAmountWithRemainderInFirst, textColorStyle, toBookingTimeZone, toLocationCoordinates, toScheduledBookingDateRange, toScheduledBookingDateTime };
|