@riverbankcms/sdk 0.135.1 → 0.136.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/CHANGELOG.md +13 -0
- package/README.md +4 -8
- package/dist/{PreviewEditorSidebar-D4p_5TdY.mjs → PreviewEditorSidebar-BU5ZlhQR.mjs} +4 -4
- package/dist/{PreviewEditorUI-D0cRoTX1.mjs → PreviewEditorUI-9XkHL-bC.mjs} +3 -3
- package/dist/{PreviewQueryProvider-DcgaESkm.mjs → PreviewQueryProvider-wbEpXryy.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-BKLtM3Nz.mjs → SdkPreviewModeRuntime-CnWmj-2B.mjs} +50 -99
- package/dist/{SiteChromeCustomizeContext-61X2m7QV.mjs → SiteChromeCustomizeContext-B6d5zkog.mjs} +2299 -1149
- package/dist/_dts/ai/src/contracts/proposals.d.ts +8 -554
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +401 -2312
- package/dist/_dts/api/src/contentRuntime.d.ts +6 -0
- package/dist/_dts/api/src/endpoints.d.ts +7 -0
- package/dist/_dts/api/src/index.d.ts +1 -0
- package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
- package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +26 -0
- package/dist/_dts/api/src/sdkBlockContentAdmission.d.ts +5 -0
- package/dist/_dts/api/src/sdkThemeWire.d.ts +6 -432
- package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +2 -3
- package/dist/_dts/block-form/src/utils/slug.d.ts +6 -0
- package/dist/_dts/blocks/src/PageRenderer.d.ts +12 -6
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +48 -0
- package/dist/_dts/blocks/src/definitions.d.ts +14 -0
- package/dist/_dts/blocks/src/index.d.ts +4 -3
- package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +40 -0
- package/dist/_dts/blocks/src/server.d.ts +2 -2
- package/dist/_dts/blocks/src/system/data/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +78 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +2 -18
- package/dist/_dts/blocks/src/system/manifest/validation.d.ts +103 -16
- package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +19 -0
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +52 -0
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +44 -18
- package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +20 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/VerifyingTimeoutStep.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.client.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +40 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +43 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarNavigationChevron.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalContext.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +31 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +9 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +4 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +3 -3
- package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +0 -1
- package/dist/_dts/calendar/src/grid.d.ts +24 -66
- package/dist/_dts/calendar/src/index.d.ts +2 -2
- package/dist/_dts/calendar/src/timetable.d.ts +5 -9
- package/dist/_dts/commerce/src/purchase/allocation.d.ts +11 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +2 -0
- package/dist/_dts/commerce/src/purchase/settlement.d.ts +33 -0
- package/dist/_dts/commerce/src/purchase/stripeCheckoutReturnUrl.d.ts +8 -0
- package/dist/_dts/content-model/src/templates/defaults.d.ts +6 -0
- package/dist/_dts/core/src/slug.d.ts +20 -5
- package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +2 -1
- package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +6 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -1
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +10 -6
- package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +0 -1
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +4 -4
- package/dist/_dts/sdk/src/rendering/helpers/footerPageOutline.d.ts +3 -0
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +3 -0
- package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +17 -0
- package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +9 -3
- package/dist/_dts/sdk/src/rendering/hooks/usePage.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/index.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +7 -4
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/cards/types.d.ts +8 -8
- package/dist/_dts/theme-core/src/data.d.ts +12 -0
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -6
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +6 -807
- package/dist/_dts/theme-core/src/schema.d.ts +452 -1278
- package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +213 -1
- package/dist/_dts/theme-core/src/site-styles/headerLayoutCatalog.d.ts +0 -29
- package/dist/_dts/theme-core/src/site-styles/headerLayoutStyles.d.ts +10 -0
- package/dist/_dts/theme-core/src/site-styles/headerLayoutTypes.d.ts +8 -5
- package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/headerStyleCompiler.d.ts +16 -2
- package/dist/_dts/theme-core/src/site-styles/headerStyleDefaults.d.ts +465 -0
- package/dist/_dts/theme-core/src/site-styles/headerStyleRecipe.d.ts +161 -0
- package/dist/client/{BookingConsentAgreement-Bz9znbpn.mjs → BookingConsentAgreement-DCch21a6.mjs} +2 -2
- package/dist/client/{DiscountCodeDisclosure-35Ru8yB9.mjs → DiscountCodeDisclosure-DIj1T59K.mjs} +1 -1
- package/dist/client/{EventCombined.client-BKB0ZxRR.mjs → EventCombined.client-BWVNlXTx.mjs} +226 -206
- package/dist/client/{EventListing.client-Dx8I21ok.mjs → EventListing.client-DVFCDe3i.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-CEWx-Bhe.mjs → LeafletStaticMap-BY5mIHw9.mjs} +1 -1
- package/dist/client/{accordion-KIDsKTwS.mjs → accordion-CK29E8rG.mjs} +1 -1
- package/dist/client/{bookingForm-D96Rmp-5.mjs → bookingForm-DFvnet-N.mjs} +5 -5
- package/dist/client/bookings.mjs +86 -47
- package/dist/client/{carousel-YwUgyL66.mjs → carousel-BVU5NQlb.mjs} +1 -1
- package/dist/client/{cart-BbwuNrUT.mjs → cart-BNItcZVa.mjs} +3 -3
- package/dist/client/{checkout-hp1ucmEY.mjs → checkout-Bu6iCdkP.mjs} +3 -3
- package/dist/client/client.mjs +1950 -1031
- package/dist/client/{context-DljQn8L5.mjs → context-BImarOAq.mjs} +12 -0
- package/dist/client/{eventCalendar-DU4iNLpo.mjs → eventCalendar-DS2h-UXD.mjs} +256 -114
- package/dist/client/{eventCombined-CZuupW8m.mjs → eventCombined-Drt4Oq9p.mjs} +3 -3
- package/dist/client/{eventDetails-DPQWwCIi.mjs → eventDetails-Bl2vWgTX.mjs} +4 -3
- package/dist/client/{eventListing-C7oMidwS.mjs → eventListing-CS7PHY7v.mjs} +3 -3
- package/dist/client/{eventRegistration-zEiunlUs.mjs → eventRegistration-D-j8eNy2.mjs} +85 -41
- package/dist/client/{form-D2KIyCVJ.mjs → form-RMpoLTyr.mjs} +2 -2
- package/dist/client/{headerSection-CK5uChUK.mjs → headerSection-BYE3Lb3k.mjs} +2 -2
- package/dist/client/hooks.mjs +2225 -276
- package/dist/client/{locationMap-DLQNH1ln.mjs → locationMap-BxSr7Kkh.mjs} +2 -2
- package/dist/client/{newsletterForm-ZuhIG7fZ.mjs → newsletterForm-DerbXwFC.mjs} +2 -2
- package/dist/client/{productDetail-7hIcGeae.mjs → productDetail-4SZCLhAf.mjs} +3 -3
- package/dist/client/{productList-T4Cii1ot.mjs → productList-D7AP4GNq.mjs} +3 -3
- package/dist/client/{propsDecoder-mB0aC_Fi.mjs → propsDecoder-pzBeCh14.mjs} +94 -24
- package/dist/client/rendering/client.mjs +758 -464
- package/dist/client/rendering/islands.mjs +17 -17
- package/dist/client/rendering.mjs +2126 -1244
- package/dist/client/{scrollToBlock-Du5mHgvL.mjs → scrollToBlock-CduAKf8T.mjs} +1 -1
- package/dist/client/{shop-B5zAcKZn.mjs → shop-Cp5p_kGe.mjs} +6 -6
- package/dist/client/{shop-commerce-BKBZB6l5.mjs → shop-commerce-DicXYaYX.mjs} +5 -5
- package/dist/client/{shop-commerce-store-Cq4qlNtQ.mjs → shop-commerce-store-CGWnpY4K.mjs} +1 -1
- package/dist/client/{shopShared-DYGzEs9D.mjs → shopShared-BDf9ljkm.mjs} +3 -3
- package/dist/client/{useEventFilters-Bphkda8m.mjs → useEventFilters-DeeyGYuk.mjs} +3 -3
- package/dist/preview-next/before-render.mjs +7 -0
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/keepAlive.mjs +7 -0
- package/dist/preview-next/middleware.mjs +7 -0
- package/dist/{previewAuthStore-C7ksxt5b.mjs → previewAuthStore-DbqBol0V.mjs} +7 -0
- package/dist/{sdk-runtime-BbIC8G4J.mjs → sdk-runtime-19MO27F0.mjs} +2 -2
- package/dist/{separator-CadhAtI7.mjs → separator-DaPLtJ1f.mjs} +1 -1
- package/dist/server/components.mjs +1527 -893
- package/dist/server/config-validation.mjs +65 -113
- package/dist/server/config.mjs +65 -113
- package/dist/server/data.mjs +65 -112
- package/dist/server/index.mjs +122 -4
- package/dist/server/manifest.mjs +0 -1
- package/dist/server/next.mjs +1432 -708
- package/dist/server/page-converter.mjs +58 -91
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +1682 -915
- package/dist/server/rendering.mjs +1694 -1020
- package/dist/server/routing.mjs +3230 -1843
- package/dist/server/server.mjs +21710 -19779
- package/dist/server/theme-bridge.mjs +656 -264
- package/dist/server/theme.mjs +2 -17
- package/dist/styles/index.css +609 -181
- package/package.json +1 -1
package/dist/client/hooks.mjs
CHANGED
|
@@ -1200,6 +1200,13 @@ const PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
|
|
|
1200
1200
|
//#endregion
|
|
1201
1201
|
//#region ../api/src/publicEventEndpointDefinitions.ts
|
|
1202
1202
|
const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
|
|
1203
|
+
resolvePublicEventCheckoutReturn: {
|
|
1204
|
+
path: "/public/sites/{siteId}/events/checkout-return",
|
|
1205
|
+
method: "POST",
|
|
1206
|
+
tags: [TAG_TEMPLATES.publicEvents, "event-checkout"],
|
|
1207
|
+
auth: "public",
|
|
1208
|
+
responseKind: "json"
|
|
1209
|
+
},
|
|
1203
1210
|
getPublicEventRegistrationOptions: {
|
|
1204
1211
|
path: "/public/sites/{siteId}/events/registration-options",
|
|
1205
1212
|
method: "POST",
|
|
@@ -1709,7 +1716,7 @@ const parseUserId = (value) => parseUuidBrand(value, unsafeAsUserId);
|
|
|
1709
1716
|
const parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
|
|
1710
1717
|
//#endregion
|
|
1711
1718
|
//#region ../core/src/assert-never.ts
|
|
1712
|
-
function assertNever$
|
|
1719
|
+
function assertNever$3(value, message = "Unexpected variant") {
|
|
1713
1720
|
throw new Error(`${message}: ${String(value)}`);
|
|
1714
1721
|
}
|
|
1715
1722
|
//#endregion
|
|
@@ -1798,7 +1805,7 @@ function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope) {
|
|
|
1798
1805
|
};
|
|
1799
1806
|
}
|
|
1800
1807
|
function parseEventPageSurfaceSubject(value) {
|
|
1801
|
-
if (!isRecord$
|
|
1808
|
+
if (!isRecord$14(value)) return err({ kind: "notObject" });
|
|
1802
1809
|
switch (value.kind) {
|
|
1803
1810
|
case "eventSeries": {
|
|
1804
1811
|
const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
|
|
@@ -1843,7 +1850,7 @@ function parseEventPageSurfaceSubject(value) {
|
|
|
1843
1850
|
});
|
|
1844
1851
|
}
|
|
1845
1852
|
}
|
|
1846
|
-
function isRecord$
|
|
1853
|
+
function isRecord$14(value) {
|
|
1847
1854
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1848
1855
|
}
|
|
1849
1856
|
//#endregion
|
|
@@ -1931,6 +1938,9 @@ function getZonedDateTimeParts(date, timeZone) {
|
|
|
1931
1938
|
function formatDateKey(date) {
|
|
1932
1939
|
return `${String(date.year).padStart(4, "0")}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
|
|
1933
1940
|
}
|
|
1941
|
+
function toBookingTimeZone(timeZone) {
|
|
1942
|
+
return getSafeTimeZone(timeZone);
|
|
1943
|
+
}
|
|
1934
1944
|
function parseUtcIsoDateTimeString(value) {
|
|
1935
1945
|
const normalized = value.trim();
|
|
1936
1946
|
const hasUtcSuffix = normalized.endsWith("Z");
|
|
@@ -2438,7 +2448,7 @@ const entryLinkSchema$1 = z.object({
|
|
|
2438
2448
|
contentType: z.string().min(1),
|
|
2439
2449
|
identifier: z.string().min(1)
|
|
2440
2450
|
}).passthrough();
|
|
2441
|
-
z.union([
|
|
2451
|
+
const linkSchema = z.union([
|
|
2442
2452
|
internalLinkSchema,
|
|
2443
2453
|
externalLinkSchema$1,
|
|
2444
2454
|
customLinkSchema$1,
|
|
@@ -8889,7 +8899,7 @@ function asDesignSystemTemplateId(value) {
|
|
|
8889
8899
|
function makeBoundaryId(previousBlockId, nextBlockId) {
|
|
8890
8900
|
return asDesignBoundaryId(`boundary:${encodeURIComponent(previousBlockId)}:${encodeURIComponent(nextBlockId)}`);
|
|
8891
8901
|
}
|
|
8892
|
-
function assertNever$
|
|
8902
|
+
function assertNever$2(value, message = "Unhandled Theme V2 variant") {
|
|
8893
8903
|
throw new Error(`${message}: ${String(value)}`);
|
|
8894
8904
|
}
|
|
8895
8905
|
function brandNonEmptyString(value, label) {
|
|
@@ -9146,12 +9156,8 @@ const legacyHeaderVariantValues = Object.keys(legacyHeaderVariants);
|
|
|
9146
9156
|
* `@riverbankcms/api` is `z.input<typeof themeSchema>`, so a widened input here
|
|
9147
9157
|
* would leak straight into a public type.
|
|
9148
9158
|
*
|
|
9149
|
-
*
|
|
9150
|
-
*
|
|
9151
|
-
* `apps/dashboard/src/server/services/sites/runtimeSiteResponse.ts` returns the
|
|
9152
|
-
* raw database JSON asserted as `Theme` with no parse, so a theme still
|
|
9153
|
-
* carrying a legacy spelling reaches the theme editor un-aliased. That gap
|
|
9154
|
-
* predates this alias and is harmless while persisted usage is zero.
|
|
9159
|
+
* Persisted runtime themes are admitted through `parseThemeForPersistence`
|
|
9160
|
+
* before reaching consumers, so legacy spellings normalize at that boundary.
|
|
9155
9161
|
*/
|
|
9156
9162
|
const headerVariantWithLegacyAliasSchema = z.enum([...headerVariantValues, ...legacyHeaderVariantValues]).transform((value) => value in legacyHeaderVariants ? legacyHeaderVariants[value] : value);
|
|
9157
9163
|
const BREAKPOINT_LG = 1024;
|
|
@@ -9265,7 +9271,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
|
|
|
9265
9271
|
})
|
|
9266
9272
|
]);
|
|
9267
9273
|
function normalizeAuthoringOpacity(value) {
|
|
9268
|
-
if (!isRecord$
|
|
9274
|
+
if (!isRecord$13(value)) return value;
|
|
9269
9275
|
return {
|
|
9270
9276
|
...value,
|
|
9271
9277
|
opacity: normalizeOpacity(value.opacity)
|
|
@@ -9274,7 +9280,7 @@ function normalizeAuthoringOpacity(value) {
|
|
|
9274
9280
|
function normalizeOpacity(value) {
|
|
9275
9281
|
return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
|
|
9276
9282
|
}
|
|
9277
|
-
function isRecord$
|
|
9283
|
+
function isRecord$13(value) {
|
|
9278
9284
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9279
9285
|
}
|
|
9280
9286
|
//#endregion
|
|
@@ -9610,7 +9616,6 @@ const navFontWeight = z.enum([
|
|
|
9610
9616
|
"bold"
|
|
9611
9617
|
]);
|
|
9612
9618
|
const headerMaxWidth = z.enum(["container", "full"]);
|
|
9613
|
-
const headerBarFrame = z.enum(["full-bleed", "inset-shell"]);
|
|
9614
9619
|
const headerBorderSchema = componentBorderSchema.extend({ position: z.enum([
|
|
9615
9620
|
"bottom",
|
|
9616
9621
|
"top",
|
|
@@ -9639,12 +9644,6 @@ const headerLogoTextSchema = z.object({
|
|
|
9639
9644
|
]).optional(),
|
|
9640
9645
|
hideOnShrink: z.boolean().optional()
|
|
9641
9646
|
}).optional();
|
|
9642
|
-
const navEffectsSchema = z.object({
|
|
9643
|
-
underlineGradient: z.boolean().default(false),
|
|
9644
|
-
glow: z.boolean().default(false),
|
|
9645
|
-
glowColor: z.string().optional(),
|
|
9646
|
-
neumorphic: z.boolean().default(false)
|
|
9647
|
-
}).optional();
|
|
9648
9647
|
const dropdownStyleSchema = z.object({
|
|
9649
9648
|
background: themeColorTokenSchema.default("surface"),
|
|
9650
9649
|
textColor: themeColorTokenSchema.default("text"),
|
|
@@ -9736,9 +9735,7 @@ const headerSchema = z.object({
|
|
|
9736
9735
|
positioning: headerPositioning,
|
|
9737
9736
|
shrinkOnScroll: z.boolean(),
|
|
9738
9737
|
maxWidth: headerMaxWidth,
|
|
9739
|
-
barFrame: headerBarFrame.optional(),
|
|
9740
9738
|
scrollTreatment: headerScrollTreatmentSchema,
|
|
9741
|
-
logoOverride: mediaSchema.nullable().optional(),
|
|
9742
9739
|
background: headerBackgroundSchema.default({
|
|
9743
9740
|
type: "color",
|
|
9744
9741
|
color: "surface"
|
|
@@ -9750,13 +9747,11 @@ const headerSchema = z.object({
|
|
|
9750
9747
|
navFontRole: z.enum(["body", "heading"]).optional(),
|
|
9751
9748
|
navTextSize: navLinkStyleSchema.shape.textSize,
|
|
9752
9749
|
interactionPalette: headerInteractionPaletteSchema.optional(),
|
|
9753
|
-
navPlacement: z.enum(["end", "center"]).optional(),
|
|
9754
9750
|
container: headerContainerSchema,
|
|
9755
9751
|
border: headerBorderSchema,
|
|
9756
9752
|
shadow: componentShadowSchema.optional(),
|
|
9757
9753
|
logo: logoStyleSchema,
|
|
9758
9754
|
logoText: headerLogoTextSchema,
|
|
9759
|
-
navEffects: navEffectsSchema,
|
|
9760
9755
|
navContainer: navContainerSchema,
|
|
9761
9756
|
navLinkStyle: navLinkStyleSchema.optional(),
|
|
9762
9757
|
ctaGap: headerCtaGapSchema.optional(),
|
|
@@ -11851,27 +11846,6 @@ function asHeaderStyleId(value) {
|
|
|
11851
11846
|
return value;
|
|
11852
11847
|
}
|
|
11853
11848
|
//#endregion
|
|
11854
|
-
//#region ../theme-core/src/site-styles/headerInteractionPalette.ts
|
|
11855
|
-
const clearSplitInteractionPalette = defineLookOptionGroup({
|
|
11856
|
-
id: "interaction-palette",
|
|
11857
|
-
label: "Hover colour",
|
|
11858
|
-
defaultOptionId: "accent",
|
|
11859
|
-
options: [
|
|
11860
|
-
{
|
|
11861
|
-
id: "accent",
|
|
11862
|
-
label: "Accent"
|
|
11863
|
-
},
|
|
11864
|
-
{
|
|
11865
|
-
id: "primary",
|
|
11866
|
-
label: "Primary"
|
|
11867
|
-
},
|
|
11868
|
-
{
|
|
11869
|
-
id: "secondary",
|
|
11870
|
-
label: "Secondary"
|
|
11871
|
-
}
|
|
11872
|
-
]
|
|
11873
|
-
});
|
|
11874
|
-
//#endregion
|
|
11875
11849
|
//#region ../theme-core/src/site-styles/headerLayoutCatalog.ts
|
|
11876
11850
|
const titleOnlyLogoAccommodation = {
|
|
11877
11851
|
pattern: "title-only",
|
|
@@ -12031,43 +12005,37 @@ const headerStyleCatalog = defineExactCatalog()([
|
|
|
12031
12005
|
id: asHeaderStyleId("minimal"),
|
|
12032
12006
|
label: "Minimal",
|
|
12033
12007
|
description: "Quiet surface with simple color-change navigation.",
|
|
12034
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12035
|
-
navTypography: "plain"
|
|
12008
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12036
12009
|
},
|
|
12037
12010
|
{
|
|
12038
12011
|
id: asHeaderStyleId("fine-line"),
|
|
12039
12012
|
label: "Seamless",
|
|
12040
12013
|
description: "Borderless surface with underline hover for a quieter page transition.",
|
|
12041
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12042
|
-
navTypography: "plain"
|
|
12014
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12043
12015
|
},
|
|
12044
12016
|
{
|
|
12045
12017
|
id: asHeaderStyleId("soft-bar"),
|
|
12046
12018
|
label: "Soft Bar",
|
|
12047
12019
|
description: "Soft tinted surface with gentle pill hover states.",
|
|
12048
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12049
|
-
navTypography: "plain"
|
|
12020
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12050
12021
|
},
|
|
12051
12022
|
{
|
|
12052
12023
|
id: asHeaderStyleId("pill-nav"),
|
|
12053
12024
|
label: "Pill Nav",
|
|
12054
12025
|
description: "A calm pill navigation rail over a neutral header.",
|
|
12055
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12056
|
-
navTypography: "plain"
|
|
12026
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12057
12027
|
},
|
|
12058
12028
|
{
|
|
12059
12029
|
id: asHeaderStyleId("brand-bar"),
|
|
12060
12030
|
label: "Brand Bar",
|
|
12061
12031
|
description: "Solid brand surface with high-contrast navigation.",
|
|
12062
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12063
|
-
navTypography: "brand-caps"
|
|
12032
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12064
12033
|
},
|
|
12065
12034
|
{
|
|
12066
12035
|
id: asHeaderStyleId("brand-underline"),
|
|
12067
12036
|
label: "Brand Underline",
|
|
12068
12037
|
description: "Brand surface with underline-grow navigation.",
|
|
12069
|
-
supportedLayoutIds: supportedLayouts(["classic"])
|
|
12070
|
-
navTypography: "brand-caps"
|
|
12038
|
+
supportedLayoutIds: supportedLayouts(["classic"])
|
|
12071
12039
|
},
|
|
12072
12040
|
{
|
|
12073
12041
|
id: asHeaderStyleId("brand-pill"),
|
|
@@ -12077,73 +12045,78 @@ const headerStyleCatalog = defineExactCatalog()([
|
|
|
12077
12045
|
"classic",
|
|
12078
12046
|
"centered",
|
|
12079
12047
|
"floating"
|
|
12080
|
-
])
|
|
12081
|
-
navTypography: "brand-caps"
|
|
12048
|
+
])
|
|
12082
12049
|
},
|
|
12083
12050
|
{
|
|
12084
12051
|
id: asHeaderStyleId("brand-capsule"),
|
|
12085
12052
|
label: "Brand Capsule",
|
|
12086
12053
|
description: "Solid brand chrome designed as a floating capsule, with quiet-caps nav, a soft pill active state, and an inverted CTA pill.",
|
|
12087
|
-
supportedLayoutIds: supportedLayouts(["classic"])
|
|
12088
|
-
navTypography: "quiet-caps"
|
|
12054
|
+
supportedLayoutIds: supportedLayouts(["classic"])
|
|
12089
12055
|
},
|
|
12090
12056
|
{
|
|
12091
12057
|
id: asHeaderStyleId("serif-line"),
|
|
12092
12058
|
label: "Serif Line",
|
|
12093
12059
|
description: "Typographic logo treatment with understated underline navigation.",
|
|
12094
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12095
|
-
navTypography: "heading"
|
|
12060
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12096
12061
|
},
|
|
12097
12062
|
{
|
|
12098
12063
|
id: asHeaderStyleId("flat-tabs"),
|
|
12099
12064
|
label: "Flat Tabs",
|
|
12100
12065
|
description: "Flat block hover and active states with a Swiss utility feel.",
|
|
12101
|
-
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12102
|
-
navTypography: "quiet-caps"
|
|
12066
|
+
supportedLayoutIds: supportedLayouts(["classic", "centered"])
|
|
12103
12067
|
},
|
|
12104
12068
|
{
|
|
12105
12069
|
id: asHeaderStyleId("glass"),
|
|
12106
12070
|
label: "Glass",
|
|
12107
12071
|
description: "Translucent chrome with frosted navigation backing.",
|
|
12108
|
-
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12109
|
-
navTypography: "plain"
|
|
12072
|
+
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12110
12073
|
},
|
|
12111
12074
|
{
|
|
12112
12075
|
id: asHeaderStyleId("minimal-surface"),
|
|
12113
12076
|
label: "Clear Split",
|
|
12114
12077
|
description: "Floating logo with transparent navigation and no shared shell.",
|
|
12115
|
-
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12116
|
-
navTypography: "plain",
|
|
12117
|
-
openingForegroundTarget: "all",
|
|
12118
|
-
scrollTreatment: "contrast-glass",
|
|
12119
|
-
interactionPalette: clearSplitInteractionPalette
|
|
12078
|
+
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12120
12079
|
},
|
|
12121
12080
|
{
|
|
12122
12081
|
id: asHeaderStyleId("soft-shell"),
|
|
12123
12082
|
label: "Soft Shell",
|
|
12124
12083
|
description: "Floating rounded shell with soft pill navigation states.",
|
|
12125
|
-
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12126
|
-
navTypography: "plain"
|
|
12084
|
+
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12127
12085
|
},
|
|
12128
12086
|
{
|
|
12129
12087
|
id: asHeaderStyleId("split-glass"),
|
|
12130
12088
|
label: "Split Glass",
|
|
12131
12089
|
description: "Logo floats independently while the navigation sits in a glass rail.",
|
|
12132
|
-
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12133
|
-
navTypography: "quiet-caps",
|
|
12134
|
-
openingForegroundTarget: "brand-only"
|
|
12090
|
+
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12135
12091
|
},
|
|
12136
12092
|
{
|
|
12137
12093
|
id: asHeaderStyleId("split-pill"),
|
|
12138
12094
|
label: "Split Pill",
|
|
12139
12095
|
description: "Logo floats independently with a soft pill-backed navigation rail.",
|
|
12140
|
-
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12141
|
-
navTypography: "heading",
|
|
12142
|
-
openingForegroundTarget: "brand-only"
|
|
12096
|
+
supportedLayoutIds: supportedLayouts(["floating"])
|
|
12143
12097
|
}
|
|
12144
12098
|
]);
|
|
12145
12099
|
new Map(headerLayoutCatalog.map((layout) => [layout.id, layout]));
|
|
12146
12100
|
new Map(headerStyleCatalog.map((style) => [style.id, style]));
|
|
12101
|
+
defineLookOptionGroup({
|
|
12102
|
+
id: "interaction-palette",
|
|
12103
|
+
label: "Hover colour",
|
|
12104
|
+
defaultOptionId: "accent",
|
|
12105
|
+
options: [
|
|
12106
|
+
{
|
|
12107
|
+
id: "accent",
|
|
12108
|
+
label: "Accent"
|
|
12109
|
+
},
|
|
12110
|
+
{
|
|
12111
|
+
id: "primary",
|
|
12112
|
+
label: "Primary"
|
|
12113
|
+
},
|
|
12114
|
+
{
|
|
12115
|
+
id: "secondary",
|
|
12116
|
+
label: "Secondary"
|
|
12117
|
+
}
|
|
12118
|
+
]
|
|
12119
|
+
});
|
|
12147
12120
|
//#endregion
|
|
12148
12121
|
//#region ../theme-core/src/site-styles/footerLooks.ts
|
|
12149
12122
|
function asFooterLookId(value) {
|
|
@@ -14829,7 +14802,7 @@ function planSiteChromePlacement(positioning) {
|
|
|
14829
14802
|
headerRootClassName: "rb-fixed rb-top-0 rb-left-0 rb-right-0",
|
|
14830
14803
|
standaloneShellClassName: "fixed left-0 right-0 top-0 z-40 w-full"
|
|
14831
14804
|
};
|
|
14832
|
-
default: return assertNever$
|
|
14805
|
+
default: return assertNever$2(positioning);
|
|
14833
14806
|
}
|
|
14834
14807
|
}
|
|
14835
14808
|
//#endregion
|
|
@@ -14896,14 +14869,9 @@ function formatKeyAsLabel(key) {
|
|
|
14896
14869
|
return key.replace(/([A-Z])/g, " $1").replace(/[-_]/g, " ").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
14897
14870
|
}
|
|
14898
14871
|
//#endregion
|
|
14899
|
-
//#region ../
|
|
14900
|
-
|
|
14901
|
-
|
|
14902
|
-
const globalScope$1 = globalThis;
|
|
14903
|
-
const manifestStore = isBlocksTestRuntime$1 ? /* @__PURE__ */ new Map() : globalScope$1[REGISTRY_SYMBOL$1] ?? (globalScope$1[REGISTRY_SYMBOL$1] = /* @__PURE__ */ new Map());
|
|
14904
|
-
function registerManifest(manifest) {
|
|
14905
|
-
manifestStore.set(manifest.name, manifest);
|
|
14906
|
-
return manifest;
|
|
14872
|
+
//#region ../media-core/src/typeGuards.ts
|
|
14873
|
+
function isRecord$12(value) {
|
|
14874
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
14907
14875
|
}
|
|
14908
14876
|
//#endregion
|
|
14909
14877
|
//#region ../media-core/src/transformRect.ts
|
|
@@ -14997,6 +14965,37 @@ function rotateNormalizedPoint(point, rotation) {
|
|
|
14997
14965
|
}
|
|
14998
14966
|
}
|
|
14999
14967
|
//#endregion
|
|
14968
|
+
//#region ../media-core/src/mediaRefNormalizer.ts
|
|
14969
|
+
function looksLikeUuid(value) {
|
|
14970
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
14971
|
+
}
|
|
14972
|
+
/**
|
|
14973
|
+
* Strip environment-specific keys from a CMS media object.
|
|
14974
|
+
* @mutates Mutates the passed object in-place.
|
|
14975
|
+
*/
|
|
14976
|
+
function deleteEnvSpecificKeys(obj) {
|
|
14977
|
+
delete obj.assetId;
|
|
14978
|
+
delete obj.storageBucket;
|
|
14979
|
+
delete obj.storagePath;
|
|
14980
|
+
delete obj.src;
|
|
14981
|
+
delete obj.mimeType;
|
|
14982
|
+
if (looksLikeUuid(obj.id)) delete obj.id;
|
|
14983
|
+
}
|
|
14984
|
+
//#endregion
|
|
14985
|
+
//#region ../media-core/src/richTextImageCollector.ts
|
|
14986
|
+
function walkAndCollectImageAttrs(value, out, location = "") {
|
|
14987
|
+
if (Array.isArray(value)) {
|
|
14988
|
+
value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
|
|
14989
|
+
return;
|
|
14990
|
+
}
|
|
14991
|
+
if (!isRecord$12(value)) return;
|
|
14992
|
+
if (value.type === "image" && isRecord$12(value.attrs)) out.push({
|
|
14993
|
+
attrs: value.attrs,
|
|
14994
|
+
location: location ? `${location}.attrs` : "attrs"
|
|
14995
|
+
});
|
|
14996
|
+
for (const [key, child] of Object.entries(value)) walkAndCollectImageAttrs(child, out, location ? `${location}.${key}` : key);
|
|
14997
|
+
}
|
|
14998
|
+
//#endregion
|
|
15000
14999
|
//#region ../blocks/src/system/node/schema.ts
|
|
15001
15000
|
const transformStepSchema = z.object({
|
|
15002
15001
|
id: z.string().min(1, "Transform requires an identifier"),
|
|
@@ -15644,6 +15643,14 @@ function parseFieldDefinition(input) {
|
|
|
15644
15643
|
function parseFieldDefinitions(input) {
|
|
15645
15644
|
return fieldSchema.array().parse(input);
|
|
15646
15645
|
}
|
|
15646
|
+
/**
|
|
15647
|
+
* Normalize legacy select fields into the closed source union before any consumer
|
|
15648
|
+
* branches on source semantics. Runtime-backed definitions must be explicit;
|
|
15649
|
+
* legacy static definitions normalize to `kind: "static"`.
|
|
15650
|
+
*/
|
|
15651
|
+
function normalizeSelectSource(field) {
|
|
15652
|
+
return field.source ?? { kind: "static" };
|
|
15653
|
+
}
|
|
15647
15654
|
function expectParsedSelectField(field) {
|
|
15648
15655
|
if (field.type !== "select") throw new Error(`Expected select field, received ${field.type}`);
|
|
15649
15656
|
return field;
|
|
@@ -15802,6 +15809,1932 @@ z.object({
|
|
|
15802
15809
|
tags: z.array(z.string()).optional(),
|
|
15803
15810
|
icon: z.string().optional()
|
|
15804
15811
|
});
|
|
15812
|
+
const inlineTextMarkSchema = z.discriminatedUnion("kind", [
|
|
15813
|
+
z.object({ kind: z.literal("strong") }),
|
|
15814
|
+
z.object({ kind: z.literal("emphasis") }),
|
|
15815
|
+
z.object({
|
|
15816
|
+
kind: z.literal("accent"),
|
|
15817
|
+
tone: z.enum([
|
|
15818
|
+
"accent",
|
|
15819
|
+
"brand",
|
|
15820
|
+
"contrast"
|
|
15821
|
+
])
|
|
15822
|
+
}),
|
|
15823
|
+
z.object({
|
|
15824
|
+
kind: z.literal("highlight"),
|
|
15825
|
+
tone: z.enum([
|
|
15826
|
+
"soft",
|
|
15827
|
+
"accent",
|
|
15828
|
+
"brand"
|
|
15829
|
+
])
|
|
15830
|
+
})
|
|
15831
|
+
]);
|
|
15832
|
+
const inlineTextRunSchema = z.object({
|
|
15833
|
+
text: z.string(),
|
|
15834
|
+
marks: z.array(inlineTextMarkSchema).optional()
|
|
15835
|
+
});
|
|
15836
|
+
z.array(inlineTextRunSchema);
|
|
15837
|
+
const MARK_ORDER = {
|
|
15838
|
+
strong: 0,
|
|
15839
|
+
emphasis: 1,
|
|
15840
|
+
accent: 2,
|
|
15841
|
+
highlight: 3
|
|
15842
|
+
};
|
|
15843
|
+
function plainTextToInlineText(value) {
|
|
15844
|
+
return normalizeInlineText(value.length > 0 ? [{ text: value }] : []);
|
|
15845
|
+
}
|
|
15846
|
+
function inlineTextToPlainText(value) {
|
|
15847
|
+
return value.map((run) => run.text).join("");
|
|
15848
|
+
}
|
|
15849
|
+
function parseInlineTextFromUnknown(value) {
|
|
15850
|
+
if (!Array.isArray(value)) return {
|
|
15851
|
+
ok: false,
|
|
15852
|
+
error: { kind: "not-array" }
|
|
15853
|
+
};
|
|
15854
|
+
const runs = [];
|
|
15855
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
15856
|
+
const parsed = inlineTextRunSchema.safeParse(value[index]);
|
|
15857
|
+
if (!parsed.success) return {
|
|
15858
|
+
ok: false,
|
|
15859
|
+
error: {
|
|
15860
|
+
kind: "invalid-run",
|
|
15861
|
+
index
|
|
15862
|
+
}
|
|
15863
|
+
};
|
|
15864
|
+
runs.push(parsed.data);
|
|
15865
|
+
}
|
|
15866
|
+
return {
|
|
15867
|
+
ok: true,
|
|
15868
|
+
value: normalizeInlineText(runs)
|
|
15869
|
+
};
|
|
15870
|
+
}
|
|
15871
|
+
function normalizeInlineText(value) {
|
|
15872
|
+
const normalized = [];
|
|
15873
|
+
for (const run of value) {
|
|
15874
|
+
if (run.text.length === 0) continue;
|
|
15875
|
+
const marks = normalizeInlineTextMarks(run.marks ?? []);
|
|
15876
|
+
const nextRun = marks.length > 0 ? {
|
|
15877
|
+
text: run.text,
|
|
15878
|
+
marks
|
|
15879
|
+
} : { text: run.text };
|
|
15880
|
+
const previous = normalized[normalized.length - 1];
|
|
15881
|
+
if (previous && inlineTextMarksEqual(previous.marks ?? [], nextRun.marks ?? [])) {
|
|
15882
|
+
normalized[normalized.length - 1] = previous.marks && previous.marks.length > 0 ? {
|
|
15883
|
+
text: previous.text + nextRun.text,
|
|
15884
|
+
marks: previous.marks
|
|
15885
|
+
} : { text: previous.text + nextRun.text };
|
|
15886
|
+
continue;
|
|
15887
|
+
}
|
|
15888
|
+
normalized.push(nextRun);
|
|
15889
|
+
}
|
|
15890
|
+
return normalized;
|
|
15891
|
+
}
|
|
15892
|
+
function normalizeInlineTextMarks(marks) {
|
|
15893
|
+
let strong = null;
|
|
15894
|
+
let emphasis = null;
|
|
15895
|
+
let accent = null;
|
|
15896
|
+
let highlight = null;
|
|
15897
|
+
for (const mark of marks) switch (mark.kind) {
|
|
15898
|
+
case "strong":
|
|
15899
|
+
strong = { kind: "strong" };
|
|
15900
|
+
break;
|
|
15901
|
+
case "emphasis":
|
|
15902
|
+
emphasis = { kind: "emphasis" };
|
|
15903
|
+
break;
|
|
15904
|
+
case "accent":
|
|
15905
|
+
accent = {
|
|
15906
|
+
kind: "accent",
|
|
15907
|
+
tone: mark.tone
|
|
15908
|
+
};
|
|
15909
|
+
break;
|
|
15910
|
+
case "highlight":
|
|
15911
|
+
highlight = {
|
|
15912
|
+
kind: "highlight",
|
|
15913
|
+
tone: mark.tone
|
|
15914
|
+
};
|
|
15915
|
+
break;
|
|
15916
|
+
}
|
|
15917
|
+
return [
|
|
15918
|
+
strong,
|
|
15919
|
+
emphasis,
|
|
15920
|
+
accent,
|
|
15921
|
+
highlight
|
|
15922
|
+
].filter((mark) => mark !== null).sort((left, right) => MARK_ORDER[left.kind] - MARK_ORDER[right.kind]);
|
|
15923
|
+
}
|
|
15924
|
+
function inlineTextMarksEqual(left, right) {
|
|
15925
|
+
const normalizedLeft = normalizeInlineTextMarks(left);
|
|
15926
|
+
const normalizedRight = normalizeInlineTextMarks(right);
|
|
15927
|
+
if (normalizedLeft.length !== normalizedRight.length) return false;
|
|
15928
|
+
return normalizedLeft.every((mark, index) => inlineTextMarkEqual(mark, normalizedRight[index]));
|
|
15929
|
+
}
|
|
15930
|
+
function inlineTextMarkEqual(left, right) {
|
|
15931
|
+
if (!right || left.kind !== right.kind) return false;
|
|
15932
|
+
switch (left.kind) {
|
|
15933
|
+
case "strong":
|
|
15934
|
+
case "emphasis": return true;
|
|
15935
|
+
case "accent": return right.kind === "accent" && left.tone === right.tone;
|
|
15936
|
+
case "highlight": return right.kind === "highlight" && left.tone === right.tone;
|
|
15937
|
+
}
|
|
15938
|
+
}
|
|
15939
|
+
//#endregion
|
|
15940
|
+
//#region ../blocks/src/system/icons/ids.ts
|
|
15941
|
+
const GENERATED_ICON_SET_ID_PATTERN = /^generated-icon-set:[a-z0-9][a-z0-9:_-]{0,107}$/u;
|
|
15942
|
+
const GENERATED_ICON_ASSET_ID_PATTERN = /^generated-icon-asset:[a-z0-9][a-z0-9:_-]{0,105}$/u;
|
|
15943
|
+
const SITE_ICON_STYLE_GUIDE_VERSION_ID_PATTERN = /^site-icon-style-guide:[a-f0-9]{16}$/u;
|
|
15944
|
+
function normalizeString(value) {
|
|
15945
|
+
if (typeof value !== "string") return null;
|
|
15946
|
+
const normalized = value.trim();
|
|
15947
|
+
return normalized.length > 0 ? normalized : null;
|
|
15948
|
+
}
|
|
15949
|
+
function unsafeAsGeneratedIconSetId(value) {
|
|
15950
|
+
return value;
|
|
15951
|
+
}
|
|
15952
|
+
function unsafeAsGeneratedIconAssetId(value) {
|
|
15953
|
+
return value;
|
|
15954
|
+
}
|
|
15955
|
+
function unsafeAsSiteIconStyleGuideVersionId(value) {
|
|
15956
|
+
return value;
|
|
15957
|
+
}
|
|
15958
|
+
function parseGeneratedIconSetId(value) {
|
|
15959
|
+
const normalized = normalizeString(value);
|
|
15960
|
+
return normalized !== null && GENERATED_ICON_SET_ID_PATTERN.test(normalized) ? unsafeAsGeneratedIconSetId(normalized) : null;
|
|
15961
|
+
}
|
|
15962
|
+
function parseGeneratedIconAssetId(value) {
|
|
15963
|
+
const normalized = normalizeString(value);
|
|
15964
|
+
return normalized !== null && GENERATED_ICON_ASSET_ID_PATTERN.test(normalized) ? unsafeAsGeneratedIconAssetId(normalized) : null;
|
|
15965
|
+
}
|
|
15966
|
+
function parseSiteIconStyleGuideVersionId(value) {
|
|
15967
|
+
if (typeof value !== "string") return null;
|
|
15968
|
+
const normalized = value.trim();
|
|
15969
|
+
return SITE_ICON_STYLE_GUIDE_VERSION_ID_PATTERN.test(normalized) ? unsafeAsSiteIconStyleGuideVersionId(normalized) : null;
|
|
15970
|
+
}
|
|
15971
|
+
//#endregion
|
|
15972
|
+
//#region ../blocks/src/system/icons/semantic.ts
|
|
15973
|
+
const SEMANTIC_ICON_IDS = [
|
|
15974
|
+
"protection-trust",
|
|
15975
|
+
"confidentiality",
|
|
15976
|
+
"care-support",
|
|
15977
|
+
"partnership",
|
|
15978
|
+
"warmth",
|
|
15979
|
+
"community",
|
|
15980
|
+
"personal-guidance",
|
|
15981
|
+
"conversation",
|
|
15982
|
+
"friendly-welcome",
|
|
15983
|
+
"insight-learning",
|
|
15984
|
+
"natural-wellbeing",
|
|
15985
|
+
"growth",
|
|
15986
|
+
"gentle-care",
|
|
15987
|
+
"special-touch",
|
|
15988
|
+
"ideas",
|
|
15989
|
+
"direction",
|
|
15990
|
+
"focus",
|
|
15991
|
+
"quality",
|
|
15992
|
+
"highlight",
|
|
15993
|
+
"verified-quality",
|
|
15994
|
+
"learning",
|
|
15995
|
+
"training",
|
|
15996
|
+
"programmes-dates",
|
|
15997
|
+
"place",
|
|
15998
|
+
"products",
|
|
15999
|
+
"packages",
|
|
16000
|
+
"time",
|
|
16001
|
+
"practical-service",
|
|
16002
|
+
"at-home",
|
|
16003
|
+
"worldwide",
|
|
16004
|
+
"professional-service"
|
|
16005
|
+
];
|
|
16006
|
+
const featurePreset = ["feature"];
|
|
16007
|
+
[
|
|
16008
|
+
{
|
|
16009
|
+
id: "protection-trust",
|
|
16010
|
+
label: "Protection and trust",
|
|
16011
|
+
tags: [
|
|
16012
|
+
"safe",
|
|
16013
|
+
"safety",
|
|
16014
|
+
"security",
|
|
16015
|
+
"trust",
|
|
16016
|
+
"privacy",
|
|
16017
|
+
"confidence"
|
|
16018
|
+
],
|
|
16019
|
+
domains: [
|
|
16020
|
+
"wellbeing",
|
|
16021
|
+
"services",
|
|
16022
|
+
"technology"
|
|
16023
|
+
],
|
|
16024
|
+
tone: ["trustworthy", "practical"],
|
|
16025
|
+
presets: featurePreset
|
|
16026
|
+
},
|
|
16027
|
+
{
|
|
16028
|
+
id: "confidentiality",
|
|
16029
|
+
label: "Confidentiality",
|
|
16030
|
+
tags: [
|
|
16031
|
+
"confidential",
|
|
16032
|
+
"privacy",
|
|
16033
|
+
"secure",
|
|
16034
|
+
"protected",
|
|
16035
|
+
"private"
|
|
16036
|
+
],
|
|
16037
|
+
domains: [
|
|
16038
|
+
"wellbeing",
|
|
16039
|
+
"coaching",
|
|
16040
|
+
"services",
|
|
16041
|
+
"technology"
|
|
16042
|
+
],
|
|
16043
|
+
tone: ["trustworthy", "calm"],
|
|
16044
|
+
presets: featurePreset
|
|
16045
|
+
},
|
|
16046
|
+
{
|
|
16047
|
+
id: "care-support",
|
|
16048
|
+
label: "Care and support",
|
|
16049
|
+
tags: [
|
|
16050
|
+
"care",
|
|
16051
|
+
"support",
|
|
16052
|
+
"therapy",
|
|
16053
|
+
"kindness",
|
|
16054
|
+
"help",
|
|
16055
|
+
"compassion"
|
|
16056
|
+
],
|
|
16057
|
+
domains: [
|
|
16058
|
+
"wellbeing",
|
|
16059
|
+
"coaching",
|
|
16060
|
+
"community"
|
|
16061
|
+
],
|
|
16062
|
+
tone: ["warm", "human"],
|
|
16063
|
+
presets: featurePreset
|
|
16064
|
+
},
|
|
16065
|
+
{
|
|
16066
|
+
id: "partnership",
|
|
16067
|
+
label: "Partnership",
|
|
16068
|
+
tags: [
|
|
16069
|
+
"partnership",
|
|
16070
|
+
"together",
|
|
16071
|
+
"support",
|
|
16072
|
+
"relationship",
|
|
16073
|
+
"collaboration"
|
|
16074
|
+
],
|
|
16075
|
+
domains: [
|
|
16076
|
+
"coaching",
|
|
16077
|
+
"community",
|
|
16078
|
+
"services"
|
|
16079
|
+
],
|
|
16080
|
+
tone: [
|
|
16081
|
+
"warm",
|
|
16082
|
+
"human",
|
|
16083
|
+
"trustworthy"
|
|
16084
|
+
],
|
|
16085
|
+
presets: featurePreset
|
|
16086
|
+
},
|
|
16087
|
+
{
|
|
16088
|
+
id: "warmth",
|
|
16089
|
+
label: "Warmth",
|
|
16090
|
+
tags: [
|
|
16091
|
+
"heart",
|
|
16092
|
+
"warmth",
|
|
16093
|
+
"care",
|
|
16094
|
+
"love",
|
|
16095
|
+
"wellbeing",
|
|
16096
|
+
"personal"
|
|
16097
|
+
],
|
|
16098
|
+
domains: [
|
|
16099
|
+
"wellbeing",
|
|
16100
|
+
"community",
|
|
16101
|
+
"hospitality"
|
|
16102
|
+
],
|
|
16103
|
+
tone: ["warm", "human"],
|
|
16104
|
+
presets: featurePreset
|
|
16105
|
+
},
|
|
16106
|
+
{
|
|
16107
|
+
id: "community",
|
|
16108
|
+
label: "Community",
|
|
16109
|
+
tags: [
|
|
16110
|
+
"community",
|
|
16111
|
+
"group",
|
|
16112
|
+
"people",
|
|
16113
|
+
"team",
|
|
16114
|
+
"members",
|
|
16115
|
+
"belonging"
|
|
16116
|
+
],
|
|
16117
|
+
domains: [
|
|
16118
|
+
"community",
|
|
16119
|
+
"education",
|
|
16120
|
+
"events"
|
|
16121
|
+
],
|
|
16122
|
+
tone: ["human", "warm"],
|
|
16123
|
+
presets: featurePreset
|
|
16124
|
+
},
|
|
16125
|
+
{
|
|
16126
|
+
id: "personal-guidance",
|
|
16127
|
+
label: "Personal guidance",
|
|
16128
|
+
tags: [
|
|
16129
|
+
"guidance",
|
|
16130
|
+
"personal",
|
|
16131
|
+
"coach",
|
|
16132
|
+
"expert",
|
|
16133
|
+
"one to one",
|
|
16134
|
+
"trusted"
|
|
16135
|
+
],
|
|
16136
|
+
domains: [
|
|
16137
|
+
"coaching",
|
|
16138
|
+
"services",
|
|
16139
|
+
"education"
|
|
16140
|
+
],
|
|
16141
|
+
tone: ["trustworthy", "human"],
|
|
16142
|
+
presets: featurePreset
|
|
16143
|
+
},
|
|
16144
|
+
{
|
|
16145
|
+
id: "conversation",
|
|
16146
|
+
label: "Conversation",
|
|
16147
|
+
tags: [
|
|
16148
|
+
"conversation",
|
|
16149
|
+
"talk",
|
|
16150
|
+
"chat",
|
|
16151
|
+
"communication",
|
|
16152
|
+
"support"
|
|
16153
|
+
],
|
|
16154
|
+
domains: [
|
|
16155
|
+
"coaching",
|
|
16156
|
+
"community",
|
|
16157
|
+
"services"
|
|
16158
|
+
],
|
|
16159
|
+
tone: ["human", "warm"],
|
|
16160
|
+
presets: featurePreset
|
|
16161
|
+
},
|
|
16162
|
+
{
|
|
16163
|
+
id: "friendly-welcome",
|
|
16164
|
+
label: "Friendly welcome",
|
|
16165
|
+
tags: [
|
|
16166
|
+
"friendly",
|
|
16167
|
+
"welcome",
|
|
16168
|
+
"positive",
|
|
16169
|
+
"happy",
|
|
16170
|
+
"approachable"
|
|
16171
|
+
],
|
|
16172
|
+
domains: [
|
|
16173
|
+
"hospitality",
|
|
16174
|
+
"community",
|
|
16175
|
+
"services"
|
|
16176
|
+
],
|
|
16177
|
+
tone: [
|
|
16178
|
+
"warm",
|
|
16179
|
+
"playful",
|
|
16180
|
+
"human"
|
|
16181
|
+
],
|
|
16182
|
+
presets: featurePreset
|
|
16183
|
+
},
|
|
16184
|
+
{
|
|
16185
|
+
id: "insight-learning",
|
|
16186
|
+
label: "Insight and learning",
|
|
16187
|
+
tags: [
|
|
16188
|
+
"mind",
|
|
16189
|
+
"insight",
|
|
16190
|
+
"learning",
|
|
16191
|
+
"clarity",
|
|
16192
|
+
"thinking",
|
|
16193
|
+
"therapy"
|
|
16194
|
+
],
|
|
16195
|
+
domains: [
|
|
16196
|
+
"wellbeing",
|
|
16197
|
+
"coaching",
|
|
16198
|
+
"education"
|
|
16199
|
+
],
|
|
16200
|
+
tone: ["calm", "practical"],
|
|
16201
|
+
presets: featurePreset
|
|
16202
|
+
},
|
|
16203
|
+
{
|
|
16204
|
+
id: "natural-wellbeing",
|
|
16205
|
+
label: "Natural wellbeing",
|
|
16206
|
+
tags: [
|
|
16207
|
+
"natural",
|
|
16208
|
+
"wellbeing",
|
|
16209
|
+
"growth",
|
|
16210
|
+
"eco",
|
|
16211
|
+
"calm",
|
|
16212
|
+
"organic"
|
|
16213
|
+
],
|
|
16214
|
+
domains: [
|
|
16215
|
+
"wellbeing",
|
|
16216
|
+
"hospitality",
|
|
16217
|
+
"creative"
|
|
16218
|
+
],
|
|
16219
|
+
tone: ["calm", "warm"],
|
|
16220
|
+
presets: featurePreset
|
|
16221
|
+
},
|
|
16222
|
+
{
|
|
16223
|
+
id: "growth",
|
|
16224
|
+
label: "Growth",
|
|
16225
|
+
tags: [
|
|
16226
|
+
"growth",
|
|
16227
|
+
"new",
|
|
16228
|
+
"progress",
|
|
16229
|
+
"development",
|
|
16230
|
+
"nurture"
|
|
16231
|
+
],
|
|
16232
|
+
domains: [
|
|
16233
|
+
"wellbeing",
|
|
16234
|
+
"coaching",
|
|
16235
|
+
"education",
|
|
16236
|
+
"community"
|
|
16237
|
+
],
|
|
16238
|
+
tone: ["warm", "calm"],
|
|
16239
|
+
presets: featurePreset
|
|
16240
|
+
},
|
|
16241
|
+
{
|
|
16242
|
+
id: "gentle-care",
|
|
16243
|
+
label: "Gentle care",
|
|
16244
|
+
tags: [
|
|
16245
|
+
"gentle",
|
|
16246
|
+
"soft",
|
|
16247
|
+
"care",
|
|
16248
|
+
"wellbeing",
|
|
16249
|
+
"beauty",
|
|
16250
|
+
"calm"
|
|
16251
|
+
],
|
|
16252
|
+
domains: [
|
|
16253
|
+
"wellbeing",
|
|
16254
|
+
"creative",
|
|
16255
|
+
"hospitality"
|
|
16256
|
+
],
|
|
16257
|
+
tone: [
|
|
16258
|
+
"warm",
|
|
16259
|
+
"calm",
|
|
16260
|
+
"premium"
|
|
16261
|
+
],
|
|
16262
|
+
presets: featurePreset
|
|
16263
|
+
},
|
|
16264
|
+
{
|
|
16265
|
+
id: "special-touch",
|
|
16266
|
+
label: "Special touch",
|
|
16267
|
+
tags: [
|
|
16268
|
+
"special",
|
|
16269
|
+
"sparkle",
|
|
16270
|
+
"magic",
|
|
16271
|
+
"polish",
|
|
16272
|
+
"delight",
|
|
16273
|
+
"creative"
|
|
16274
|
+
],
|
|
16275
|
+
domains: [
|
|
16276
|
+
"creative",
|
|
16277
|
+
"commerce",
|
|
16278
|
+
"hospitality"
|
|
16279
|
+
],
|
|
16280
|
+
tone: ["playful", "premium"],
|
|
16281
|
+
presets: featurePreset
|
|
16282
|
+
},
|
|
16283
|
+
{
|
|
16284
|
+
id: "ideas",
|
|
16285
|
+
label: "Ideas",
|
|
16286
|
+
tags: [
|
|
16287
|
+
"idea",
|
|
16288
|
+
"innovation",
|
|
16289
|
+
"clarity",
|
|
16290
|
+
"creative",
|
|
16291
|
+
"strategy"
|
|
16292
|
+
],
|
|
16293
|
+
domains: [
|
|
16294
|
+
"coaching",
|
|
16295
|
+
"education",
|
|
16296
|
+
"creative",
|
|
16297
|
+
"technology"
|
|
16298
|
+
],
|
|
16299
|
+
tone: ["practical", "playful"],
|
|
16300
|
+
presets: featurePreset
|
|
16301
|
+
},
|
|
16302
|
+
{
|
|
16303
|
+
id: "direction",
|
|
16304
|
+
label: "Direction",
|
|
16305
|
+
tags: [
|
|
16306
|
+
"direction",
|
|
16307
|
+
"navigation",
|
|
16308
|
+
"path",
|
|
16309
|
+
"journey",
|
|
16310
|
+
"guidance"
|
|
16311
|
+
],
|
|
16312
|
+
domains: [
|
|
16313
|
+
"coaching",
|
|
16314
|
+
"education",
|
|
16315
|
+
"services"
|
|
16316
|
+
],
|
|
16317
|
+
tone: ["trustworthy", "practical"],
|
|
16318
|
+
presets: featurePreset
|
|
16319
|
+
},
|
|
16320
|
+
{
|
|
16321
|
+
id: "focus",
|
|
16322
|
+
label: "Focus",
|
|
16323
|
+
tags: [
|
|
16324
|
+
"focus",
|
|
16325
|
+
"goal",
|
|
16326
|
+
"outcome",
|
|
16327
|
+
"aim",
|
|
16328
|
+
"strategy"
|
|
16329
|
+
],
|
|
16330
|
+
domains: [
|
|
16331
|
+
"coaching",
|
|
16332
|
+
"services",
|
|
16333
|
+
"technology"
|
|
16334
|
+
],
|
|
16335
|
+
tone: ["practical"],
|
|
16336
|
+
presets: featurePreset
|
|
16337
|
+
},
|
|
16338
|
+
{
|
|
16339
|
+
id: "quality",
|
|
16340
|
+
label: "Quality",
|
|
16341
|
+
tags: [
|
|
16342
|
+
"quality",
|
|
16343
|
+
"award",
|
|
16344
|
+
"standard",
|
|
16345
|
+
"achievement",
|
|
16346
|
+
"premium"
|
|
16347
|
+
],
|
|
16348
|
+
domains: [
|
|
16349
|
+
"services",
|
|
16350
|
+
"education",
|
|
16351
|
+
"commerce"
|
|
16352
|
+
],
|
|
16353
|
+
tone: ["premium", "trustworthy"],
|
|
16354
|
+
presets: featurePreset
|
|
16355
|
+
},
|
|
16356
|
+
{
|
|
16357
|
+
id: "highlight",
|
|
16358
|
+
label: "Highlight",
|
|
16359
|
+
tags: [
|
|
16360
|
+
"highlight",
|
|
16361
|
+
"featured",
|
|
16362
|
+
"favorite",
|
|
16363
|
+
"quality",
|
|
16364
|
+
"special"
|
|
16365
|
+
],
|
|
16366
|
+
domains: [
|
|
16367
|
+
"creative",
|
|
16368
|
+
"commerce",
|
|
16369
|
+
"services"
|
|
16370
|
+
],
|
|
16371
|
+
tone: ["playful", "premium"],
|
|
16372
|
+
presets: featurePreset
|
|
16373
|
+
},
|
|
16374
|
+
{
|
|
16375
|
+
id: "verified-quality",
|
|
16376
|
+
label: "Verified quality",
|
|
16377
|
+
tags: [
|
|
16378
|
+
"verified",
|
|
16379
|
+
"quality",
|
|
16380
|
+
"approved",
|
|
16381
|
+
"trusted",
|
|
16382
|
+
"check"
|
|
16383
|
+
],
|
|
16384
|
+
domains: [
|
|
16385
|
+
"services",
|
|
16386
|
+
"commerce",
|
|
16387
|
+
"education"
|
|
16388
|
+
],
|
|
16389
|
+
tone: ["trustworthy", "practical"],
|
|
16390
|
+
presets: featurePreset
|
|
16391
|
+
},
|
|
16392
|
+
{
|
|
16393
|
+
id: "learning",
|
|
16394
|
+
label: "Learning",
|
|
16395
|
+
tags: [
|
|
16396
|
+
"learning",
|
|
16397
|
+
"book",
|
|
16398
|
+
"course",
|
|
16399
|
+
"knowledge",
|
|
16400
|
+
"education"
|
|
16401
|
+
],
|
|
16402
|
+
domains: [
|
|
16403
|
+
"education",
|
|
16404
|
+
"coaching",
|
|
16405
|
+
"community"
|
|
16406
|
+
],
|
|
16407
|
+
tone: ["calm", "practical"],
|
|
16408
|
+
presets: featurePreset
|
|
16409
|
+
},
|
|
16410
|
+
{
|
|
16411
|
+
id: "training",
|
|
16412
|
+
label: "Training",
|
|
16413
|
+
tags: [
|
|
16414
|
+
"training",
|
|
16415
|
+
"course",
|
|
16416
|
+
"qualification",
|
|
16417
|
+
"school",
|
|
16418
|
+
"education"
|
|
16419
|
+
],
|
|
16420
|
+
domains: ["education", "coaching"],
|
|
16421
|
+
tone: ["trustworthy", "practical"],
|
|
16422
|
+
presets: featurePreset
|
|
16423
|
+
},
|
|
16424
|
+
{
|
|
16425
|
+
id: "programmes-dates",
|
|
16426
|
+
label: "Programmes and dates",
|
|
16427
|
+
tags: [
|
|
16428
|
+
"calendar",
|
|
16429
|
+
"dates",
|
|
16430
|
+
"schedule",
|
|
16431
|
+
"events",
|
|
16432
|
+
"programme",
|
|
16433
|
+
"classes"
|
|
16434
|
+
],
|
|
16435
|
+
domains: [
|
|
16436
|
+
"events",
|
|
16437
|
+
"education",
|
|
16438
|
+
"community"
|
|
16439
|
+
],
|
|
16440
|
+
tone: ["practical"],
|
|
16441
|
+
presets: featurePreset
|
|
16442
|
+
},
|
|
16443
|
+
{
|
|
16444
|
+
id: "place",
|
|
16445
|
+
label: "Place",
|
|
16446
|
+
tags: [
|
|
16447
|
+
"place",
|
|
16448
|
+
"location",
|
|
16449
|
+
"local",
|
|
16450
|
+
"venue",
|
|
16451
|
+
"destination"
|
|
16452
|
+
],
|
|
16453
|
+
domains: [
|
|
16454
|
+
"events",
|
|
16455
|
+
"hospitality",
|
|
16456
|
+
"services"
|
|
16457
|
+
],
|
|
16458
|
+
tone: ["practical"],
|
|
16459
|
+
presets: featurePreset
|
|
16460
|
+
},
|
|
16461
|
+
{
|
|
16462
|
+
id: "products",
|
|
16463
|
+
label: "Products",
|
|
16464
|
+
tags: [
|
|
16465
|
+
"products",
|
|
16466
|
+
"shop",
|
|
16467
|
+
"store",
|
|
16468
|
+
"retail",
|
|
16469
|
+
"commerce"
|
|
16470
|
+
],
|
|
16471
|
+
domains: ["commerce"],
|
|
16472
|
+
tone: ["practical", "premium"],
|
|
16473
|
+
presets: featurePreset
|
|
16474
|
+
},
|
|
16475
|
+
{
|
|
16476
|
+
id: "packages",
|
|
16477
|
+
label: "Packages",
|
|
16478
|
+
tags: [
|
|
16479
|
+
"package",
|
|
16480
|
+
"bundle",
|
|
16481
|
+
"delivery",
|
|
16482
|
+
"offer",
|
|
16483
|
+
"product"
|
|
16484
|
+
],
|
|
16485
|
+
domains: ["commerce", "services"],
|
|
16486
|
+
tone: ["practical"],
|
|
16487
|
+
presets: featurePreset
|
|
16488
|
+
},
|
|
16489
|
+
{
|
|
16490
|
+
id: "time",
|
|
16491
|
+
label: "Time",
|
|
16492
|
+
tags: [
|
|
16493
|
+
"time",
|
|
16494
|
+
"duration",
|
|
16495
|
+
"schedule",
|
|
16496
|
+
"availability",
|
|
16497
|
+
"appointment"
|
|
16498
|
+
],
|
|
16499
|
+
domains: [
|
|
16500
|
+
"events",
|
|
16501
|
+
"services",
|
|
16502
|
+
"wellbeing"
|
|
16503
|
+
],
|
|
16504
|
+
tone: ["practical", "calm"],
|
|
16505
|
+
presets: featurePreset
|
|
16506
|
+
},
|
|
16507
|
+
{
|
|
16508
|
+
id: "practical-service",
|
|
16509
|
+
label: "Practical service",
|
|
16510
|
+
tags: [
|
|
16511
|
+
"service",
|
|
16512
|
+
"repair",
|
|
16513
|
+
"setup",
|
|
16514
|
+
"practical",
|
|
16515
|
+
"tools",
|
|
16516
|
+
"support"
|
|
16517
|
+
],
|
|
16518
|
+
domains: ["services", "technology"],
|
|
16519
|
+
tone: ["practical"],
|
|
16520
|
+
presets: featurePreset
|
|
16521
|
+
},
|
|
16522
|
+
{
|
|
16523
|
+
id: "at-home",
|
|
16524
|
+
label: "At home",
|
|
16525
|
+
tags: [
|
|
16526
|
+
"home",
|
|
16527
|
+
"domestic",
|
|
16528
|
+
"comfort",
|
|
16529
|
+
"local",
|
|
16530
|
+
"space"
|
|
16531
|
+
],
|
|
16532
|
+
domains: [
|
|
16533
|
+
"hospitality",
|
|
16534
|
+
"services",
|
|
16535
|
+
"community"
|
|
16536
|
+
],
|
|
16537
|
+
tone: ["warm", "calm"],
|
|
16538
|
+
presets: featurePreset
|
|
16539
|
+
},
|
|
16540
|
+
{
|
|
16541
|
+
id: "worldwide",
|
|
16542
|
+
label: "Worldwide",
|
|
16543
|
+
tags: [
|
|
16544
|
+
"global",
|
|
16545
|
+
"online",
|
|
16546
|
+
"worldwide",
|
|
16547
|
+
"remote",
|
|
16548
|
+
"international"
|
|
16549
|
+
],
|
|
16550
|
+
domains: [
|
|
16551
|
+
"technology",
|
|
16552
|
+
"education",
|
|
16553
|
+
"services"
|
|
16554
|
+
],
|
|
16555
|
+
tone: ["practical"],
|
|
16556
|
+
presets: featurePreset
|
|
16557
|
+
},
|
|
16558
|
+
{
|
|
16559
|
+
id: "professional-service",
|
|
16560
|
+
label: "Professional service",
|
|
16561
|
+
tags: [
|
|
16562
|
+
"business",
|
|
16563
|
+
"professional",
|
|
16564
|
+
"consulting",
|
|
16565
|
+
"service",
|
|
16566
|
+
"work"
|
|
16567
|
+
],
|
|
16568
|
+
domains: [
|
|
16569
|
+
"services",
|
|
16570
|
+
"technology",
|
|
16571
|
+
"coaching"
|
|
16572
|
+
],
|
|
16573
|
+
tone: ["practical", "trustworthy"],
|
|
16574
|
+
presets: featurePreset
|
|
16575
|
+
}
|
|
16576
|
+
].map(({ id, label }) => ({
|
|
16577
|
+
id,
|
|
16578
|
+
label
|
|
16579
|
+
}));
|
|
16580
|
+
function isSemanticIconId(value) {
|
|
16581
|
+
return typeof value === "string" && SEMANTIC_ICON_IDS.includes(value);
|
|
16582
|
+
}
|
|
16583
|
+
//#endregion
|
|
16584
|
+
//#region ../blocks/src/system/icons/value.ts
|
|
16585
|
+
const NO_BLOCK_ICON_VALUE = { kind: "none" };
|
|
16586
|
+
function isRecord$11(value) {
|
|
16587
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16588
|
+
}
|
|
16589
|
+
function parseBlockIconValue(value) {
|
|
16590
|
+
if (isSemanticIconId(value)) return {
|
|
16591
|
+
kind: "semantic",
|
|
16592
|
+
iconId: value
|
|
16593
|
+
};
|
|
16594
|
+
if (!isRecord$11(value)) return NO_BLOCK_ICON_VALUE;
|
|
16595
|
+
switch (value.kind) {
|
|
16596
|
+
case "none": return NO_BLOCK_ICON_VALUE;
|
|
16597
|
+
case "semantic": return isSemanticIconId(value.iconId) ? {
|
|
16598
|
+
kind: "semantic",
|
|
16599
|
+
iconId: value.iconId
|
|
16600
|
+
} : NO_BLOCK_ICON_VALUE;
|
|
16601
|
+
case "generated": {
|
|
16602
|
+
const setId = parseGeneratedIconSetId(value.setId);
|
|
16603
|
+
const assetId = parseGeneratedIconAssetId(value.assetId);
|
|
16604
|
+
const styleGuideVersionId = parseSiteIconStyleGuideVersionId(value.styleGuideVersionId);
|
|
16605
|
+
if (setId !== null && assetId !== null && styleGuideVersionId !== null) return {
|
|
16606
|
+
kind: "generated",
|
|
16607
|
+
setId,
|
|
16608
|
+
assetId,
|
|
16609
|
+
styleGuideVersionId
|
|
16610
|
+
};
|
|
16611
|
+
return NO_BLOCK_ICON_VALUE;
|
|
16612
|
+
}
|
|
16613
|
+
default: return NO_BLOCK_ICON_VALUE;
|
|
16614
|
+
}
|
|
16615
|
+
}
|
|
16616
|
+
//#endregion
|
|
16617
|
+
//#region ../blocks/src/lib/typeGuards.ts
|
|
16618
|
+
/**
|
|
16619
|
+
* Strict record guard: excludes null, primitives, and arrays.
|
|
16620
|
+
*/
|
|
16621
|
+
function isRecord$10(value) {
|
|
16622
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16623
|
+
}
|
|
16624
|
+
/**
|
|
16625
|
+
* Non-null object guard: includes arrays for behavior parity with legacy helpers.
|
|
16626
|
+
*
|
|
16627
|
+
* NOTE: This intentionally narrows to UnknownRecord for compatibility with existing
|
|
16628
|
+
* callsites even though arrays pass at runtime. Follow-up cleanup should replace
|
|
16629
|
+
* this API with a more precise predicate type and migrate consumers.
|
|
16630
|
+
*/
|
|
16631
|
+
function isObjectRecord$1(value) {
|
|
16632
|
+
return typeof value === "object" && value !== null;
|
|
16633
|
+
}
|
|
16634
|
+
//#endregion
|
|
16635
|
+
//#region ../blocks/src/system/manifest/richTextSchema.ts
|
|
16636
|
+
/**
|
|
16637
|
+
* Shared Rich Text Schema
|
|
16638
|
+
*
|
|
16639
|
+
* This module provides a single source of truth for TipTap rich text validation
|
|
16640
|
+
* across both the block-form editor and the block rendering system.
|
|
16641
|
+
*
|
|
16642
|
+
* Rich-text fields use one canonical root shape:
|
|
16643
|
+
* `{ type: 'doc', content: [...] }`.
|
|
16644
|
+
*/
|
|
16645
|
+
/**
|
|
16646
|
+
* TipTap document node schema (recursive structure)
|
|
16647
|
+
*
|
|
16648
|
+
* Supports the full TipTap document structure including:
|
|
16649
|
+
* - type: Node type (e.g., 'doc', 'paragraph', 'text')
|
|
16650
|
+
* - content: Nested array of child nodes
|
|
16651
|
+
* - text: Text content for text nodes
|
|
16652
|
+
* - attrs: Node attributes (e.g., alignment, color)
|
|
16653
|
+
* - marks: Text formatting marks (e.g., bold, italic)
|
|
16654
|
+
*/
|
|
16655
|
+
const TipTapMarkSchema = z.object({
|
|
16656
|
+
type: z.string().min(1),
|
|
16657
|
+
attrs: z.record(z.string(), z.unknown()).optional()
|
|
16658
|
+
}).strict();
|
|
16659
|
+
const TipTapNodeSchema = z.lazy(() => z.object({
|
|
16660
|
+
type: z.string().min(1),
|
|
16661
|
+
content: z.array(TipTapNodeSchema).optional(),
|
|
16662
|
+
text: z.string().optional(),
|
|
16663
|
+
attrs: z.record(z.string(), z.unknown()).optional(),
|
|
16664
|
+
marks: z.array(TipTapMarkSchema).optional()
|
|
16665
|
+
}).strict().superRefine((node, ctx) => {
|
|
16666
|
+
if (node.type === "doc") ctx.addIssue({
|
|
16667
|
+
code: "custom",
|
|
16668
|
+
path: ["type"],
|
|
16669
|
+
message: "Document nodes are only valid at the rich-text root"
|
|
16670
|
+
});
|
|
16671
|
+
if (node.type === "text") {
|
|
16672
|
+
if (node.text === void 0 || node.text.length === 0) ctx.addIssue({
|
|
16673
|
+
code: "custom",
|
|
16674
|
+
path: ["text"],
|
|
16675
|
+
message: "Text nodes require a non-empty text value"
|
|
16676
|
+
});
|
|
16677
|
+
if (node.content !== void 0) ctx.addIssue({
|
|
16678
|
+
code: "custom",
|
|
16679
|
+
path: ["content"],
|
|
16680
|
+
message: "Text nodes cannot contain child nodes"
|
|
16681
|
+
});
|
|
16682
|
+
return;
|
|
16683
|
+
}
|
|
16684
|
+
if (node.text !== void 0) ctx.addIssue({
|
|
16685
|
+
code: "custom",
|
|
16686
|
+
path: ["text"],
|
|
16687
|
+
message: "Only text nodes can contain a text value"
|
|
16688
|
+
});
|
|
16689
|
+
}));
|
|
16690
|
+
/**
|
|
16691
|
+
* Canonical schema for a TipTap rich-text document root.
|
|
16692
|
+
*
|
|
16693
|
+
* Stricter than {@link TipTapNodeSchema}: `type` is literally `'doc'` and
|
|
16694
|
+
* `content` is required (possibly empty). This is the shape every producer
|
|
16695
|
+
* (dummy content, editor output, migrations) must emit, and the shape every
|
|
16696
|
+
* non-legacy consumer can rely on.
|
|
16697
|
+
*
|
|
16698
|
+
*/
|
|
16699
|
+
const RichTextDocSchema = z.object({
|
|
16700
|
+
type: z.literal("doc"),
|
|
16701
|
+
content: z.array(TipTapNodeSchema)
|
|
16702
|
+
}).strict();
|
|
16703
|
+
/**
|
|
16704
|
+
* Type guard for {@link RichTextDoc}.
|
|
16705
|
+
*
|
|
16706
|
+
* Returns `true` only for the canonical unwrapped form. The shared structural
|
|
16707
|
+
* contract lives in `@riverbankcms/core`; parity tests keep its dependency-free
|
|
16708
|
+
* guard aligned with this detailed Zod validator.
|
|
16709
|
+
*/
|
|
16710
|
+
function isRichTextDoc(value) {
|
|
16711
|
+
return RichTextDocSchema.safeParse(value).success;
|
|
16712
|
+
}
|
|
16713
|
+
//#endregion
|
|
16714
|
+
//#region ../blocks/src/lib/media.ts
|
|
16715
|
+
const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
|
|
16716
|
+
"document",
|
|
16717
|
+
"spreadsheet",
|
|
16718
|
+
"archive",
|
|
16719
|
+
"audio"
|
|
16720
|
+
];
|
|
16721
|
+
//#endregion
|
|
16722
|
+
//#region ../blocks/src/system/manifest/fieldValidation/writeCanonicalization.ts
|
|
16723
|
+
function allGroupChildPlans(plan) {
|
|
16724
|
+
return plan.childSelection.kind === "all" ? plan.childSelection.fields : plan.childSelection.tabs.flatMap((tab) => tab.fields);
|
|
16725
|
+
}
|
|
16726
|
+
function selectedGroupChildPlans(plan, value) {
|
|
16727
|
+
if (plan.childSelection.kind === "all") return plan.childSelection.fields;
|
|
16728
|
+
if (!isPlainObject$3(value)) return [];
|
|
16729
|
+
const selectedType = value[plan.childSelection.activeTabField];
|
|
16730
|
+
return plan.childSelection.tabs.find((tab) => tab.typeId === selectedType)?.fields ?? [];
|
|
16731
|
+
}
|
|
16732
|
+
function canonicalizeObjectForWrite(plans, value) {
|
|
16733
|
+
if (!isPlainObject$3(value)) return value;
|
|
16734
|
+
const canonical = { ...value };
|
|
16735
|
+
for (const plan of plans) {
|
|
16736
|
+
if (!(plan.fieldId in canonical)) continue;
|
|
16737
|
+
canonical[plan.fieldId] = canonicalizeFieldValue(plan, canonical[plan.fieldId]);
|
|
16738
|
+
}
|
|
16739
|
+
return omitUndefined(canonical);
|
|
16740
|
+
}
|
|
16741
|
+
function canonicalizeFieldValue(plan, value) {
|
|
16742
|
+
switch (plan.kind) {
|
|
16743
|
+
case "media": return canonicalizeMedia(value);
|
|
16744
|
+
case "group": return plan.childSelection.kind === "discriminatedTabs" ? canonicalizeDiscriminatedGroup(plan, value) : canonicalizeObjectForWrite(plan.childSelection.fields, value);
|
|
16745
|
+
case "repeater": return canonicalizeRepeater(plan, value);
|
|
16746
|
+
case "string":
|
|
16747
|
+
case "number":
|
|
16748
|
+
case "boolean":
|
|
16749
|
+
case "richText":
|
|
16750
|
+
case "inlineText":
|
|
16751
|
+
case "link":
|
|
16752
|
+
case "select":
|
|
16753
|
+
case "passthrough": return value;
|
|
16754
|
+
}
|
|
16755
|
+
}
|
|
16756
|
+
function canonicalizeMedia(value) {
|
|
16757
|
+
if (!isPlainObject$3(value)) return value;
|
|
16758
|
+
const canonical = { ...value };
|
|
16759
|
+
if (mediaIdentifierSchema.safeParse(canonical.identifier).success) deleteEnvSpecificKeys(canonical);
|
|
16760
|
+
return canonical;
|
|
16761
|
+
}
|
|
16762
|
+
function canonicalizeRepeater(plan, value) {
|
|
16763
|
+
if (!isUnknownArray$1(value)) return value;
|
|
16764
|
+
return value.map((item) => {
|
|
16765
|
+
if (!isPlainObject$3(item)) return item;
|
|
16766
|
+
const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
|
|
16767
|
+
return childPlans ? canonicalizeObjectForWrite(childPlans, item) : item;
|
|
16768
|
+
});
|
|
16769
|
+
}
|
|
16770
|
+
function canonicalizeDiscriminatedGroup(plan, value) {
|
|
16771
|
+
if (!isPlainObject$3(value) || plan.childSelection.kind !== "discriminatedTabs") return value;
|
|
16772
|
+
const selection = plan.childSelection;
|
|
16773
|
+
const selectedPlans = selectedGroupChildPlans(plan, value);
|
|
16774
|
+
const selectedIds = rootFieldIds(selectedPlans);
|
|
16775
|
+
const allChildIds = rootFieldIds(allGroupChildPlans(plan));
|
|
16776
|
+
const canonical = omitUndefined(canonicalizeObjectForWrite(selectedPlans, Object.fromEntries(Object.entries(value).filter(([key]) => key === selection.activeTabField || selectedIds.has(key) || !allChildIds.has(key)))));
|
|
16777
|
+
if (plan.valueContract !== "boxBackground") return canonical;
|
|
16778
|
+
const parsed = boxBackgroundSchema.safeParse(canonical);
|
|
16779
|
+
return parsed.success ? parsed.data : canonical;
|
|
16780
|
+
}
|
|
16781
|
+
function rootFieldIds(plans) {
|
|
16782
|
+
return new Set(plans.map((child) => child.fieldId.split(".")[0] ?? child.fieldId));
|
|
16783
|
+
}
|
|
16784
|
+
function omitUndefined(value) {
|
|
16785
|
+
if (isUnknownArray$1(value)) return value.map(omitUndefined);
|
|
16786
|
+
if (!isPlainObject$3(value)) return value;
|
|
16787
|
+
return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== void 0).map(([key, field]) => [key, omitUndefined(field)]));
|
|
16788
|
+
}
|
|
16789
|
+
function isPlainObject$3(value) {
|
|
16790
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16791
|
+
}
|
|
16792
|
+
function isUnknownArray$1(value) {
|
|
16793
|
+
return Array.isArray(value);
|
|
16794
|
+
}
|
|
16795
|
+
//#endregion
|
|
16796
|
+
//#region ../blocks/src/system/manifest/fieldValidation/index.ts
|
|
16797
|
+
const TEL_RE = /^[+()0-9\s-]{3,}$/;
|
|
16798
|
+
const SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
|
|
16799
|
+
const ALLOWED_URL_PROTOCOLS = ["http:", "https:"];
|
|
16800
|
+
const DATE_PATTERN = /^(?<year>[1-9]\d{3})-(?<month>\d{2})-(?<day>\d{2})$/;
|
|
16801
|
+
const TIME_PATTERN = /^(?<hours>[01]\d|2[0-3]):(?<minutes>[0-5]\d)$/;
|
|
16802
|
+
const DATETIME_PATTERN = /^(?<date>[1-9]\d{3}-\d{2}-\d{2})T(?<time>(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d)(?:\.\d+)?(?<offset>Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
|
|
16803
|
+
function assertNever$1(value) {
|
|
16804
|
+
throw new Error(`Unhandled field validation variant: ${JSON.stringify(value)}`);
|
|
16805
|
+
}
|
|
16806
|
+
function validationContext(options = {}) {
|
|
16807
|
+
const isDraft = options.mode === "draft";
|
|
16808
|
+
return {
|
|
16809
|
+
allowNull: options.allowNull ?? true,
|
|
16810
|
+
allowIncomplete: isDraft || (options.allowIncomplete ?? false)
|
|
16811
|
+
};
|
|
16812
|
+
}
|
|
16813
|
+
function strictValidationContext(options = {}) {
|
|
16814
|
+
return {
|
|
16815
|
+
...validationContext(options),
|
|
16816
|
+
allowNull: options.allowNull ?? false
|
|
16817
|
+
};
|
|
16818
|
+
}
|
|
16819
|
+
function formatFieldPath(path) {
|
|
16820
|
+
return path.map((segment) => String(segment)).join(".");
|
|
16821
|
+
}
|
|
16822
|
+
function toZodIssuePath(path) {
|
|
16823
|
+
return [...path];
|
|
16824
|
+
}
|
|
16825
|
+
function parseFieldPathKey(key) {
|
|
16826
|
+
if (!key) return [];
|
|
16827
|
+
return key.split(".").map((segment) => {
|
|
16828
|
+
const numeric = Number(segment);
|
|
16829
|
+
return Number.isInteger(numeric) && String(numeric) === segment ? numeric : segment;
|
|
16830
|
+
});
|
|
16831
|
+
}
|
|
16832
|
+
function fieldIssueToMessage(issue) {
|
|
16833
|
+
switch (issue.kind) {
|
|
16834
|
+
case "required": return "This field is required";
|
|
16835
|
+
case "wrongType": return `${issue.label} needs ${issue.expected}`;
|
|
16836
|
+
case "tooLong": return `Use ${issue.maximum} characters or fewer`;
|
|
16837
|
+
case "invalidEmail": return "Enter a valid email address";
|
|
16838
|
+
case "invalidPhone": return "Enter a valid phone number";
|
|
16839
|
+
case "invalidPattern": return "Check the format and try again";
|
|
16840
|
+
case "invalidUrl": return "Enter a valid web address";
|
|
16841
|
+
case "invalidDate": return "Choose a valid date";
|
|
16842
|
+
case "invalidTime": return "Choose a valid time";
|
|
16843
|
+
case "invalidDateTime": return "Choose a valid date and time";
|
|
16844
|
+
case "invalidNumber": return `${issue.label} needs a number`;
|
|
16845
|
+
case "tooSmall": return `${issue.label} must be ${issue.minimum} or more`;
|
|
16846
|
+
case "tooLarge": return `${issue.label} must be ${issue.maximum} or less`;
|
|
16847
|
+
case "invalidSlug": return `${issue.label} can only use lowercase letters, numbers, and dashes`;
|
|
16848
|
+
case "invalidOption": return `Choose one of the available options for ${issue.label}`;
|
|
16849
|
+
case "tooFewItems": return `${issue.label} must have at least ${issue.minimum} ${pluralize(issue.itemLabel, issue.minimum)}`;
|
|
16850
|
+
case "tooManyItems": return `${issue.label} must have at most ${issue.maximum} ${pluralize(issue.itemLabel, issue.maximum)}`;
|
|
16851
|
+
case "invalidRichText": return `${issue.label} must be valid rich text`;
|
|
16852
|
+
case "invalidInlineText": return `${issue.label} must be valid styled text`;
|
|
16853
|
+
case "invalidMedia": return `${issue.label} must be a media object with an identifier`;
|
|
16854
|
+
case "invalidBoxBackground": return `${issue.label} must use a valid background type and matching fields`;
|
|
16855
|
+
case "invalidLink": return `${issue.label} must be a valid link`;
|
|
16856
|
+
case "invalidReference": return `${issue.label} must reference a valid item`;
|
|
16857
|
+
default: return assertNever$1(issue);
|
|
16858
|
+
}
|
|
16859
|
+
}
|
|
16860
|
+
function pluralize(label, count) {
|
|
16861
|
+
if (count === 1) return label;
|
|
16862
|
+
return label.endsWith("s") ? label : `${label}s`;
|
|
16863
|
+
}
|
|
16864
|
+
function valueContractForField(field) {
|
|
16865
|
+
return field.ui?.valueContract === "boxBackground" ? { valueContract: "boxBackground" } : {};
|
|
16866
|
+
}
|
|
16867
|
+
function deriveTabGroupValidationPlan(field, path, required) {
|
|
16868
|
+
return {
|
|
16869
|
+
...makePlan("group", "object", field, path, required, requiredConstraints(required)),
|
|
16870
|
+
...valueContractForField(field),
|
|
16871
|
+
childSelection: field.activeTabField ? {
|
|
16872
|
+
kind: "discriminatedTabs",
|
|
16873
|
+
activeTabField: field.activeTabField,
|
|
16874
|
+
tabs: field.tabs.map((tab) => ({
|
|
16875
|
+
typeId: tab.id,
|
|
16876
|
+
fields: deriveNestedFieldPlans(tab.fields, path)
|
|
16877
|
+
}))
|
|
16878
|
+
} : {
|
|
16879
|
+
kind: "all",
|
|
16880
|
+
fields: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path))
|
|
16881
|
+
}
|
|
16882
|
+
};
|
|
16883
|
+
}
|
|
16884
|
+
function deriveFieldValidationPlan(field, path = [field.id]) {
|
|
16885
|
+
const required = Boolean(field.required);
|
|
16886
|
+
switch (field.type) {
|
|
16887
|
+
case "text": {
|
|
16888
|
+
const inputType = field.ui?.inputType;
|
|
16889
|
+
if (inputType === "number") {
|
|
16890
|
+
const constraints = commonConstraints(required, { kind: "numberType" });
|
|
16891
|
+
if (typeof field.ui?.min === "number") constraints.push({
|
|
16892
|
+
kind: "numberMin",
|
|
16893
|
+
minimum: field.ui.min
|
|
16894
|
+
});
|
|
16895
|
+
if (typeof field.ui?.max === "number") constraints.push({
|
|
16896
|
+
kind: "numberMax",
|
|
16897
|
+
maximum: field.ui.max
|
|
16898
|
+
});
|
|
16899
|
+
return makePlan("number", "number", field, path, required, constraints);
|
|
16900
|
+
}
|
|
16901
|
+
const constraints = commonConstraints(required, { kind: field.ui?.widget === "iconPicker" ? "blockIconValue" : "textType" });
|
|
16902
|
+
if (inputType === "email") constraints.push({ kind: "emailFormat" });
|
|
16903
|
+
if (inputType === "tel") constraints.push({ kind: "phoneFormat" });
|
|
16904
|
+
if (field.ui?.pattern) constraints.push({
|
|
16905
|
+
kind: "patternFormat",
|
|
16906
|
+
pattern: field.ui.pattern
|
|
16907
|
+
});
|
|
16908
|
+
if (typeof field.maxLength === "number") constraints.push({
|
|
16909
|
+
kind: "maxLength",
|
|
16910
|
+
maximum: field.maxLength
|
|
16911
|
+
});
|
|
16912
|
+
return makePlan("string", "string", field, path, required, constraints);
|
|
16913
|
+
}
|
|
16914
|
+
case "number": {
|
|
16915
|
+
const constraints = commonConstraints(required, { kind: "numberType" });
|
|
16916
|
+
if (typeof field.min === "number") constraints.push({
|
|
16917
|
+
kind: "numberMin",
|
|
16918
|
+
minimum: field.min
|
|
16919
|
+
});
|
|
16920
|
+
if (typeof field.max === "number") constraints.push({
|
|
16921
|
+
kind: "numberMax",
|
|
16922
|
+
maximum: field.max
|
|
16923
|
+
});
|
|
16924
|
+
return makePlan("number", "number", field, path, required, constraints);
|
|
16925
|
+
}
|
|
16926
|
+
case "slug": {
|
|
16927
|
+
const constraints = commonConstraints(required, { kind: "textType" }, { kind: "slugFormat" });
|
|
16928
|
+
if (typeof field.maxLength === "number") constraints.push({
|
|
16929
|
+
kind: "maxLength",
|
|
16930
|
+
maximum: field.maxLength
|
|
16931
|
+
});
|
|
16932
|
+
return makePlan("string", "string", field, path, required, constraints);
|
|
16933
|
+
}
|
|
16934
|
+
case "url": return makePlan("string", "string", field, path, required, commonConstraints(required, { kind: "textType" }, {
|
|
16935
|
+
kind: "urlFormat",
|
|
16936
|
+
allowRelative: Boolean(field.allowRelative)
|
|
16937
|
+
}));
|
|
16938
|
+
case "reference": return makePlan("string", "string", field, path, required, commonConstraints(required, { kind: "referenceText" }));
|
|
16939
|
+
case "date": return makePlan("string", "string", field, path, required, commonConstraints(required, { kind: "textType" }, { kind: "dateFormat" }));
|
|
16940
|
+
case "time": return makePlan("string", "string", field, path, required, commonConstraints(required, { kind: "textType" }, { kind: "timeFormat" }));
|
|
16941
|
+
case "datetime": return makePlan("string", "string", field, path, required, commonConstraints(required, { kind: "textType" }, { kind: "datetimeFormat" }));
|
|
16942
|
+
case "select": return makePlan("select", "select", field, path, required, commonConstraints(required, {
|
|
16943
|
+
kind: "selectOption",
|
|
16944
|
+
source: resolveSelectConstraintSource(field),
|
|
16945
|
+
multiple: Boolean(field.multiple)
|
|
16946
|
+
}));
|
|
16947
|
+
case "richText": return makePlan("richText", "object", field, path, required, commonConstraints(required, { kind: "richTextDoc" }));
|
|
16948
|
+
case "inlineText": {
|
|
16949
|
+
const constraints = commonConstraints(required, { kind: "inlineText" });
|
|
16950
|
+
if (typeof field.maxLength === "number") constraints.push({
|
|
16951
|
+
kind: "maxPlainTextLength",
|
|
16952
|
+
maximum: field.maxLength
|
|
16953
|
+
});
|
|
16954
|
+
return {
|
|
16955
|
+
...makePlan("inlineText", "array", field, path, required, constraints),
|
|
16956
|
+
...field.plainTextField ? { plainTextFallbackPath: parseFieldPathKey(field.plainTextField) } : {}
|
|
16957
|
+
};
|
|
16958
|
+
}
|
|
16959
|
+
case "media":
|
|
16960
|
+
case "file": return {
|
|
16961
|
+
...makePlan("media", "object", field, path, required, commonConstraints(required, { kind: "mediaObject" })),
|
|
16962
|
+
allowedMediaTypes: field.type === "media" ? field.mediaKinds ?? DEFAULT_MEDIA_FIELD_KINDS : field.fileKinds ?? PUBLIC_FILE_FIELD_KINDS
|
|
16963
|
+
};
|
|
16964
|
+
case "link": return makePlan("link", "object", field, path, required, commonConstraints(required, { kind: "linkObject" }));
|
|
16965
|
+
case "boolean": return makePlan("boolean", "boolean", field, path, required, requiredConstraints(required));
|
|
16966
|
+
case "repeater": return {
|
|
16967
|
+
...makePlan("repeater", "array", field, path, required, commonConstraints(required, { kind: "arrayType" })),
|
|
16968
|
+
...field.polymorphic && field.itemTypes ? { repeatedItemVariants: deriveRepeatedItemVariants(field, [...path, 0]) } : { repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path, 0]) },
|
|
16969
|
+
constraints: withRepeaterItemConstraints(field, commonConstraints(required, { kind: "arrayType" }))
|
|
16970
|
+
};
|
|
16971
|
+
case "group":
|
|
16972
|
+
case "modal": return {
|
|
16973
|
+
...makePlan("group", "object", field, path, required, requiredConstraints(required)),
|
|
16974
|
+
childSelection: {
|
|
16975
|
+
kind: "all",
|
|
16976
|
+
fields: deriveNestedFieldPlans(field.schema?.fields ?? [], path)
|
|
16977
|
+
},
|
|
16978
|
+
allowNullChildren: field.type === "group" && field.ui?.widget === "locationPicker"
|
|
16979
|
+
};
|
|
16980
|
+
case "tabGroup": return deriveTabGroupValidationPlan(field, path, required);
|
|
16981
|
+
case "presetOrCustom":
|
|
16982
|
+
case "contentTypeSelect":
|
|
16983
|
+
case "entryPicker": return makePlan("passthrough", "unknown", field, path, false, []);
|
|
16984
|
+
default: return assertNever$1(field);
|
|
16985
|
+
}
|
|
16986
|
+
}
|
|
16987
|
+
function deriveFieldValidationPlans(fields, parentPath = []) {
|
|
16988
|
+
return fields.map((field) => deriveFieldValidationPlan(field, [...parentPath, field.id]));
|
|
16989
|
+
}
|
|
16990
|
+
function commonConstraints(required, ...specific) {
|
|
16991
|
+
return required ? [{ kind: "required" }, ...specific] : [...specific];
|
|
16992
|
+
}
|
|
16993
|
+
function requiredConstraints(required) {
|
|
16994
|
+
return required ? [{ kind: "required" }] : [];
|
|
16995
|
+
}
|
|
16996
|
+
function makePlan(kind, valueKind, field, path, required, constraints) {
|
|
16997
|
+
return {
|
|
16998
|
+
kind,
|
|
16999
|
+
valueKind,
|
|
17000
|
+
fieldId: field.id,
|
|
17001
|
+
label: field.label,
|
|
17002
|
+
fieldType: field.type,
|
|
17003
|
+
path,
|
|
17004
|
+
required,
|
|
17005
|
+
visibility: fieldVisibility(field),
|
|
17006
|
+
constraints
|
|
17007
|
+
};
|
|
17008
|
+
}
|
|
17009
|
+
function fieldVisibility(field) {
|
|
17010
|
+
if (field.ui?.hidden) return { kind: "hidden" };
|
|
17011
|
+
if (field.visibleRoles && field.visibleRoles.length > 0) return {
|
|
17012
|
+
kind: "roleRestricted",
|
|
17013
|
+
roles: field.visibleRoles
|
|
17014
|
+
};
|
|
17015
|
+
return { kind: "visible" };
|
|
17016
|
+
}
|
|
17017
|
+
function withRepeaterItemConstraints(field, constraints) {
|
|
17018
|
+
const next = [...constraints];
|
|
17019
|
+
if (typeof field.minItems === "number") next.push({
|
|
17020
|
+
kind: "minItems",
|
|
17021
|
+
minimum: field.minItems
|
|
17022
|
+
});
|
|
17023
|
+
if (typeof field.maxItems === "number") next.push({
|
|
17024
|
+
kind: "maxItems",
|
|
17025
|
+
maximum: field.maxItems
|
|
17026
|
+
});
|
|
17027
|
+
return next;
|
|
17028
|
+
}
|
|
17029
|
+
function deriveRepeatedItemVariants(field, parentPath) {
|
|
17030
|
+
return Object.entries(field.itemTypes ?? {}).map(([typeId, itemType]) => ({
|
|
17031
|
+
typeId,
|
|
17032
|
+
fields: deriveNestedFieldPlans(getFlattenedRepeaterFields(itemType.fields), parentPath)
|
|
17033
|
+
}));
|
|
17034
|
+
}
|
|
17035
|
+
function deriveNestedFieldPlans(fields, parentPath) {
|
|
17036
|
+
return deriveFieldValidationPlans(fields, parentPath);
|
|
17037
|
+
}
|
|
17038
|
+
function getRepeaterFields(field) {
|
|
17039
|
+
return getFlattenedRepeaterFields(field.polymorphic && field.itemTypes ? Object.values(field.itemTypes).flatMap((itemType) => itemType.fields) : field.schema?.fields ?? []);
|
|
17040
|
+
}
|
|
17041
|
+
function getFlattenedRepeaterFields(fields) {
|
|
17042
|
+
return fields.flatMap((child) => {
|
|
17043
|
+
if (child.type === "group" && child.ui?.flattenInRepeater) return child.schema?.fields ?? [];
|
|
17044
|
+
return child;
|
|
17045
|
+
});
|
|
17046
|
+
}
|
|
17047
|
+
function resolveSelectConstraintSource(field) {
|
|
17048
|
+
const source = normalizeSelectSource(field);
|
|
17049
|
+
switch (source.kind) {
|
|
17050
|
+
case "static": return {
|
|
17051
|
+
kind: "static",
|
|
17052
|
+
values: field.options.map((option) => option.value)
|
|
17053
|
+
};
|
|
17054
|
+
case "site":
|
|
17055
|
+
case "sdk": return {
|
|
17056
|
+
kind: "runtime",
|
|
17057
|
+
source: source.kind
|
|
17058
|
+
};
|
|
17059
|
+
default: return assertNever$1(source);
|
|
17060
|
+
}
|
|
17061
|
+
}
|
|
17062
|
+
function normalizeStoredContentValues(plans, content, options = {}) {
|
|
17063
|
+
if (!content || typeof content !== "object" || Array.isArray(content)) return {};
|
|
17064
|
+
const planMap = new Map(plans.map((plan) => [plan.fieldId, plan]));
|
|
17065
|
+
const normalized = {};
|
|
17066
|
+
const ctx = validationContext(options);
|
|
17067
|
+
for (const [key, value] of Object.entries(content)) {
|
|
17068
|
+
const plan = planMap.get(key);
|
|
17069
|
+
normalized[key] = plan ? normalizeStoredFieldValueWithContext(plan, value, ctx) : value;
|
|
17070
|
+
}
|
|
17071
|
+
normalizeInlineTextFallbacks(plans, normalized, ctx);
|
|
17072
|
+
return normalized;
|
|
17073
|
+
}
|
|
17074
|
+
/**
|
|
17075
|
+
* Produces the portable representation accepted by content persistence.
|
|
17076
|
+
* Runtime-hydrated media fields are stripped only when a canonical identifier
|
|
17077
|
+
* is already present; unresolved environment-specific references remain
|
|
17078
|
+
* invalid and must be handled by the site-scoped media write normalizer first.
|
|
17079
|
+
*/
|
|
17080
|
+
function normalizeManifestContentForWrite(plans, content, options = {}) {
|
|
17081
|
+
return canonicalizeObjectForWrite(plans, normalizeStoredContentValues(plans, content, options));
|
|
17082
|
+
}
|
|
17083
|
+
function normalizeStoredFieldValueWithContext(plan, value, ctx) {
|
|
17084
|
+
if (value === null && !plan.required) return;
|
|
17085
|
+
switch (plan.kind) {
|
|
17086
|
+
case "group": return normalizeStoredObjectChildren(selectedGroupChildPlans(plan, value), value, childValidationContext(plan, ctx));
|
|
17087
|
+
case "repeater": return normalizeStoredRepeaterItems(plan, value, ctx);
|
|
17088
|
+
case "string":
|
|
17089
|
+
case "number":
|
|
17090
|
+
case "boolean":
|
|
17091
|
+
case "richText":
|
|
17092
|
+
case "inlineText":
|
|
17093
|
+
case "media":
|
|
17094
|
+
case "link":
|
|
17095
|
+
case "select":
|
|
17096
|
+
case "passthrough": return normalizeFieldValue(plan, value, ctx);
|
|
17097
|
+
default: return assertNever$1(plan);
|
|
17098
|
+
}
|
|
17099
|
+
}
|
|
17100
|
+
function normalizeStoredObjectChildren(children, value, ctx) {
|
|
17101
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
17102
|
+
const normalized = { ...value };
|
|
17103
|
+
for (const child of children) normalized[child.fieldId] = normalizeStoredFieldValueWithContext(child, normalized[child.fieldId], ctx);
|
|
17104
|
+
normalizeInlineTextFallbacks(children, normalized, ctx);
|
|
17105
|
+
return normalized;
|
|
17106
|
+
}
|
|
17107
|
+
function normalizeStoredRepeaterItems(plan, value, ctx) {
|
|
17108
|
+
if (!isUnknownArray(value)) return value;
|
|
17109
|
+
return value.map((item) => {
|
|
17110
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return item;
|
|
17111
|
+
const itemRecord = item;
|
|
17112
|
+
const fields = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemRecord._type)?.fields : plan.repeatedItemPlan;
|
|
17113
|
+
if (!fields) return item;
|
|
17114
|
+
return normalizeStoredObjectChildren(fields, itemRecord, ctx);
|
|
17115
|
+
});
|
|
17116
|
+
}
|
|
17117
|
+
function normalizeFieldValue(plan, value, ctx) {
|
|
17118
|
+
switch (plan.kind) {
|
|
17119
|
+
case "number": return normalizeNumberInput(value, ctx.allowNull);
|
|
17120
|
+
case "string": return acceptsOptionalBlankAsMissing(plan, value) ? void 0 : value;
|
|
17121
|
+
case "group": return normalizeObjectChildren(selectedGroupChildPlans(plan, value), value, childValidationContext(plan, ctx));
|
|
17122
|
+
case "repeater": return normalizeRepeaterItems(plan, value, ctx);
|
|
17123
|
+
case "boolean":
|
|
17124
|
+
case "richText":
|
|
17125
|
+
case "inlineText":
|
|
17126
|
+
case "link":
|
|
17127
|
+
case "select":
|
|
17128
|
+
case "passthrough": return value;
|
|
17129
|
+
case "media": return value;
|
|
17130
|
+
default: return assertNever$1(plan);
|
|
17131
|
+
}
|
|
17132
|
+
}
|
|
17133
|
+
function normalizeObjectChildren(children, value, ctx) {
|
|
17134
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
17135
|
+
const normalized = { ...value };
|
|
17136
|
+
for (const child of children) normalized[child.fieldId] = normalizeFieldValue(child, normalized[child.fieldId], ctx);
|
|
17137
|
+
normalizeInlineTextFallbacks(children, normalized, ctx);
|
|
17138
|
+
return normalized;
|
|
17139
|
+
}
|
|
17140
|
+
function normalizeInlineTextFallbacks(plans, values, ctx) {
|
|
17141
|
+
for (const plan of plans) {
|
|
17142
|
+
if (plan.kind !== "inlineText" || !plan.plainTextFallbackPath) continue;
|
|
17143
|
+
if (!isMissingForPlan(plan, values[plan.fieldId]) && !(ctx.allowIncomplete && !parseInlineTextFromUnknown(values[plan.fieldId]).ok)) continue;
|
|
17144
|
+
const fallback = getAtFieldPath(values, plan.plainTextFallbackPath);
|
|
17145
|
+
if (typeof fallback !== "string" || fallback.trim().length === 0) continue;
|
|
17146
|
+
values[plan.fieldId] = normalizeFieldValue(plan, plainTextToInlineText(fallback), ctx);
|
|
17147
|
+
}
|
|
17148
|
+
}
|
|
17149
|
+
function getAtFieldPath(source, path) {
|
|
17150
|
+
return path.reduce((current, segment) => {
|
|
17151
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) return void 0;
|
|
17152
|
+
return current[String(segment)];
|
|
17153
|
+
}, source);
|
|
17154
|
+
}
|
|
17155
|
+
function normalizeRepeaterItems(plan, value, ctx) {
|
|
17156
|
+
if (!isUnknownArray(value)) return value;
|
|
17157
|
+
return value.map((item) => {
|
|
17158
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return item;
|
|
17159
|
+
const itemRecord = item;
|
|
17160
|
+
const fields = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemRecord._type)?.fields : plan.repeatedItemPlan;
|
|
17161
|
+
if (!fields) return item;
|
|
17162
|
+
return normalizeObjectChildren(fields, itemRecord, ctx);
|
|
17163
|
+
});
|
|
17164
|
+
}
|
|
17165
|
+
function normalizeNumberInput(value, _allowNull) {
|
|
17166
|
+
if (value === "") return void 0;
|
|
17167
|
+
if (typeof value === "string" && value.trim() !== "") return Number(value);
|
|
17168
|
+
return value;
|
|
17169
|
+
}
|
|
17170
|
+
function acceptsOptionalBlankAsMissing(plan, value) {
|
|
17171
|
+
if (plan.required || typeof value !== "string" || value.trim() !== "") return false;
|
|
17172
|
+
return plan.constraints.some((constraint) => constraint.kind === "urlFormat" || constraint.kind === "slugFormat" || constraint.kind === "emailFormat" || constraint.kind === "phoneFormat" || constraint.kind === "patternFormat");
|
|
17173
|
+
}
|
|
17174
|
+
function validateNormalizedFieldValue(plan, value, ctx) {
|
|
17175
|
+
if (value === null && (ctx.allowNull || acceptsOptionalNullValue(plan))) return [];
|
|
17176
|
+
if (isMissingForPlan(plan, value)) return shouldRequireValue(plan, value, ctx) ? [requiredIssue(plan, value)] : [];
|
|
17177
|
+
switch (plan.kind) {
|
|
17178
|
+
case "string": return validateStringPlan(plan, value);
|
|
17179
|
+
case "number": return validateNumberPlan(plan, value);
|
|
17180
|
+
case "boolean": return typeof value === "boolean" ? [] : [issue(plan, "wrongType", { expected: "a true/false value" })];
|
|
17181
|
+
case "select": return validateSelectPlan(plan, value);
|
|
17182
|
+
case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
|
|
17183
|
+
case "inlineText": return validateInlineTextPlan(plan, value);
|
|
17184
|
+
case "media": return isPlainObject$2(value) && mediaIdentifierSchema.safeParse(value.identifier).success && (value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type)) ? [] : [issue(plan, "invalidMedia")];
|
|
17185
|
+
case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
|
|
17186
|
+
case "repeater": return validateRepeaterPlan(plan, value, ctx);
|
|
17187
|
+
case "group": return validateGroupPlan(plan, value, ctx);
|
|
17188
|
+
case "passthrough": return [];
|
|
17189
|
+
default: return assertNever$1(plan);
|
|
17190
|
+
}
|
|
17191
|
+
}
|
|
17192
|
+
function shouldRequireValue(plan, value, ctx) {
|
|
17193
|
+
if (!plan.required || ctx.allowIncomplete) return false;
|
|
17194
|
+
if (value === null && ctx.allowNull) return false;
|
|
17195
|
+
return true;
|
|
17196
|
+
}
|
|
17197
|
+
function acceptsOptionalNullValue(plan) {
|
|
17198
|
+
return !plan.required && (plan.kind === "media" || plan.kind === "number");
|
|
17199
|
+
}
|
|
17200
|
+
function isMissingForPlan(plan, value) {
|
|
17201
|
+
if (value === void 0) return true;
|
|
17202
|
+
if (value === null) return plan.required;
|
|
17203
|
+
if (typeof value === "string" && value.trim() === "") return true;
|
|
17204
|
+
if (Array.isArray(value) && value.length === 0) return true;
|
|
17205
|
+
return false;
|
|
17206
|
+
}
|
|
17207
|
+
function validateStringPlan(plan, value) {
|
|
17208
|
+
if (plan.constraints.some((constraint) => constraint.kind === "blockIconValue")) return plan.constraints.flatMap((constraint) => validateStringConstraint(plan, constraint, value));
|
|
17209
|
+
if (typeof value !== "string") return [issue(plan, "wrongType", { expected: "text" })];
|
|
17210
|
+
return plan.constraints.flatMap((constraint) => validateStringConstraint(plan, constraint, value));
|
|
17211
|
+
}
|
|
17212
|
+
function validateStringConstraint(plan, constraint, value) {
|
|
17213
|
+
switch (constraint.kind) {
|
|
17214
|
+
case "required": return [];
|
|
17215
|
+
case "textType":
|
|
17216
|
+
case "referenceText": return typeof value === "string" ? [] : [issue(plan, "wrongType", { expected: "text" })];
|
|
17217
|
+
case "blockIconValue": return isValidIconPickerValue(value) ? [] : [issue(plan, "wrongType", { expected: "text or icon" })];
|
|
17218
|
+
case "maxLength": return typeof value === "string" && value.length > constraint.maximum ? [issue(plan, "tooLong", { maximum: constraint.maximum })] : [];
|
|
17219
|
+
case "emailFormat": return typeof value === "string" && isCanonicalEmailValue(value) ? [] : [issue(plan, "invalidEmail")];
|
|
17220
|
+
case "phoneFormat": return typeof value === "string" && isCanonicalPhoneValue(value) ? [] : [issue(plan, "invalidPhone")];
|
|
17221
|
+
case "patternFormat": {
|
|
17222
|
+
if (typeof value !== "string") return [issue(plan, "wrongType", { expected: "text" })];
|
|
17223
|
+
const re = compilePattern(constraint.pattern);
|
|
17224
|
+
return re && !re.test(value) ? [issue(plan, "invalidPattern")] : [];
|
|
17225
|
+
}
|
|
17226
|
+
case "urlFormat": return typeof value === "string" && isCanonicalUrlValue(value, { allowRelative: constraint.allowRelative }) ? [] : [issue(plan, "invalidUrl")];
|
|
17227
|
+
case "dateFormat": return typeof value === "string" && isValidDateString(value) ? [] : [issue(plan, "invalidDate")];
|
|
17228
|
+
case "timeFormat": return typeof value === "string" && isValidTimeString(value) ? [] : [issue(plan, "invalidTime")];
|
|
17229
|
+
case "datetimeFormat": return typeof value === "string" && isValidDateTimeInstantString(value) ? [] : [issue(plan, "invalidDateTime")];
|
|
17230
|
+
case "slugFormat": return typeof value === "string" && SLUG_PATTERN.test(value) ? [] : [issue(plan, "invalidSlug")];
|
|
17231
|
+
default: return assertNever$1(constraint);
|
|
17232
|
+
}
|
|
17233
|
+
}
|
|
17234
|
+
function isValidIconPickerValue(value) {
|
|
17235
|
+
if (typeof value === "string") return true;
|
|
17236
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
17237
|
+
if (value.kind === "none") return true;
|
|
17238
|
+
return parseBlockIconValue(value).kind !== "none";
|
|
17239
|
+
}
|
|
17240
|
+
function validateNumberPlan(plan, value) {
|
|
17241
|
+
if (!isValidNumber(value)) return [issue(plan, "invalidNumber")];
|
|
17242
|
+
return plan.constraints.flatMap((constraint) => validateNumberConstraint(plan, constraint, Number(value)));
|
|
17243
|
+
}
|
|
17244
|
+
function validateNumberConstraint(plan, constraint, value) {
|
|
17245
|
+
switch (constraint.kind) {
|
|
17246
|
+
case "required":
|
|
17247
|
+
case "numberType": return [];
|
|
17248
|
+
case "numberMin": return value < constraint.minimum ? [issue(plan, "tooSmall", { minimum: constraint.minimum })] : [];
|
|
17249
|
+
case "numberMax": return value > constraint.maximum ? [issue(plan, "tooLarge", { maximum: constraint.maximum })] : [];
|
|
17250
|
+
default: return assertNever$1(constraint);
|
|
17251
|
+
}
|
|
17252
|
+
}
|
|
17253
|
+
function validateSelectPlan(plan, value) {
|
|
17254
|
+
const constraint = plan.constraints.find((candidate) => candidate.kind === "selectOption");
|
|
17255
|
+
if (!constraint || constraint.source.kind === "runtime") return [];
|
|
17256
|
+
return isValidSelectValue(value, constraint.source.values, constraint.multiple) ? [] : [issue(plan, "invalidOption")];
|
|
17257
|
+
}
|
|
17258
|
+
function validateRepeaterPlan(plan, value, ctx) {
|
|
17259
|
+
if (!Array.isArray(value)) return [issue(plan, "wrongType", { expected: "a list" })];
|
|
17260
|
+
return [...plan.constraints.flatMap((constraint) => {
|
|
17261
|
+
switch (constraint.kind) {
|
|
17262
|
+
case "required":
|
|
17263
|
+
case "arrayType": return [];
|
|
17264
|
+
case "minItems": return value.length < constraint.minimum ? [issue(plan, "tooFewItems", {
|
|
17265
|
+
minimum: constraint.minimum,
|
|
17266
|
+
itemLabel: "item"
|
|
17267
|
+
})] : [];
|
|
17268
|
+
case "maxItems": return value.length > constraint.maximum ? [issue(plan, "tooManyItems", {
|
|
17269
|
+
maximum: constraint.maximum,
|
|
17270
|
+
itemLabel: "item"
|
|
17271
|
+
})] : [];
|
|
17272
|
+
default: return assertNever$1(constraint);
|
|
17273
|
+
}
|
|
17274
|
+
}), ...value.flatMap((item, index) => validateRepeaterItem(plan, item, index, ctx))];
|
|
17275
|
+
}
|
|
17276
|
+
function validateRepeaterItem(plan, item, index, ctx) {
|
|
17277
|
+
if (!isPlainObject$2(item)) return [{
|
|
17278
|
+
kind: "wrongType",
|
|
17279
|
+
path: [...plan.path, index],
|
|
17280
|
+
fieldId: plan.fieldId,
|
|
17281
|
+
label: plan.label,
|
|
17282
|
+
expected: "an object"
|
|
17283
|
+
}];
|
|
17284
|
+
const itemType = item._type;
|
|
17285
|
+
const variant = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((candidate) => candidate.typeId === itemType) : void 0;
|
|
17286
|
+
if (plan.repeatedItemVariants && !variant) return [{
|
|
17287
|
+
kind: "invalidOption",
|
|
17288
|
+
path: [
|
|
17289
|
+
...plan.path,
|
|
17290
|
+
index,
|
|
17291
|
+
"_type"
|
|
17292
|
+
],
|
|
17293
|
+
fieldId: "_type",
|
|
17294
|
+
label: `${plan.label} item type`
|
|
17295
|
+
}];
|
|
17296
|
+
const fields = variant?.fields ?? plan.repeatedItemPlan;
|
|
17297
|
+
if (!fields) return [];
|
|
17298
|
+
return fields.flatMap((childPlan) => {
|
|
17299
|
+
return validateNormalizedFieldValue(materializeRepeaterItemPlan(childPlan, plan.path, index), item[childPlan.fieldId], ctx);
|
|
17300
|
+
});
|
|
17301
|
+
}
|
|
17302
|
+
function validateGroupPlan(plan, value, ctx) {
|
|
17303
|
+
if (!isPlainObject$2(value)) return [issue(plan, "wrongType", { expected: "an object" })];
|
|
17304
|
+
if (plan.childSelection.kind === "discriminatedTabs") {
|
|
17305
|
+
const selectedType = value[plan.childSelection.activeTabField];
|
|
17306
|
+
if (selectedType !== void 0 && selectedType !== null && !plan.childSelection.tabs.some((tab) => tab.typeId === selectedType)) return [{
|
|
17307
|
+
kind: "invalidOption",
|
|
17308
|
+
path: [...plan.path, plan.childSelection.activeTabField],
|
|
17309
|
+
fieldId: plan.childSelection.activeTabField,
|
|
17310
|
+
label: `${plan.label} type`
|
|
17311
|
+
}];
|
|
17312
|
+
}
|
|
17313
|
+
const childCtx = childValidationContext(plan, ctx);
|
|
17314
|
+
const childIssues = selectedGroupChildPlans(plan, value).flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
|
|
17315
|
+
if (childIssues.length > 0) return childIssues;
|
|
17316
|
+
if (plan.valueContract === "boxBackground" && !boxBackgroundSchema.safeParse(value).success) return [issue(plan, "invalidBoxBackground")];
|
|
17317
|
+
return [];
|
|
17318
|
+
}
|
|
17319
|
+
function childValidationContext(plan, ctx) {
|
|
17320
|
+
return plan.allowNullChildren ? {
|
|
17321
|
+
...ctx,
|
|
17322
|
+
allowNull: true
|
|
17323
|
+
} : ctx;
|
|
17324
|
+
}
|
|
17325
|
+
function materializeRepeaterItemPlan(plan, parentPath, index) {
|
|
17326
|
+
return rebaseFieldPlanPath(plan, [...parentPath, 0], [...parentPath, index]);
|
|
17327
|
+
}
|
|
17328
|
+
function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
|
|
17329
|
+
const path = rebaseFieldPath(plan.path, fromPrefix, toPrefix);
|
|
17330
|
+
switch (plan.kind) {
|
|
17331
|
+
case "group": return {
|
|
17332
|
+
...plan,
|
|
17333
|
+
path,
|
|
17334
|
+
childSelection: plan.childSelection.kind === "all" ? {
|
|
17335
|
+
kind: "all",
|
|
17336
|
+
fields: plan.childSelection.fields.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
|
|
17337
|
+
} : {
|
|
17338
|
+
...plan.childSelection,
|
|
17339
|
+
tabs: plan.childSelection.tabs.map((tab) => ({
|
|
17340
|
+
...tab,
|
|
17341
|
+
fields: tab.fields.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
|
|
17342
|
+
}))
|
|
17343
|
+
}
|
|
17344
|
+
};
|
|
17345
|
+
case "repeater": return {
|
|
17346
|
+
...plan,
|
|
17347
|
+
path,
|
|
17348
|
+
...plan.repeatedItemVariants ? { repeatedItemVariants: plan.repeatedItemVariants.map((variant) => ({
|
|
17349
|
+
...variant,
|
|
17350
|
+
fields: variant.fields.map((fieldPlan) => rebaseFieldPlanPath(fieldPlan, fromPrefix, toPrefix))
|
|
17351
|
+
})) } : {},
|
|
17352
|
+
...plan.repeatedItemPlan ? { repeatedItemPlan: plan.repeatedItemPlan.map((fieldPlan) => rebaseFieldPlanPath(fieldPlan, fromPrefix, toPrefix)) } : {}
|
|
17353
|
+
};
|
|
17354
|
+
case "string":
|
|
17355
|
+
case "number":
|
|
17356
|
+
case "boolean":
|
|
17357
|
+
case "richText":
|
|
17358
|
+
case "inlineText":
|
|
17359
|
+
case "media":
|
|
17360
|
+
case "link":
|
|
17361
|
+
case "select":
|
|
17362
|
+
case "passthrough": return {
|
|
17363
|
+
...plan,
|
|
17364
|
+
path
|
|
17365
|
+
};
|
|
17366
|
+
default: return assertNever$1(plan);
|
|
17367
|
+
}
|
|
17368
|
+
}
|
|
17369
|
+
function validateInlineTextPlan(plan, value) {
|
|
17370
|
+
const parsed = parseInlineTextFromUnknown(value);
|
|
17371
|
+
if (!parsed.ok) return [issue(plan, "invalidInlineText")];
|
|
17372
|
+
const text = inlineTextToPlainText(parsed.value);
|
|
17373
|
+
const lengthIssue = plan.constraints.find((constraint) => constraint.kind === "maxPlainTextLength");
|
|
17374
|
+
if (lengthIssue && text.length > lengthIssue.maximum) return [issue(plan, "tooLong", { maximum: lengthIssue.maximum })];
|
|
17375
|
+
return [];
|
|
17376
|
+
}
|
|
17377
|
+
function rebaseFieldPath(path, fromPrefix, toPrefix) {
|
|
17378
|
+
if (!startsWithFieldPath(path, fromPrefix)) throw new Error(`Cannot rebase field path ${formatFieldPath(path)} from ${formatFieldPath(fromPrefix)}`);
|
|
17379
|
+
return [...toPrefix, ...path.slice(fromPrefix.length)];
|
|
17380
|
+
}
|
|
17381
|
+
function startsWithFieldPath(path, prefix) {
|
|
17382
|
+
return prefix.every((segment, index) => path[index] === segment);
|
|
17383
|
+
}
|
|
17384
|
+
function issue(plan, kind, extra) {
|
|
17385
|
+
return {
|
|
17386
|
+
kind,
|
|
17387
|
+
path: plan.path,
|
|
17388
|
+
fieldId: plan.fieldId,
|
|
17389
|
+
label: plan.label,
|
|
17390
|
+
...extra ?? {}
|
|
17391
|
+
};
|
|
17392
|
+
}
|
|
17393
|
+
function requiredIssue(plan, value) {
|
|
17394
|
+
if (typeof value === "string") return issue(plan, "required", { emptyOrigin: "string" });
|
|
17395
|
+
if (Array.isArray(value)) return issue(plan, "required", { emptyOrigin: "array" });
|
|
17396
|
+
return issue(plan, "required");
|
|
17397
|
+
}
|
|
17398
|
+
function fieldPlanToZod(plan, options = {}) {
|
|
17399
|
+
const ctx = validationContext(options);
|
|
17400
|
+
return z.any().transform((value) => normalizeFieldValue(plan, value, ctx)).superRefine((value, zodCtx) => {
|
|
17401
|
+
for (const validationIssue of validateNormalizedFieldValue(plan, value, ctx)) addFieldIssueToZodContext(zodCtx, validationIssue, plan.path);
|
|
17402
|
+
});
|
|
17403
|
+
}
|
|
17404
|
+
function fieldPresenceForPlan(plan) {
|
|
17405
|
+
return plan.required ? { kind: "required" } : { kind: "optional" };
|
|
17406
|
+
}
|
|
17407
|
+
function fieldPlanToObjectPropertyZod(plan, options = {}) {
|
|
17408
|
+
const schema = fieldPlanToZod(plan, options);
|
|
17409
|
+
const presence = fieldPresenceForPlan(plan);
|
|
17410
|
+
switch (presence.kind) {
|
|
17411
|
+
case "required": return schema;
|
|
17412
|
+
case "optional": return schema.optional();
|
|
17413
|
+
default: return assertNever$1(presence);
|
|
17414
|
+
}
|
|
17415
|
+
}
|
|
17416
|
+
/** Validate stored field values without applying editor/write normalization. */
|
|
17417
|
+
function fieldPlanToStoredObjectPropertyZod(plan) {
|
|
17418
|
+
const ctx = strictValidationContext({ allowNull: false });
|
|
17419
|
+
const schema = z.any().superRefine((value, zodCtx) => {
|
|
17420
|
+
for (const validationIssue of validateNormalizedFieldValue(plan, value, ctx)) addFieldIssueToZodContext(zodCtx, validationIssue, plan.path);
|
|
17421
|
+
});
|
|
17422
|
+
return plan.required ? schema : schema.optional();
|
|
17423
|
+
}
|
|
17424
|
+
function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
|
|
17425
|
+
const message = fieldIssueToMessage(validationIssue);
|
|
17426
|
+
const path = relativeZodIssuePath(validationIssue.path, rootPath);
|
|
17427
|
+
const issuePath = path.length > 0 ? { path: toZodIssuePath(path) } : {};
|
|
17428
|
+
switch (validationIssue.kind) {
|
|
17429
|
+
case "required":
|
|
17430
|
+
if (validationIssue.emptyOrigin) {
|
|
17431
|
+
zodCtx.addIssue({
|
|
17432
|
+
...issuePath,
|
|
17433
|
+
code: "too_small",
|
|
17434
|
+
origin: validationIssue.emptyOrigin,
|
|
17435
|
+
minimum: 1,
|
|
17436
|
+
inclusive: true,
|
|
17437
|
+
message
|
|
17438
|
+
});
|
|
17439
|
+
return;
|
|
17440
|
+
}
|
|
17441
|
+
zodCtx.addIssue({
|
|
17442
|
+
...issuePath,
|
|
17443
|
+
code: "invalid_type",
|
|
17444
|
+
expected: "nonoptional",
|
|
17445
|
+
message
|
|
17446
|
+
});
|
|
17447
|
+
return;
|
|
17448
|
+
case "tooLong":
|
|
17449
|
+
zodCtx.addIssue({
|
|
17450
|
+
...issuePath,
|
|
17451
|
+
code: "too_big",
|
|
17452
|
+
origin: "string",
|
|
17453
|
+
maximum: validationIssue.maximum,
|
|
17454
|
+
inclusive: true,
|
|
17455
|
+
message
|
|
17456
|
+
});
|
|
17457
|
+
return;
|
|
17458
|
+
case "invalidOption":
|
|
17459
|
+
zodCtx.addIssue({
|
|
17460
|
+
...issuePath,
|
|
17461
|
+
code: "invalid_value",
|
|
17462
|
+
values: [],
|
|
17463
|
+
message
|
|
17464
|
+
});
|
|
17465
|
+
return;
|
|
17466
|
+
case "wrongType":
|
|
17467
|
+
case "invalidEmail":
|
|
17468
|
+
case "invalidPhone":
|
|
17469
|
+
case "invalidPattern":
|
|
17470
|
+
case "invalidUrl":
|
|
17471
|
+
case "invalidDate":
|
|
17472
|
+
case "invalidTime":
|
|
17473
|
+
case "invalidDateTime":
|
|
17474
|
+
case "invalidNumber":
|
|
17475
|
+
case "tooSmall":
|
|
17476
|
+
case "tooLarge":
|
|
17477
|
+
case "invalidSlug":
|
|
17478
|
+
case "tooFewItems":
|
|
17479
|
+
case "tooManyItems":
|
|
17480
|
+
case "invalidRichText":
|
|
17481
|
+
case "invalidInlineText":
|
|
17482
|
+
case "invalidMedia":
|
|
17483
|
+
case "invalidBoxBackground":
|
|
17484
|
+
case "invalidLink":
|
|
17485
|
+
case "invalidReference":
|
|
17486
|
+
zodCtx.addIssue({
|
|
17487
|
+
...issuePath,
|
|
17488
|
+
code: "custom",
|
|
17489
|
+
message
|
|
17490
|
+
});
|
|
17491
|
+
return;
|
|
17492
|
+
default: assertNever$1(validationIssue);
|
|
17493
|
+
}
|
|
17494
|
+
}
|
|
17495
|
+
function relativeZodIssuePath(path, rootPath) {
|
|
17496
|
+
return startsWithFieldPath(path, rootPath) ? path.slice(rootPath.length) : path;
|
|
17497
|
+
}
|
|
17498
|
+
function compilePattern(pattern) {
|
|
17499
|
+
try {
|
|
17500
|
+
return new RegExp(pattern);
|
|
17501
|
+
} catch {
|
|
17502
|
+
return null;
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
function isValidNumber(value) {
|
|
17506
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
17507
|
+
}
|
|
17508
|
+
function isCanonicalEmailValue(value) {
|
|
17509
|
+
return z.email().safeParse(value).success;
|
|
17510
|
+
}
|
|
17511
|
+
function isCanonicalPhoneValue(value) {
|
|
17512
|
+
return TEL_RE.test(value);
|
|
17513
|
+
}
|
|
17514
|
+
function isCanonicalUrlValue(value, options = {}) {
|
|
17515
|
+
if (!value) return false;
|
|
17516
|
+
if (options.allowRelative === true && value.startsWith("/")) return true;
|
|
17517
|
+
try {
|
|
17518
|
+
const parsed = new URL(value);
|
|
17519
|
+
return ALLOWED_URL_PROTOCOLS.includes(parsed.protocol);
|
|
17520
|
+
} catch {
|
|
17521
|
+
return false;
|
|
17522
|
+
}
|
|
17523
|
+
}
|
|
17524
|
+
function isValidDateString(value) {
|
|
17525
|
+
const match = DATE_PATTERN.exec(value);
|
|
17526
|
+
if (!match?.groups) return false;
|
|
17527
|
+
return isValidCalendarDate(Number(match.groups.year), Number(match.groups.month), Number(match.groups.day));
|
|
17528
|
+
}
|
|
17529
|
+
function isValidTimeString(value) {
|
|
17530
|
+
return TIME_PATTERN.test(value);
|
|
17531
|
+
}
|
|
17532
|
+
function isValidDateTimeInstantString(value) {
|
|
17533
|
+
const match = DATETIME_PATTERN.exec(value);
|
|
17534
|
+
if (!match?.groups) return false;
|
|
17535
|
+
const datePart = match.groups.date;
|
|
17536
|
+
if (!datePart || !isValidDateString(datePart)) return false;
|
|
17537
|
+
return !Number.isNaN(Date.parse(value));
|
|
17538
|
+
}
|
|
17539
|
+
function isValidCalendarDate(year, month, day) {
|
|
17540
|
+
if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) return false;
|
|
17541
|
+
if (year < 1 || month < 1 || month > 12) return false;
|
|
17542
|
+
return day >= 1 && day <= daysInMonth(year, month);
|
|
17543
|
+
}
|
|
17544
|
+
function daysInMonth(year, month) {
|
|
17545
|
+
switch (month) {
|
|
17546
|
+
case 2: return isLeapYear(year) ? 29 : 28;
|
|
17547
|
+
case 4:
|
|
17548
|
+
case 6:
|
|
17549
|
+
case 9:
|
|
17550
|
+
case 11: return 30;
|
|
17551
|
+
case 1:
|
|
17552
|
+
case 3:
|
|
17553
|
+
case 5:
|
|
17554
|
+
case 7:
|
|
17555
|
+
case 8:
|
|
17556
|
+
case 10:
|
|
17557
|
+
case 12: return 31;
|
|
17558
|
+
default: return 0;
|
|
17559
|
+
}
|
|
17560
|
+
}
|
|
17561
|
+
function isLeapYear(year) {
|
|
17562
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
17563
|
+
}
|
|
17564
|
+
function isValidSelectValue(value, values, multiple) {
|
|
17565
|
+
if (multiple) return Array.isArray(value) && value.every((item) => typeof item === "string" && values.includes(item));
|
|
17566
|
+
return typeof value === "string" && values.includes(value);
|
|
17567
|
+
}
|
|
17568
|
+
function isEmptyValue(value) {
|
|
17569
|
+
if (value === null || value === void 0) return true;
|
|
17570
|
+
if (typeof value === "string" && value.trim() === "") return true;
|
|
17571
|
+
if (Array.isArray(value) && value.length === 0) return true;
|
|
17572
|
+
if (isEmptyRichTextDoc(value)) return true;
|
|
17573
|
+
return false;
|
|
17574
|
+
}
|
|
17575
|
+
function isPlainObject$2(value) {
|
|
17576
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
17577
|
+
}
|
|
17578
|
+
function isUnknownArray(value) {
|
|
17579
|
+
return Array.isArray(value);
|
|
17580
|
+
}
|
|
17581
|
+
function isValidRichTextDoc(value) {
|
|
17582
|
+
return isRichTextDoc(value);
|
|
17583
|
+
}
|
|
17584
|
+
function isEmptyRichTextDoc(value) {
|
|
17585
|
+
if (!isPlainObject$2(value)) return false;
|
|
17586
|
+
if (value.type !== "doc") return false;
|
|
17587
|
+
const content = value.content;
|
|
17588
|
+
if (!Array.isArray(content) || content.length === 0) return true;
|
|
17589
|
+
if (content.length !== 1) return false;
|
|
17590
|
+
const first = content[0];
|
|
17591
|
+
return first?.type === "paragraph" && (!Array.isArray(first.content) || first.content.length === 0);
|
|
17592
|
+
}
|
|
17593
|
+
//#endregion
|
|
17594
|
+
//#region ../blocks/src/system/manifest/registry.ts
|
|
17595
|
+
const REGISTRY_SYMBOL$1 = Symbol.for("@riverbankcms/blocks/manifest-registry");
|
|
17596
|
+
const isBlocksTestRuntime$1 = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.RIVERBANK_BLOCKS_TEST === "1";
|
|
17597
|
+
const globalScope$1 = globalThis;
|
|
17598
|
+
const manifestStore = isBlocksTestRuntime$1 ? /* @__PURE__ */ new Map() : globalScope$1[REGISTRY_SYMBOL$1] ?? (globalScope$1[REGISTRY_SYMBOL$1] = /* @__PURE__ */ new Map());
|
|
17599
|
+
function registerManifest(manifest) {
|
|
17600
|
+
manifestStore.set(manifest.name, manifest);
|
|
17601
|
+
return manifest;
|
|
17602
|
+
}
|
|
17603
|
+
//#endregion
|
|
17604
|
+
//#region ../blocks/src/system/manifest/validation.ts
|
|
17605
|
+
const compiledManifestContentContract = Symbol("compiledManifestContentContract");
|
|
17606
|
+
/**
|
|
17607
|
+
* Preprocess content by converting empty values to undefined.
|
|
17608
|
+
* Used in draft mode to allow required fields to be temporarily empty.
|
|
17609
|
+
*/
|
|
17610
|
+
function preprocessEmptyValues(content) {
|
|
17611
|
+
if (!content || typeof content !== "object" || Array.isArray(content)) return {};
|
|
17612
|
+
const result = {};
|
|
17613
|
+
for (const [key, value] of Object.entries(content)) result[key] = isEmptyValue(value) ? void 0 : value;
|
|
17614
|
+
return result;
|
|
17615
|
+
}
|
|
17616
|
+
/**
|
|
17617
|
+
* Compiles editor-facing manifest structure into the presentation-independent
|
|
17618
|
+
* validation contract used by every manifest-content trust transition.
|
|
17619
|
+
*/
|
|
17620
|
+
function compileManifestContentContract(manifestOrFields) {
|
|
17621
|
+
const plans = derivePlansFromManifestOrFields(manifestOrFields);
|
|
17622
|
+
const strictOptions = { allowNull: false };
|
|
17623
|
+
const strictStoredSchema = deriveStrictStoredZodFromPlans(plans);
|
|
17624
|
+
return Object.freeze({ [compiledManifestContentContract]: Object.freeze({
|
|
17625
|
+
plans,
|
|
17626
|
+
strictStoredSchema,
|
|
17627
|
+
writeSchema: deriveNormalizedContentZodFromPlans(plans, strictOptions, normalizeManifestContentForWrite).transform((value) => canonicalizeObjectForWrite(plans, value)),
|
|
17628
|
+
draftSchema: deriveNormalizedContentZodFromPlans(plans, {
|
|
17629
|
+
allowNull: true,
|
|
17630
|
+
allowIncomplete: true,
|
|
17631
|
+
mode: "draft"
|
|
17632
|
+
}, normalizeStoredContentValues),
|
|
17633
|
+
renderSchema: strictStoredSchema,
|
|
17634
|
+
findNonPortableMediaPaths: (content) => findNonPortableMediaPaths(plans, content)
|
|
17635
|
+
}) });
|
|
17636
|
+
}
|
|
17637
|
+
/**
|
|
17638
|
+
* Re-admits renderable content after a transport boundary has erased its
|
|
17639
|
+
* compile-time proof. Unlike write admission, this never canonicalizes or
|
|
17640
|
+
* grants a stored proof, so hydrated media cannot flow back to persistence.
|
|
17641
|
+
*/
|
|
17642
|
+
function admitTransportedRenderableManifestContent(contract, content) {
|
|
17643
|
+
const parsed = contract[compiledManifestContentContract].renderSchema.safeParse(content);
|
|
17644
|
+
return parsed.success ? {
|
|
17645
|
+
ok: true,
|
|
17646
|
+
value: content
|
|
17647
|
+
} : {
|
|
17648
|
+
ok: false,
|
|
17649
|
+
error: zodAdmissionError(parsed.error)
|
|
17650
|
+
};
|
|
17651
|
+
}
|
|
17652
|
+
function deriveNormalizedContentZodFromPlans(plans, options, normalize) {
|
|
17653
|
+
const isDraft = options.mode === "draft";
|
|
17654
|
+
const baseSchema = deriveContentZodFromPlans(plans, options);
|
|
17655
|
+
if (isDraft) return z.preprocess((content) => preprocessEmptyValues(normalize(plans, content, options)), baseSchema);
|
|
17656
|
+
return z.preprocess((content) => normalize(plans, content, options), baseSchema);
|
|
17657
|
+
}
|
|
17658
|
+
function deriveContentZodFromPlans(plans, options) {
|
|
17659
|
+
const shape = {};
|
|
17660
|
+
for (const plan of plans) shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
|
|
17661
|
+
return z.object(shape).catchall(z.unknown()).passthrough();
|
|
17662
|
+
}
|
|
17663
|
+
function deriveStrictStoredZodFromPlans(plans) {
|
|
17664
|
+
const shape = {};
|
|
17665
|
+
for (const plan of plans) shape[plan.fieldId] = fieldPlanToStoredObjectPropertyZod(plan);
|
|
17666
|
+
return z.object(shape).catchall(z.unknown()).passthrough();
|
|
17667
|
+
}
|
|
17668
|
+
function derivePlansFromManifestOrFields(manifestOrFields) {
|
|
17669
|
+
return deriveFieldValidationPlans(Array.isArray(manifestOrFields) ? manifestOrFields : manifestOrFields.fields ?? []);
|
|
17670
|
+
}
|
|
17671
|
+
function zodAdmissionError(error) {
|
|
17672
|
+
return {
|
|
17673
|
+
kind: "invalid_shape",
|
|
17674
|
+
issues: zodAdmissionIssues(error)
|
|
17675
|
+
};
|
|
17676
|
+
}
|
|
17677
|
+
function zodAdmissionIssues(error) {
|
|
17678
|
+
return error.issues.map((issue) => ({
|
|
17679
|
+
code: issue.code,
|
|
17680
|
+
path: issue.path.map((segment) => typeof segment === "number" ? segment : String(segment)),
|
|
17681
|
+
message: issue.message
|
|
17682
|
+
}));
|
|
17683
|
+
}
|
|
17684
|
+
function findNonPortableMediaPaths(plans, content) {
|
|
17685
|
+
const paths = /* @__PURE__ */ new Set();
|
|
17686
|
+
collectNonPortablePlannedMedia(plans, content, [], paths);
|
|
17687
|
+
return [...paths].sort();
|
|
17688
|
+
}
|
|
17689
|
+
function collectNonPortablePlannedMedia(plans, content, parentPath, paths) {
|
|
17690
|
+
if (!isPlainRecord(content)) return;
|
|
17691
|
+
for (const plan of plans) {
|
|
17692
|
+
if (!(plan.fieldId in content)) continue;
|
|
17693
|
+
const value = content[plan.fieldId];
|
|
17694
|
+
const path = [...parentPath, plan.fieldId];
|
|
17695
|
+
switch (plan.kind) {
|
|
17696
|
+
case "media":
|
|
17697
|
+
if (isPlainRecord(value) && hasEnvironmentSpecificMediaField(value)) paths.add(formatFieldPath(path));
|
|
17698
|
+
break;
|
|
17699
|
+
case "richText":
|
|
17700
|
+
collectNonPortableRichTextImages(value, path, paths);
|
|
17701
|
+
break;
|
|
17702
|
+
case "group":
|
|
17703
|
+
collectNonPortablePlannedMedia(selectedGroupChildPlans(plan, value), value, path, paths);
|
|
17704
|
+
break;
|
|
17705
|
+
case "repeater":
|
|
17706
|
+
collectNonPortableRepeaterMedia(plan, value, path, paths);
|
|
17707
|
+
break;
|
|
17708
|
+
case "string":
|
|
17709
|
+
case "number":
|
|
17710
|
+
case "boolean":
|
|
17711
|
+
case "inlineText":
|
|
17712
|
+
case "link":
|
|
17713
|
+
case "select":
|
|
17714
|
+
case "passthrough": break;
|
|
17715
|
+
}
|
|
17716
|
+
}
|
|
17717
|
+
}
|
|
17718
|
+
function collectNonPortableRepeaterMedia(plan, value, path, paths) {
|
|
17719
|
+
if (!Array.isArray(value)) return;
|
|
17720
|
+
value.forEach((item, index) => {
|
|
17721
|
+
if (!isPlainRecord(item)) return;
|
|
17722
|
+
const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
|
|
17723
|
+
if (childPlans) collectNonPortablePlannedMedia(childPlans, item, [...path, index], paths);
|
|
17724
|
+
});
|
|
17725
|
+
}
|
|
17726
|
+
function collectNonPortableRichTextImages(value, path, paths) {
|
|
17727
|
+
const images = [];
|
|
17728
|
+
walkAndCollectImageAttrs(value, images);
|
|
17729
|
+
const prefix = formatFieldPath(path);
|
|
17730
|
+
for (const reference of images) if (hasEnvironmentSpecificMediaField(reference.attrs)) paths.add(reference.location ? `${prefix}.${reference.location}` : prefix);
|
|
17731
|
+
}
|
|
17732
|
+
function isPlainRecord(value) {
|
|
17733
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17734
|
+
}
|
|
17735
|
+
function hasEnvironmentSpecificMediaField(value) {
|
|
17736
|
+
return "assetId" in value || "storageBucket" in value || "storagePath" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id);
|
|
17737
|
+
}
|
|
15805
17738
|
//#endregion
|
|
15806
17739
|
//#region ../blocks/src/system/designCapabilities.ts
|
|
15807
17740
|
function declareBlockDesignCapability(capability) {
|
|
@@ -23536,26 +25469,6 @@ const headerLogoTextVisibleTransform = {
|
|
|
23536
25469
|
return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
|
|
23537
25470
|
}
|
|
23538
25471
|
};
|
|
23539
|
-
/**
|
|
23540
|
-
* Selects which classic-layout nav row should render.
|
|
23541
|
-
*
|
|
23542
|
-
* - `'inline'` → classic variant with the historical logo-left / nav-right row
|
|
23543
|
-
* - `'centered'`→ classic variant with a centred (flex-1) nav and a right CTA
|
|
23544
|
-
* - `'other'` → not a classic variant (centered/floating handle it)
|
|
23545
|
-
*
|
|
23546
|
-
* Consumed by the site-header block's `$when` gates so the two classic rows are
|
|
23547
|
-
* mutually exclusive without introducing a new top-level header variant.
|
|
23548
|
-
*/
|
|
23549
|
-
const classicNavModeTransform = {
|
|
23550
|
-
id: "layout.classicNavMode",
|
|
23551
|
-
kind: "formatter",
|
|
23552
|
-
summary: "Resolve which classic-layout nav row to render",
|
|
23553
|
-
run: (value) => {
|
|
23554
|
-
const header = asPartialObject(value);
|
|
23555
|
-
if (header?.variant !== "classic") return "other";
|
|
23556
|
-
return header?.navPlacement === "center" ? "centered" : "inline";
|
|
23557
|
-
}
|
|
23558
|
-
};
|
|
23559
25472
|
const maxWidthClassTransform = {
|
|
23560
25473
|
id: "layout.maxWidthClass",
|
|
23561
25474
|
kind: "string",
|
|
@@ -23661,7 +25574,6 @@ const headerRootClassTransform = {
|
|
|
23661
25574
|
if (isHeaderScrollRuntimeEnabled(content)) classes.push(config.shrink);
|
|
23662
25575
|
const variant = header?.variant;
|
|
23663
25576
|
if (variant && headerVariantValues.includes(variant)) classes.push(`header-variant-${variant}`);
|
|
23664
|
-
if (header?.barFrame === "inset-shell" && variant === "classic") classes.push("header-bar-frame-inset-shell");
|
|
23665
25577
|
return joinClasses(classes);
|
|
23666
25578
|
}
|
|
23667
25579
|
};
|
|
@@ -23869,7 +25781,6 @@ const layoutTransforms = [
|
|
|
23869
25781
|
headerLogoClassTransform,
|
|
23870
25782
|
headerLogoMediaClassTransform,
|
|
23871
25783
|
headerLogoTextVisibleTransform,
|
|
23872
|
-
classicNavModeTransform,
|
|
23873
25784
|
footerRootClassTransform,
|
|
23874
25785
|
headerRootStyleTransform,
|
|
23875
25786
|
headerSectionBackgroundTransform,
|
|
@@ -23945,40 +25856,22 @@ const mediaTransforms = [{
|
|
|
23945
25856
|
}
|
|
23946
25857
|
}];
|
|
23947
25858
|
//#endregion
|
|
23948
|
-
//#region ../blocks/src/lib/typeGuards.ts
|
|
23949
|
-
/**
|
|
23950
|
-
* Strict record guard: excludes null, primitives, and arrays.
|
|
23951
|
-
*/
|
|
23952
|
-
function isRecord$8(value) {
|
|
23953
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23954
|
-
}
|
|
23955
|
-
/**
|
|
23956
|
-
* Non-null object guard: includes arrays for behavior parity with legacy helpers.
|
|
23957
|
-
*
|
|
23958
|
-
* NOTE: This intentionally narrows to UnknownRecord for compatibility with existing
|
|
23959
|
-
* callsites even though arrays pass at runtime. Follow-up cleanup should replace
|
|
23960
|
-
* this API with a more precise predicate type and migrate consumers.
|
|
23961
|
-
*/
|
|
23962
|
-
function isObjectRecord(value) {
|
|
23963
|
-
return typeof value === "object" && value !== null;
|
|
23964
|
-
}
|
|
23965
|
-
//#endregion
|
|
23966
25859
|
//#region ../blocks/src/system/transforms/registry/content.ts
|
|
23967
25860
|
const supportedRichTextTokenSchema = z.enum(["year", "site_name"]);
|
|
23968
25861
|
const interpolateRichTextTokensOptionsSchema = z.object({ tokens: z.array(supportedRichTextTokenSchema).default(["year", "site_name"]) });
|
|
23969
25862
|
const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
|
|
23970
25863
|
function getSiteName(context) {
|
|
23971
25864
|
const viewModel = context.viewModel;
|
|
23972
|
-
if (!isRecord$
|
|
25865
|
+
if (!isRecord$10(viewModel)) return null;
|
|
23973
25866
|
const site = viewModel.site;
|
|
23974
|
-
if (isRecord$
|
|
25867
|
+
if (isRecord$10(site) && typeof site.title === "string") {
|
|
23975
25868
|
const title = site.title.trim();
|
|
23976
25869
|
return title.length > 0 ? title : null;
|
|
23977
25870
|
}
|
|
23978
25871
|
const root = viewModel.$root;
|
|
23979
|
-
if (isRecord$
|
|
25872
|
+
if (isRecord$10(root)) {
|
|
23980
25873
|
const rootSite = root.site;
|
|
23981
|
-
if (isRecord$
|
|
25874
|
+
if (isRecord$10(rootSite) && typeof rootSite.title === "string") {
|
|
23982
25875
|
const title = rootSite.title.trim();
|
|
23983
25876
|
if (title.length > 0) return title;
|
|
23984
25877
|
}
|
|
@@ -24000,7 +25893,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
|
|
|
24000
25893
|
});
|
|
24001
25894
|
}
|
|
24002
25895
|
function visitRichTextNode(node, allowedTokens, tokenValues) {
|
|
24003
|
-
if (!isRecord$
|
|
25896
|
+
if (!isRecord$10(node)) return node;
|
|
24004
25897
|
let changed = false;
|
|
24005
25898
|
const nextNode = { ...node };
|
|
24006
25899
|
if (nextNode.type === "text" && typeof nextNode.text === "string") {
|
|
@@ -24021,7 +25914,7 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
|
|
|
24021
25914
|
return changed ? nextNode : node;
|
|
24022
25915
|
}
|
|
24023
25916
|
function interpolateRichTextTokens(value, options, context) {
|
|
24024
|
-
if (!isRecord$
|
|
25917
|
+
if (!isRecord$10(value)) return value;
|
|
24025
25918
|
return visitRichTextNode(value, new Set(options.tokens), {
|
|
24026
25919
|
year: String((/* @__PURE__ */ new Date()).getFullYear()),
|
|
24027
25920
|
site_name: getSiteName(context)
|
|
@@ -24269,18 +26162,7 @@ const classicLayout = inline({
|
|
|
24269
26162
|
logoRow,
|
|
24270
26163
|
createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
|
|
24271
26164
|
headerCta
|
|
24272
|
-
],
|
|
24273
|
-
const classicCenteredNavLayout = inline({
|
|
24274
|
-
className: bindProp("$root.theme.header.maxWidth", {
|
|
24275
|
-
transforms: pipe(tx("layout.maxWidthClass", { base: `rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6` })),
|
|
24276
|
-
fallback: `rb-container rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6`
|
|
24277
|
-
}),
|
|
24278
|
-
align: "center"
|
|
24279
|
-
}, [
|
|
24280
|
-
logoRow,
|
|
24281
|
-
createNavRow(`rb-flex-1 rb-justify-center ${desktopOnlyDisplay("flex")} rb-gap-6`, "center"),
|
|
24282
|
-
headerCta
|
|
24283
|
-
], whenTransformed("$root.theme.header", "layout.classicNavMode", "centered"));
|
|
26165
|
+
], when("$root.theme.header.variant", { equals: "classic" }));
|
|
24284
26166
|
const centeredLayout = stack({
|
|
24285
26167
|
gap: "md",
|
|
24286
26168
|
align: "center",
|
|
@@ -24345,7 +26227,6 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
|
|
|
24345
26227
|
}, [
|
|
24346
26228
|
mobileHeaderBar,
|
|
24347
26229
|
classicLayout,
|
|
24348
|
-
classicCenteredNavLayout,
|
|
24349
26230
|
centeredLayout,
|
|
24350
26231
|
floatingLayout,
|
|
24351
26232
|
mobileOverlay
|
|
@@ -26299,83 +28180,6 @@ const weeklySlotAvailabilityBlockDefinition = {
|
|
|
26299
28180
|
} }
|
|
26300
28181
|
};
|
|
26301
28182
|
//#endregion
|
|
26302
|
-
//#region ../blocks/src/lib/media.ts
|
|
26303
|
-
const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
|
|
26304
|
-
"document",
|
|
26305
|
-
"spreadsheet",
|
|
26306
|
-
"archive",
|
|
26307
|
-
"audio"
|
|
26308
|
-
];
|
|
26309
|
-
//#endregion
|
|
26310
|
-
//#region ../blocks/src/system/manifest/richTextSchema.ts
|
|
26311
|
-
/**
|
|
26312
|
-
* Shared Rich Text Schema
|
|
26313
|
-
*
|
|
26314
|
-
* This module provides a single source of truth for TipTap rich text validation
|
|
26315
|
-
* across both the block-form editor and the block rendering system.
|
|
26316
|
-
*
|
|
26317
|
-
* Rich-text fields use one canonical root shape:
|
|
26318
|
-
* `{ type: 'doc', content: [...] }`.
|
|
26319
|
-
*/
|
|
26320
|
-
/**
|
|
26321
|
-
* TipTap document node schema (recursive structure)
|
|
26322
|
-
*
|
|
26323
|
-
* Supports the full TipTap document structure including:
|
|
26324
|
-
* - type: Node type (e.g., 'doc', 'paragraph', 'text')
|
|
26325
|
-
* - content: Nested array of child nodes
|
|
26326
|
-
* - text: Text content for text nodes
|
|
26327
|
-
* - attrs: Node attributes (e.g., alignment, color)
|
|
26328
|
-
* - marks: Text formatting marks (e.g., bold, italic)
|
|
26329
|
-
*/
|
|
26330
|
-
const TipTapMarkSchema = z.object({
|
|
26331
|
-
type: z.string().min(1),
|
|
26332
|
-
attrs: z.record(z.string(), z.unknown()).optional()
|
|
26333
|
-
}).strict();
|
|
26334
|
-
const TipTapNodeSchema = z.lazy(() => z.object({
|
|
26335
|
-
type: z.string().min(1),
|
|
26336
|
-
content: z.array(TipTapNodeSchema).optional(),
|
|
26337
|
-
text: z.string().optional(),
|
|
26338
|
-
attrs: z.record(z.string(), z.unknown()).optional(),
|
|
26339
|
-
marks: z.array(TipTapMarkSchema).optional()
|
|
26340
|
-
}).strict().superRefine((node, ctx) => {
|
|
26341
|
-
if (node.type === "doc") ctx.addIssue({
|
|
26342
|
-
code: "custom",
|
|
26343
|
-
path: ["type"],
|
|
26344
|
-
message: "Document nodes are only valid at the rich-text root"
|
|
26345
|
-
});
|
|
26346
|
-
if (node.type === "text") {
|
|
26347
|
-
if (node.text === void 0 || node.text.length === 0) ctx.addIssue({
|
|
26348
|
-
code: "custom",
|
|
26349
|
-
path: ["text"],
|
|
26350
|
-
message: "Text nodes require a non-empty text value"
|
|
26351
|
-
});
|
|
26352
|
-
if (node.content !== void 0) ctx.addIssue({
|
|
26353
|
-
code: "custom",
|
|
26354
|
-
path: ["content"],
|
|
26355
|
-
message: "Text nodes cannot contain child nodes"
|
|
26356
|
-
});
|
|
26357
|
-
return;
|
|
26358
|
-
}
|
|
26359
|
-
if (node.text !== void 0) ctx.addIssue({
|
|
26360
|
-
code: "custom",
|
|
26361
|
-
path: ["text"],
|
|
26362
|
-
message: "Only text nodes can contain a text value"
|
|
26363
|
-
});
|
|
26364
|
-
}));
|
|
26365
|
-
/**
|
|
26366
|
-
* Canonical schema for a TipTap rich-text document root.
|
|
26367
|
-
*
|
|
26368
|
-
* Stricter than {@link TipTapNodeSchema}: `type` is literally `'doc'` and
|
|
26369
|
-
* `content` is required (possibly empty). This is the shape every producer
|
|
26370
|
-
* (dummy content, editor output, migrations) must emit, and the shape every
|
|
26371
|
-
* non-legacy consumer can rely on.
|
|
26372
|
-
*
|
|
26373
|
-
*/
|
|
26374
|
-
const RichTextDocSchema = z.object({
|
|
26375
|
-
type: z.literal("doc"),
|
|
26376
|
-
content: z.array(TipTapNodeSchema)
|
|
26377
|
-
}).strict();
|
|
26378
|
-
//#endregion
|
|
26379
28183
|
//#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
|
|
26380
28184
|
const bookingDepositRefundPolicySchema$1 = z.enum(["refundable", "non_refundable"]);
|
|
26381
28185
|
const bookingInstalmentPlanSchema$1 = z.union([
|
|
@@ -27371,11 +29175,11 @@ function planEventRegistrationScope(input) {
|
|
|
27371
29175
|
}
|
|
27372
29176
|
//#endregion
|
|
27373
29177
|
//#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
|
|
27374
|
-
function isRecord$
|
|
29178
|
+
function isRecord$9(value) {
|
|
27375
29179
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27376
29180
|
}
|
|
27377
29181
|
function isRuntimeEventDestination(value) {
|
|
27378
|
-
if (!isRecord$
|
|
29182
|
+
if (!isRecord$9(value) || typeof value.kind !== "string") return false;
|
|
27379
29183
|
if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
|
|
27380
29184
|
return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
|
|
27381
29185
|
}
|
|
@@ -27438,15 +29242,15 @@ function resolveRuntimeEventPricing(event) {
|
|
|
27438
29242
|
function readCurrency(value) {
|
|
27439
29243
|
return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
|
|
27440
29244
|
}
|
|
27441
|
-
function isRecord$
|
|
29245
|
+
function isRecord$8(value) {
|
|
27442
29246
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27443
29247
|
}
|
|
27444
29248
|
function isPublicEventPricing(value) {
|
|
27445
|
-
if (!isRecord$
|
|
29249
|
+
if (!isRecord$8(value) || typeof value.kind !== "string") return false;
|
|
27446
29250
|
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "whole_series" || value.kind === "external";
|
|
27447
29251
|
}
|
|
27448
29252
|
function isPublicEventTicketType(value) {
|
|
27449
|
-
return isRecord$
|
|
29253
|
+
return isRecord$8(value) && typeof value.id === "string";
|
|
27450
29254
|
}
|
|
27451
29255
|
function readTicketTypePriceDisplay(value, currency) {
|
|
27452
29256
|
const display = readLegacyPriceDisplay(value, currency);
|
|
@@ -27456,7 +29260,7 @@ function readTicketTypePriceDisplay(value, currency) {
|
|
|
27456
29260
|
} : display;
|
|
27457
29261
|
}
|
|
27458
29262
|
function readLegacyPriceDisplay(value, currency) {
|
|
27459
|
-
if (!isRecord$
|
|
29263
|
+
if (!isRecord$8(value) || typeof value.kind !== "string") return {
|
|
27460
29264
|
kind: "unavailable",
|
|
27461
29265
|
currency
|
|
27462
29266
|
};
|
|
@@ -27508,7 +29312,7 @@ function readLegacyPriceDisplay(value, currency) {
|
|
|
27508
29312
|
kind: "unavailable",
|
|
27509
29313
|
currency: displayCurrency
|
|
27510
29314
|
};
|
|
27511
|
-
case "whole_series": return isRecord$
|
|
29315
|
+
case "whole_series": return isRecord$8(value.display) ? {
|
|
27512
29316
|
kind: "whole_series",
|
|
27513
29317
|
display: readCoursePriceDisplay(value.display, displayCurrency)
|
|
27514
29318
|
} : {
|
|
@@ -27969,14 +29773,14 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
|
27969
29773
|
}
|
|
27970
29774
|
});
|
|
27971
29775
|
function normalizeEventRegistrationEventInput(value) {
|
|
27972
|
-
if (!isRecord$
|
|
29776
|
+
if (!isRecord$7(value)) return value;
|
|
27973
29777
|
return {
|
|
27974
29778
|
...value,
|
|
27975
29779
|
destination: resolveRuntimeEventDestination(value),
|
|
27976
29780
|
pricing: resolveRuntimeEventPricing(value)
|
|
27977
29781
|
};
|
|
27978
29782
|
}
|
|
27979
|
-
function isRecord$
|
|
29783
|
+
function isRecord$7(value) {
|
|
27980
29784
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27981
29785
|
}
|
|
27982
29786
|
const eventRegistrationBlockDefinition = {
|
|
@@ -28750,7 +30554,8 @@ const eventCollectionSourceSchemaShape = {
|
|
|
28750
30554
|
buttonVariant: eventButtonVariantSchema.optional(),
|
|
28751
30555
|
buttonText: z.string().optional(),
|
|
28752
30556
|
emptyMessage: z.string().optional(),
|
|
28753
|
-
className: z.string().optional()
|
|
30557
|
+
className: z.string().optional(),
|
|
30558
|
+
bookingTimeZone: z.string().optional()
|
|
28754
30559
|
};
|
|
28755
30560
|
const eventCollectionDisplaySchemaShape = {
|
|
28756
30561
|
events: z.array(publicEventSchema),
|
|
@@ -28785,7 +30590,15 @@ const eventCollectionHydrationSchema = z.object({
|
|
|
28785
30590
|
prefetchedEvents: z.boolean(),
|
|
28786
30591
|
eventSurface: eventSurfaceScopeSchema$1,
|
|
28787
30592
|
filterEventPresets: z.string().nullable(),
|
|
28788
|
-
scheduleScope: eventScheduleScopeSchema$1
|
|
30593
|
+
scheduleScope: eventScheduleScopeSchema$1,
|
|
30594
|
+
calendarContext: z.object({
|
|
30595
|
+
timeZone: z.string().transform(toBookingTimeZone),
|
|
30596
|
+
initialToday: z.object({
|
|
30597
|
+
year: z.number().int(),
|
|
30598
|
+
month: z.number().int().min(1).max(12),
|
|
30599
|
+
day: z.number().int().min(1).max(31)
|
|
30600
|
+
})
|
|
30601
|
+
})
|
|
28789
30602
|
});
|
|
28790
30603
|
function buildEventCollectionDisplay(source) {
|
|
28791
30604
|
return {
|
|
@@ -28830,14 +30643,19 @@ function buildEventCollectionPresentationDisplay(source) {
|
|
|
28830
30643
|
emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
|
|
28831
30644
|
};
|
|
28832
30645
|
}
|
|
28833
|
-
function buildEventCollectionHydration(source) {
|
|
30646
|
+
function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
|
|
30647
|
+
const timeZone = toBookingTimeZone(source.bookingTimeZone);
|
|
28834
30648
|
return {
|
|
28835
30649
|
siteId: source.siteId,
|
|
28836
30650
|
stage: source.stage,
|
|
28837
30651
|
prefetchedEvents: source.events != null,
|
|
28838
30652
|
eventSurface: normalizeEventSurfaceScope(source.eventSurface),
|
|
28839
30653
|
filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
|
|
28840
|
-
scheduleScope: normalizeEventScheduleScope(source.scheduleScope)
|
|
30654
|
+
scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
|
|
30655
|
+
calendarContext: {
|
|
30656
|
+
timeZone,
|
|
30657
|
+
initialToday: getLocalScheduleDate(now, timeZone)
|
|
30658
|
+
}
|
|
28841
30659
|
};
|
|
28842
30660
|
}
|
|
28843
30661
|
//#endregion
|
|
@@ -30828,7 +32646,7 @@ function inferLegacyOfferingsPreviewGroupOrder(overrides) {
|
|
|
30828
32646
|
return keys.length >= 2 ? keys : [];
|
|
30829
32647
|
}
|
|
30830
32648
|
function normalizeOfferingsPreviewContentForWrite(value) {
|
|
30831
|
-
if (!isRecord$
|
|
32649
|
+
if (!isRecord$6(value)) return null;
|
|
30832
32650
|
const groupOrderValue = value.groupOrder;
|
|
30833
32651
|
if (Array.isArray(groupOrderValue)) {
|
|
30834
32652
|
const normalized = normalizeOfferingsPreviewGroupOrder(groupOrderValue);
|
|
@@ -30841,7 +32659,7 @@ function normalizeOfferingsPreviewContentForWrite(value) {
|
|
|
30841
32659
|
...value,
|
|
30842
32660
|
groupOrder: []
|
|
30843
32661
|
};
|
|
30844
|
-
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$
|
|
32662
|
+
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$6) : []);
|
|
30845
32663
|
return legacyOrder.length > 0 ? {
|
|
30846
32664
|
...value,
|
|
30847
32665
|
groupOrder: legacyOrder
|
|
@@ -30855,7 +32673,7 @@ function uniqueOfferingsPreviewSourceKeys(values) {
|
|
|
30855
32673
|
}
|
|
30856
32674
|
return keys;
|
|
30857
32675
|
}
|
|
30858
|
-
function isRecord$
|
|
32676
|
+
function isRecord$6(value) {
|
|
30859
32677
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30860
32678
|
}
|
|
30861
32679
|
//#endregion
|
|
@@ -31233,7 +33051,7 @@ function isOfferingsPreviewItemLimit(value) {
|
|
|
31233
33051
|
return value === "1" || value === "2" || value === "3" || value === "4" || value === "5" || value === "6" || value === null;
|
|
31234
33052
|
}
|
|
31235
33053
|
function normalizeOfferingsPreviewGroupOverride(value) {
|
|
31236
|
-
if (!isRecord$
|
|
33054
|
+
if (!isRecord$5(value)) return [];
|
|
31237
33055
|
const override = {};
|
|
31238
33056
|
if (isOfferingsPreviewSourceKey(value.sourceKey) || value.sourceKey === null) override.sourceKey = value.sourceKey;
|
|
31239
33057
|
if (typeof value.title === "string" || value.title === null) override.title = value.title;
|
|
@@ -31256,7 +33074,7 @@ function normalizeSectionStylesContent(value) {
|
|
|
31256
33074
|
}
|
|
31257
33075
|
function normalizeBoxStylesContent(value) {
|
|
31258
33076
|
if (value === null) return null;
|
|
31259
|
-
if (!isRecord$
|
|
33077
|
+
if (!isRecord$5(value)) return void 0;
|
|
31260
33078
|
const { background: _background, ...rest } = value;
|
|
31261
33079
|
const background = parseBackgroundContent(value.background);
|
|
31262
33080
|
return {
|
|
@@ -31264,7 +33082,7 @@ function normalizeBoxStylesContent(value) {
|
|
|
31264
33082
|
...background ? { background } : {}
|
|
31265
33083
|
};
|
|
31266
33084
|
}
|
|
31267
|
-
function isRecord$
|
|
33085
|
+
function isRecord$5(value) {
|
|
31268
33086
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31269
33087
|
}
|
|
31270
33088
|
const embedManifest = createBlockManifest({
|
|
@@ -34485,6 +36303,23 @@ function deriveNewsletterSignupRuntimeSource(values) {
|
|
|
34485
36303
|
tags: parseTrimmedString(normalized.tags)
|
|
34486
36304
|
};
|
|
34487
36305
|
}
|
|
36306
|
+
function sanitizeNewsletterSignupPublicContent(content) {
|
|
36307
|
+
if (!isRecord$4(content)) return content;
|
|
36308
|
+
const provider = parseNewsletterSignupDestinationProvider(content.destinationProvider) ?? getProviderFromExplicitDestination(content.destination);
|
|
36309
|
+
const { destination: _destination, destinationProvider: _destinationProvider, mailchimpAudienceId: _mailchimpAudienceId, mailchimpTags: _mailchimpTags, listId, tags, ...publicContent } = content;
|
|
36310
|
+
const mutablePublicContent = { ...publicContent };
|
|
36311
|
+
if (provider !== "mailchimp") {
|
|
36312
|
+
if ("listId" in content) mutablePublicContent.listId = listId;
|
|
36313
|
+
if ("tags" in content) mutablePublicContent.tags = tags;
|
|
36314
|
+
}
|
|
36315
|
+
return mutablePublicContent;
|
|
36316
|
+
}
|
|
36317
|
+
function getProviderFromExplicitDestination(destination) {
|
|
36318
|
+
if (!isRecord$4(destination) || typeof destination.tag !== "string") return null;
|
|
36319
|
+
if (destination.tag === "riverbank_list") return "riverbank";
|
|
36320
|
+
if (destination.tag === "mailchimp_audience") return "mailchimp";
|
|
36321
|
+
return null;
|
|
36322
|
+
}
|
|
34488
36323
|
const BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
|
|
34489
36324
|
const SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
|
|
34490
36325
|
function parseTrimmedString(value) {
|
|
@@ -34492,6 +36327,9 @@ function parseTrimmedString(value) {
|
|
|
34492
36327
|
const trimmed = value.trim();
|
|
34493
36328
|
return trimmed.length > 0 ? trimmed : null;
|
|
34494
36329
|
}
|
|
36330
|
+
function isRecord$4(value) {
|
|
36331
|
+
return typeof value === "object" && value !== null;
|
|
36332
|
+
}
|
|
34495
36333
|
//#endregion
|
|
34496
36334
|
//#region ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
|
|
34497
36335
|
/**
|
|
@@ -34727,7 +36565,7 @@ function projectNewsletterFormHydrationTarget(source) {
|
|
|
34727
36565
|
tag: "legacy-direct-list",
|
|
34728
36566
|
listId: source.listId
|
|
34729
36567
|
};
|
|
34730
|
-
default: return assertNever$
|
|
36568
|
+
default: return assertNever$3(source);
|
|
34731
36569
|
}
|
|
34732
36570
|
}
|
|
34733
36571
|
function parseRequiredNewsletterSignupBlockId(value) {
|
|
@@ -36905,7 +38743,7 @@ function isNonProductionEnv() {
|
|
|
36905
38743
|
//#region ../blocks/src/system/data/linkedContentEntries.ts
|
|
36906
38744
|
const LINKED_CONTENT_ENTRY_META_KEY = "__rbLinkedContentEntry";
|
|
36907
38745
|
function coerceLinkedContentEntriesPayload(payload) {
|
|
36908
|
-
if (!isRecord$
|
|
38746
|
+
if (!isRecord$3(payload)) return payload;
|
|
36909
38747
|
const response = payload;
|
|
36910
38748
|
if (!Array.isArray(response.entries)) return payload;
|
|
36911
38749
|
const contentType = parsePublicContentTypeMeta(response.contentType);
|
|
@@ -36913,12 +38751,12 @@ function coerceLinkedContentEntriesPayload(payload) {
|
|
|
36913
38751
|
return response.entries.map((entry) => enrichLinkedContentEntry(entry, contentType));
|
|
36914
38752
|
}
|
|
36915
38753
|
function enrichLinkedContentEntry(entry, contentType) {
|
|
36916
|
-
if (!isRecord$
|
|
38754
|
+
if (!isRecord$3(entry)) return entry;
|
|
36917
38755
|
const entryId = typeof entry.id === "string" ? entry.id : null;
|
|
36918
38756
|
if (!entryId) return entry;
|
|
36919
38757
|
const title = typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title : entryId;
|
|
36920
38758
|
const optimisticHash = typeof entry.optimisticHash === "string" && entry.optimisticHash.length > 0 ? entry.optimisticHash : null;
|
|
36921
|
-
const content = isRecord$
|
|
38759
|
+
const content = isRecord$3(entry.content) ? entry.content : {};
|
|
36922
38760
|
const meta = {
|
|
36923
38761
|
kind: "linked-content-entry",
|
|
36924
38762
|
entryId,
|
|
@@ -37001,7 +38839,7 @@ function resolveLinkedContentEditSupport(contentType) {
|
|
|
37001
38839
|
kind: "unsupported-domain-backed",
|
|
37002
38840
|
reason: metadata.reason
|
|
37003
38841
|
};
|
|
37004
|
-
default: return assertNever$
|
|
38842
|
+
default: return assertNever$3(metadata);
|
|
37005
38843
|
}
|
|
37006
38844
|
}
|
|
37007
38845
|
function contentTypeKeyToLabel(key) {
|
|
@@ -37011,7 +38849,7 @@ function capitalize(value) {
|
|
|
37011
38849
|
return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
|
|
37012
38850
|
}
|
|
37013
38851
|
function parsePublicContentTypeMeta(value) {
|
|
37014
|
-
if (!isRecord$
|
|
38852
|
+
if (!isRecord$3(value)) return null;
|
|
37015
38853
|
if (typeof value.key !== "string" || value.key.trim().length === 0) return null;
|
|
37016
38854
|
return {
|
|
37017
38855
|
key: value.key,
|
|
@@ -37021,7 +38859,7 @@ function parsePublicContentTypeMeta(value) {
|
|
|
37021
38859
|
};
|
|
37022
38860
|
}
|
|
37023
38861
|
function parsePublicContentTypeLinkedEntryEditing(value) {
|
|
37024
|
-
if (!isRecord$
|
|
38862
|
+
if (!isRecord$3(value) || typeof value.kind !== "string") return null;
|
|
37025
38863
|
switch (value.kind) {
|
|
37026
38864
|
case "generic": return { kind: "generic" };
|
|
37027
38865
|
case "unsupported-domain-backed": return {
|
|
@@ -37032,7 +38870,7 @@ function parsePublicContentTypeLinkedEntryEditing(value) {
|
|
|
37032
38870
|
}
|
|
37033
38871
|
}
|
|
37034
38872
|
function parsePublicContentTypeFieldMeta(value) {
|
|
37035
|
-
if (!isRecord$
|
|
38873
|
+
if (!isRecord$3(value)) return [];
|
|
37036
38874
|
if (typeof value.id !== "string" || typeof value.type !== "string") return [];
|
|
37037
38875
|
return [{
|
|
37038
38876
|
id: value.id,
|
|
@@ -37046,7 +38884,7 @@ function parseStringArray(value) {
|
|
|
37046
38884
|
if (!Array.isArray(value)) return null;
|
|
37047
38885
|
return value.filter((item) => typeof item === "string");
|
|
37048
38886
|
}
|
|
37049
|
-
function isRecord$
|
|
38887
|
+
function isRecord$3(value) {
|
|
37050
38888
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37051
38889
|
}
|
|
37052
38890
|
//#endregion
|
|
@@ -37067,10 +38905,10 @@ function normalizeDataLoaders(def) {
|
|
|
37067
38905
|
*/
|
|
37068
38906
|
function normalizeContent(block) {
|
|
37069
38907
|
const source = block.draftContent ?? block.content ?? block.publishedContent ?? {};
|
|
37070
|
-
if (!isObjectRecord(source)) return {};
|
|
38908
|
+
if (!isObjectRecord$1(source)) return {};
|
|
37071
38909
|
if ("data" in source) {
|
|
37072
38910
|
const data = source.data;
|
|
37073
|
-
if (isObjectRecord(data)) return data;
|
|
38911
|
+
if (isObjectRecord$1(data)) return data;
|
|
37074
38912
|
if (data === null || data === void 0) return {};
|
|
37075
38913
|
}
|
|
37076
38914
|
return source;
|
|
@@ -37253,7 +39091,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
|
|
|
37253
39091
|
//#endregion
|
|
37254
39092
|
//#region ../blocks/src/system/data/normalizeLoaderParams.ts
|
|
37255
39093
|
function toStringParams(value) {
|
|
37256
|
-
if (!isObjectRecord(value)) return {};
|
|
39094
|
+
if (!isObjectRecord$1(value)) return {};
|
|
37257
39095
|
const out = {};
|
|
37258
39096
|
for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
|
|
37259
39097
|
return out;
|
|
@@ -37851,7 +39689,7 @@ function describeSiteVerticalConfigIssue(issue) {
|
|
|
37851
39689
|
case "duplicate_preset_id":
|
|
37852
39690
|
case "duplicate_canonical_behaviour":
|
|
37853
39691
|
case "future_preset_selected": return issue.code;
|
|
37854
|
-
default: return assertNever$
|
|
39692
|
+
default: return assertNever$3(issue);
|
|
37855
39693
|
}
|
|
37856
39694
|
}
|
|
37857
39695
|
const VerticalIdSchema = z.string().trim().transform((value, ctx) => {
|
|
@@ -37892,7 +39730,7 @@ z.object({
|
|
|
37892
39730
|
});
|
|
37893
39731
|
//#endregion
|
|
37894
39732
|
//#region ../api/src/utils/isRecord.ts
|
|
37895
|
-
function isRecord$
|
|
39733
|
+
function isRecord$2(value) {
|
|
37896
39734
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37897
39735
|
}
|
|
37898
39736
|
//#endregion
|
|
@@ -38141,7 +39979,7 @@ function sanitizeMarks(marks) {
|
|
|
38141
39979
|
if (!Array.isArray(marks) || marks.length === 0) return;
|
|
38142
39980
|
const sanitized = marks.flatMap((mark) => {
|
|
38143
39981
|
if (mark.type === "bold" || mark.type === "strong" || mark.type === "italic" || mark.type === "em") return [{ type: mark.type }];
|
|
38144
|
-
if (mark.type === "link" && isRecord$
|
|
39982
|
+
if (mark.type === "link" && isRecord$2(mark.attrs) && typeof mark.attrs.href === "string") {
|
|
38145
39983
|
const attrs = { href: mark.attrs.href };
|
|
38146
39984
|
if (typeof mark.attrs.target === "string" && mark.attrs.target.trim().length > 0) attrs.target = mark.attrs.target;
|
|
38147
39985
|
if (typeof mark.attrs.rel === "string" && mark.attrs.rel.trim().length > 0) attrs.rel = mark.attrs.rel;
|
|
@@ -38336,7 +40174,7 @@ const ENTRY_REF_KEYS = [
|
|
|
38336
40174
|
"entryId",
|
|
38337
40175
|
"slug"
|
|
38338
40176
|
];
|
|
38339
|
-
function isRecord(value) {
|
|
40177
|
+
function isRecord$1(value) {
|
|
38340
40178
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
38341
40179
|
}
|
|
38342
40180
|
function extractManualEntryRef(item) {
|
|
@@ -38344,7 +40182,7 @@ function extractManualEntryRef(item) {
|
|
|
38344
40182
|
const trimmed = item.trim();
|
|
38345
40183
|
return trimmed.length > 0 ? trimmed : null;
|
|
38346
40184
|
}
|
|
38347
|
-
if (!isRecord(item)) return null;
|
|
40185
|
+
if (!isRecord$1(item)) return null;
|
|
38348
40186
|
for (const key of ENTRY_REF_KEYS) {
|
|
38349
40187
|
const raw = item[key];
|
|
38350
40188
|
if (typeof raw === "string" && raw.trim().length > 0) return raw.trim();
|
|
@@ -38649,6 +40487,126 @@ function requireSdkTheme(theme, siteId, reason = "cms_theme_absent") {
|
|
|
38649
40487
|
return theme;
|
|
38650
40488
|
}
|
|
38651
40489
|
//#endregion
|
|
40490
|
+
//#region src/rendering/helpers/siteCustomBlocks.ts
|
|
40491
|
+
/**
|
|
40492
|
+
* Prefer the DB-backed custom block manifest list (`site.customBlocks`) when available,
|
|
40493
|
+
* but fall back to SDK config custom blocks (`site.sdkConfig.customBlocks`) for SDK-mode sites.
|
|
40494
|
+
*
|
|
40495
|
+
* This avoids subtle DX bugs where one source is populated but the renderer/prefetch layer
|
|
40496
|
+
* is looking at the other.
|
|
40497
|
+
*/
|
|
40498
|
+
function resolveSiteCustomBlocks(site) {
|
|
40499
|
+
const dbBlocks = site.customBlocks;
|
|
40500
|
+
if (Array.isArray(dbBlocks) && dbBlocks.length > 0) return dbBlocks;
|
|
40501
|
+
const sdkBlocks = site.sdkConfig?.customBlocks;
|
|
40502
|
+
if (Array.isArray(sdkBlocks) && sdkBlocks.length > 0) return sdkBlocks;
|
|
40503
|
+
}
|
|
40504
|
+
//#endregion
|
|
40505
|
+
//#region src/rendering/helpers/pageRuntimeSupport.ts
|
|
40506
|
+
function convertPageResponseBlock(block) {
|
|
40507
|
+
if (!isRecord(block)) throw new Error("Invalid block format in page API response");
|
|
40508
|
+
if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
|
|
40509
|
+
if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
|
|
40510
|
+
if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
|
|
40511
|
+
const admission = readInvalidBlockAdmission(block.admission);
|
|
40512
|
+
return {
|
|
40513
|
+
id: block.id,
|
|
40514
|
+
kind: block.kind,
|
|
40515
|
+
purpose: block.purpose,
|
|
40516
|
+
content: sanitizeSdkRuntimeBlockContent(block.kind, readContentRecord(block.content) ?? {}),
|
|
40517
|
+
draftContent: sanitizeNullableSdkRuntimeBlockContent(block.kind, readNestedContentRecord(block.draftContent)),
|
|
40518
|
+
...admission ? { admission } : {}
|
|
40519
|
+
};
|
|
40520
|
+
}
|
|
40521
|
+
function readInvalidBlockAdmission(value) {
|
|
40522
|
+
if (!isRecord(value) || value.kind !== "invalid" || !isRecord(value.error)) return null;
|
|
40523
|
+
if (value.error.kind !== "invalid_manifest_content" && value.error.kind !== "manifest_unavailable") return null;
|
|
40524
|
+
return value;
|
|
40525
|
+
}
|
|
40526
|
+
function buildPageOutline(input) {
|
|
40527
|
+
return {
|
|
40528
|
+
name: input.name,
|
|
40529
|
+
path: input.path ?? input.fallbackPath,
|
|
40530
|
+
purpose: input.purpose,
|
|
40531
|
+
blocks: input.blocks.map(convertPageResponseBlock)
|
|
40532
|
+
};
|
|
40533
|
+
}
|
|
40534
|
+
function buildRenderablePageOutline(input) {
|
|
40535
|
+
const page = buildPageOutline(input);
|
|
40536
|
+
return {
|
|
40537
|
+
...page,
|
|
40538
|
+
blocks: page.blocks.map((block) => admitSdkRuntimePageBlock(block, input.customBlocks))
|
|
40539
|
+
};
|
|
40540
|
+
}
|
|
40541
|
+
function projectRenderablePageOutline(page) {
|
|
40542
|
+
return {
|
|
40543
|
+
...page,
|
|
40544
|
+
blocks: page.blocks.flatMap((block) => block.admission.kind === "renderable" ? [{
|
|
40545
|
+
id: block.id,
|
|
40546
|
+
kind: block.kind,
|
|
40547
|
+
purpose: block.purpose,
|
|
40548
|
+
content: block.admission.content,
|
|
40549
|
+
...block.bindings ? { bindings: block.bindings } : {}
|
|
40550
|
+
}] : [])
|
|
40551
|
+
};
|
|
40552
|
+
}
|
|
40553
|
+
function admitSdkRuntimePageBlock(block, customBlocks) {
|
|
40554
|
+
const base = {
|
|
40555
|
+
id: block.id,
|
|
40556
|
+
kind: block.kind,
|
|
40557
|
+
purpose: block.purpose,
|
|
40558
|
+
...block.bindings ? { bindings: block.bindings } : {}
|
|
40559
|
+
};
|
|
40560
|
+
const transportedAdmission = readInvalidBlockAdmission(block.admission);
|
|
40561
|
+
if (transportedAdmission) return invalidRenderableBlock(base, transportedAdmission.error);
|
|
40562
|
+
const manifest = resolveSdkBlockManifest(block.kind, customBlocks);
|
|
40563
|
+
if (!manifest) return invalidRenderableBlock(base, { kind: "manifest_unavailable" });
|
|
40564
|
+
const content = block.content ?? {};
|
|
40565
|
+
const renderable = admitTransportedRenderableManifestContent(compileManifestContentContract(manifest), content);
|
|
40566
|
+
if (!renderable.ok) return invalidRenderableBlock(base, {
|
|
40567
|
+
kind: "invalid_manifest_content",
|
|
40568
|
+
error: renderable.error
|
|
40569
|
+
});
|
|
40570
|
+
return {
|
|
40571
|
+
...base,
|
|
40572
|
+
admission: {
|
|
40573
|
+
kind: "renderable",
|
|
40574
|
+
content: renderable.value
|
|
40575
|
+
}
|
|
40576
|
+
};
|
|
40577
|
+
}
|
|
40578
|
+
function resolveSdkBlockManifest(blockKind, customBlocks) {
|
|
40579
|
+
const customBlock = customBlocks?.find((candidate) => candidate.id === blockKind);
|
|
40580
|
+
return customBlock ? parseFieldDefinitions(customBlock.fields) : getBlockDefinition(blockKind)?.manifest ?? null;
|
|
40581
|
+
}
|
|
40582
|
+
function invalidRenderableBlock(block, error) {
|
|
40583
|
+
return {
|
|
40584
|
+
...block,
|
|
40585
|
+
admission: {
|
|
40586
|
+
kind: "invalid",
|
|
40587
|
+
error
|
|
40588
|
+
}
|
|
40589
|
+
};
|
|
40590
|
+
}
|
|
40591
|
+
function isRecord(value) {
|
|
40592
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
40593
|
+
}
|
|
40594
|
+
function readContentRecord(value) {
|
|
40595
|
+
return isRecord(value) ? value : void 0;
|
|
40596
|
+
}
|
|
40597
|
+
function readNestedContentRecord(value) {
|
|
40598
|
+
if (!isRecord(value)) return null;
|
|
40599
|
+
return readContentRecord(value.data) ?? null;
|
|
40600
|
+
}
|
|
40601
|
+
function sanitizeSdkRuntimeBlockContent(blockKind, content) {
|
|
40602
|
+
if (blockKind !== "block.newsletter-signup") return content;
|
|
40603
|
+
const sanitized = sanitizeNewsletterSignupPublicContent(content);
|
|
40604
|
+
return isRecord(sanitized) ? sanitized : {};
|
|
40605
|
+
}
|
|
40606
|
+
function sanitizeNullableSdkRuntimeBlockContent(blockKind, content) {
|
|
40607
|
+
return content ? sanitizeSdkRuntimeBlockContent(blockKind, content) : null;
|
|
40608
|
+
}
|
|
40609
|
+
//#endregion
|
|
38652
40610
|
//#region src/rendering/hooks/usePage.ts
|
|
38653
40611
|
/**
|
|
38654
40612
|
* Client-side React hook to fetch page data.
|
|
@@ -38748,24 +40706,15 @@ function usePage(params) {
|
|
|
38748
40706
|
const { page: pageData } = pageResponse;
|
|
38749
40707
|
const canonicalPagePath = pageData.path ?? path;
|
|
38750
40708
|
const mediaAssets = Array.isArray(pageResponse.mediaAssets) && pageResponse.mediaAssets.length > 0 ? toMediaAssetSidecar(pageResponse.mediaAssets) : void 0;
|
|
38751
|
-
const
|
|
38752
|
-
if (!block || typeof block !== "object") throw new Error("Invalid block format in API response");
|
|
38753
|
-
if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id: expected string or null, got ${typeof block.id}`);
|
|
38754
|
-
if (typeof block.kind !== "string") throw new Error(`Invalid block kind: expected string, got ${typeof block.kind}`);
|
|
38755
|
-
if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose: expected string, got ${typeof block.purpose}`);
|
|
38756
|
-
return {
|
|
38757
|
-
id: block.id,
|
|
38758
|
-
kind: block.kind,
|
|
38759
|
-
purpose: block.purpose
|
|
38760
|
-
};
|
|
38761
|
-
});
|
|
38762
|
-
const pageOutline = {
|
|
40709
|
+
const pageOutline = buildRenderablePageOutline({
|
|
38763
40710
|
name: pageData.name,
|
|
38764
40711
|
path: canonicalPagePath,
|
|
40712
|
+
fallbackPath: path,
|
|
38765
40713
|
purpose: pageData.purpose,
|
|
38766
|
-
blocks
|
|
38767
|
-
|
|
38768
|
-
|
|
40714
|
+
blocks: pageData.blocks,
|
|
40715
|
+
customBlocks: resolveSiteCustomBlocks(site)
|
|
40716
|
+
});
|
|
40717
|
+
const resolvedData = await prefetchBlockData(projectRenderablePageOutline(pageOutline), {
|
|
38769
40718
|
siteId,
|
|
38770
40719
|
pageId: pageId ?? pageData.id,
|
|
38771
40720
|
previewStage: preview ? "preview" : "published"
|