@riverbankcms/sdk 0.135.0 → 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-roNY0GVy.mjs → PreviewEditorSidebar-BU5ZlhQR.mjs} +4 -4
- package/dist/{PreviewEditorUI-KboDbEh_.mjs → PreviewEditorUI-9XkHL-bC.mjs} +3 -3
- package/dist/{PreviewQueryProvider-DcgaESkm.mjs → PreviewQueryProvider-wbEpXryy.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-DBrF7Caa.mjs → SdkPreviewModeRuntime-CnWmj-2B.mjs} +50 -99
- package/dist/{SiteChromeCustomizeContext-DrIEpJKn.mjs → SiteChromeCustomizeContext-B6d5zkog.mjs} +2334 -1173
- 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/blocks/events/shared/schemas.d.ts +25 -0
- 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 +19 -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-BQqwi8Oa.mjs → BookingConsentAgreement-DCch21a6.mjs} +2 -2
- package/dist/client/{DiscountCodeDisclosure-B97aMo0V.mjs → DiscountCodeDisclosure-DIj1T59K.mjs} +1 -1
- package/dist/client/{EventCombined.client-Bs2Iw9Q6.mjs → EventCombined.client-BWVNlXTx.mjs} +226 -206
- package/dist/client/{EventListing.client-C4QUQdmg.mjs → EventListing.client-DVFCDe3i.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-CwWRk69M.mjs → LeafletStaticMap-BY5mIHw9.mjs} +1 -1
- package/dist/client/{accordion-BA0j8Mpw.mjs → accordion-CK29E8rG.mjs} +1 -1
- package/dist/client/{bookingForm-Br2e41H0.mjs → bookingForm-DFvnet-N.mjs} +5 -5
- package/dist/client/bookings.mjs +87 -47
- package/dist/client/{carousel-B4dmwnpD.mjs → carousel-BVU5NQlb.mjs} +1 -1
- package/dist/client/{cart-B_ckGW4b.mjs → cart-BNItcZVa.mjs} +3 -3
- package/dist/client/{checkout-DAyspHdf.mjs → checkout-Bu6iCdkP.mjs} +3 -3
- package/dist/client/client.mjs +1985 -1055
- package/dist/client/{context-DljQn8L5.mjs → context-BImarOAq.mjs} +12 -0
- package/dist/client/{eventCalendar-pJu3FUod.mjs → eventCalendar-DS2h-UXD.mjs} +256 -114
- package/dist/client/{eventCombined-B6Kacm9F.mjs → eventCombined-Drt4Oq9p.mjs} +3 -3
- package/dist/client/{eventDetails-CaX9z1pv.mjs → eventDetails-Bl2vWgTX.mjs} +4 -3
- package/dist/client/{eventListing-B9aXPO-I.mjs → eventListing-CS7PHY7v.mjs} +3 -3
- package/dist/client/{eventRegistration-CBSovBkg.mjs → eventRegistration-D-j8eNy2.mjs} +85 -41
- package/dist/client/{form-Cm0tu_7o.mjs → form-RMpoLTyr.mjs} +2 -2
- package/dist/client/{headerSection-OgRtHeKS.mjs → headerSection-BYE3Lb3k.mjs} +2 -2
- package/dist/client/hooks.mjs +2254 -298
- package/dist/client/{locationMap-DmjcYqNM.mjs → locationMap-BxSr7Kkh.mjs} +2 -2
- package/dist/client/{newsletterForm-D08OZQAC.mjs → newsletterForm-DerbXwFC.mjs} +2 -2
- package/dist/client/{productDetail-BqZeu2P4.mjs → productDetail-4SZCLhAf.mjs} +3 -3
- package/dist/client/{productList-mNyIF9FG.mjs → productList-D7AP4GNq.mjs} +3 -3
- package/dist/client/{propsDecoder-DwHXRm9X.mjs → propsDecoder-pzBeCh14.mjs} +123 -46
- package/dist/client/rendering/client.mjs +793 -488
- package/dist/client/rendering/islands.mjs +17 -17
- package/dist/client/rendering.mjs +2161 -1268
- package/dist/client/{scrollToBlock-DtmdM3v-.mjs → scrollToBlock-CduAKf8T.mjs} +1 -1
- package/dist/client/{shop-CNjZK16F.mjs → shop-Cp5p_kGe.mjs} +6 -6
- package/dist/client/{shop-commerce-DkNNao1J.mjs → shop-commerce-DicXYaYX.mjs} +5 -5
- package/dist/client/{shop-commerce-store-9WA--zuW.mjs → shop-commerce-store-CGWnpY4K.mjs} +1 -1
- package/dist/client/{shopShared-CHCVfccY.mjs → shopShared-BDf9ljkm.mjs} +3 -3
- package/dist/client/{useEventFilters-DvuaB4ZN.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-3GhW4knb.mjs → sdk-runtime-19MO27F0.mjs} +2 -2
- package/dist/{separator-D3bCWYYb.mjs → separator-DaPLtJ1f.mjs} +1 -1
- package/dist/server/components.mjs +1562 -917
- package/dist/server/config-validation.mjs +94 -135
- package/dist/server/config.mjs +94 -135
- package/dist/server/data.mjs +94 -134
- package/dist/server/index.mjs +122 -4
- package/dist/server/manifest.mjs +0 -1
- package/dist/server/next.mjs +1467 -732
- package/dist/server/page-converter.mjs +87 -113
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +1717 -939
- package/dist/server/rendering.mjs +1729 -1044
- package/dist/server/routing.mjs +3229 -1835
- package/dist/server/server.mjs +21739 -19801
- 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([
|
|
@@ -26799,6 +28603,7 @@ const publicWholeSeriesPriceDisplaySchema = z.discriminatedUnion("kind", [
|
|
|
26799
28603
|
freePriceDisplaySchema,
|
|
26800
28604
|
exactPriceDisplaySchema,
|
|
26801
28605
|
fromPriceDisplaySchema,
|
|
28606
|
+
rangePriceDisplaySchema,
|
|
26802
28607
|
unavailablePriceDisplaySchema
|
|
26803
28608
|
]);
|
|
26804
28609
|
z.discriminatedUnion("kind", [
|
|
@@ -27370,11 +29175,11 @@ function planEventRegistrationScope(input) {
|
|
|
27370
29175
|
}
|
|
27371
29176
|
//#endregion
|
|
27372
29177
|
//#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
|
|
27373
|
-
function isRecord$
|
|
29178
|
+
function isRecord$9(value) {
|
|
27374
29179
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27375
29180
|
}
|
|
27376
29181
|
function isRuntimeEventDestination(value) {
|
|
27377
|
-
if (!isRecord$
|
|
29182
|
+
if (!isRecord$9(value) || typeof value.kind !== "string") return false;
|
|
27378
29183
|
if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
|
|
27379
29184
|
return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
|
|
27380
29185
|
}
|
|
@@ -27437,15 +29242,15 @@ function resolveRuntimeEventPricing(event) {
|
|
|
27437
29242
|
function readCurrency(value) {
|
|
27438
29243
|
return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
|
|
27439
29244
|
}
|
|
27440
|
-
function isRecord$
|
|
29245
|
+
function isRecord$8(value) {
|
|
27441
29246
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27442
29247
|
}
|
|
27443
29248
|
function isPublicEventPricing(value) {
|
|
27444
|
-
if (!isRecord$
|
|
29249
|
+
if (!isRecord$8(value) || typeof value.kind !== "string") return false;
|
|
27445
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";
|
|
27446
29251
|
}
|
|
27447
29252
|
function isPublicEventTicketType(value) {
|
|
27448
|
-
return isRecord$
|
|
29253
|
+
return isRecord$8(value) && typeof value.id === "string";
|
|
27449
29254
|
}
|
|
27450
29255
|
function readTicketTypePriceDisplay(value, currency) {
|
|
27451
29256
|
const display = readLegacyPriceDisplay(value, currency);
|
|
@@ -27455,7 +29260,7 @@ function readTicketTypePriceDisplay(value, currency) {
|
|
|
27455
29260
|
} : display;
|
|
27456
29261
|
}
|
|
27457
29262
|
function readLegacyPriceDisplay(value, currency) {
|
|
27458
|
-
if (!isRecord$
|
|
29263
|
+
if (!isRecord$8(value) || typeof value.kind !== "string") return {
|
|
27459
29264
|
kind: "unavailable",
|
|
27460
29265
|
currency
|
|
27461
29266
|
};
|
|
@@ -27507,7 +29312,7 @@ function readLegacyPriceDisplay(value, currency) {
|
|
|
27507
29312
|
kind: "unavailable",
|
|
27508
29313
|
currency: displayCurrency
|
|
27509
29314
|
};
|
|
27510
|
-
case "whole_series": return isRecord$
|
|
29315
|
+
case "whole_series": return isRecord$8(value.display) ? {
|
|
27511
29316
|
kind: "whole_series",
|
|
27512
29317
|
display: readCoursePriceDisplay(value.display, displayCurrency)
|
|
27513
29318
|
} : {
|
|
@@ -27902,13 +29707,16 @@ function buildEventRegistrationShellStepLabels(source) {
|
|
|
27902
29707
|
}) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
|
|
27903
29708
|
}
|
|
27904
29709
|
function scopeEventRegistrationEvents(source) {
|
|
29710
|
+
return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
|
|
29711
|
+
}
|
|
29712
|
+
function scopeEventRegistrationSourceEvents(source) {
|
|
27905
29713
|
const scope = planEventRegistrationScope({
|
|
27906
|
-
events:
|
|
29714
|
+
events: source.events ?? [],
|
|
27907
29715
|
wholeSeriesOffering: source.wholeSeriesOffering,
|
|
27908
29716
|
occurrenceContext: source.occurrenceContext,
|
|
27909
29717
|
subject: source.subject
|
|
27910
29718
|
});
|
|
27911
|
-
return scope.kind === "invalidSelectedRun" ? [] : scope.events;
|
|
29719
|
+
return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
|
|
27912
29720
|
}
|
|
27913
29721
|
function shellLabelForRegistrationStep(step, events) {
|
|
27914
29722
|
switch (step) {
|
|
@@ -27940,36 +29748,39 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
|
27940
29748
|
source: createZodCodec(eventRegistrationSourceSchema),
|
|
27941
29749
|
render: createZodCodec(eventRegistrationRenderSchema)
|
|
27942
29750
|
},
|
|
27943
|
-
buildRender: (source) =>
|
|
27944
|
-
|
|
27945
|
-
|
|
27946
|
-
|
|
27947
|
-
|
|
27948
|
-
|
|
27949
|
-
|
|
27950
|
-
|
|
27951
|
-
|
|
27952
|
-
|
|
27953
|
-
|
|
27954
|
-
|
|
27955
|
-
|
|
27956
|
-
|
|
27957
|
-
|
|
27958
|
-
|
|
27959
|
-
|
|
27960
|
-
|
|
27961
|
-
|
|
27962
|
-
|
|
29751
|
+
buildRender: (source) => {
|
|
29752
|
+
const events = source.events == null ? null : scopeEventRegistrationSourceEvents(source);
|
|
29753
|
+
return {
|
|
29754
|
+
display: buildEventRegistrationDisplay(source),
|
|
29755
|
+
hydration: {
|
|
29756
|
+
occurrenceContext: source.occurrenceContext ?? null,
|
|
29757
|
+
subject: source.subject ?? null,
|
|
29758
|
+
events,
|
|
29759
|
+
wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
|
|
29760
|
+
wholeSeriesOffering: resolveWholeSeriesOffering(source),
|
|
29761
|
+
maxTickets: source.maxTickets ?? void 0,
|
|
29762
|
+
showVenue: source.showVenue,
|
|
29763
|
+
showCapacity: source.showCapacity,
|
|
29764
|
+
successMessage: source.successMessage,
|
|
29765
|
+
buttonVariant: source.buttonVariant,
|
|
29766
|
+
overlayEnabled: source.overlayEnabled,
|
|
29767
|
+
spamProtectionEnabled: source.spamProtectionEnabled,
|
|
29768
|
+
supportEmail: source.supportEmail,
|
|
29769
|
+
sitePasses: source.sitePasses ?? null,
|
|
29770
|
+
siteMemberships: source.siteMemberships ?? null
|
|
29771
|
+
}
|
|
29772
|
+
};
|
|
29773
|
+
}
|
|
27963
29774
|
});
|
|
27964
29775
|
function normalizeEventRegistrationEventInput(value) {
|
|
27965
|
-
if (!isRecord$
|
|
29776
|
+
if (!isRecord$7(value)) return value;
|
|
27966
29777
|
return {
|
|
27967
29778
|
...value,
|
|
27968
29779
|
destination: resolveRuntimeEventDestination(value),
|
|
27969
29780
|
pricing: resolveRuntimeEventPricing(value)
|
|
27970
29781
|
};
|
|
27971
29782
|
}
|
|
27972
|
-
function isRecord$
|
|
29783
|
+
function isRecord$7(value) {
|
|
27973
29784
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27974
29785
|
}
|
|
27975
29786
|
const eventRegistrationBlockDefinition = {
|
|
@@ -28743,7 +30554,8 @@ const eventCollectionSourceSchemaShape = {
|
|
|
28743
30554
|
buttonVariant: eventButtonVariantSchema.optional(),
|
|
28744
30555
|
buttonText: z.string().optional(),
|
|
28745
30556
|
emptyMessage: z.string().optional(),
|
|
28746
|
-
className: z.string().optional()
|
|
30557
|
+
className: z.string().optional(),
|
|
30558
|
+
bookingTimeZone: z.string().optional()
|
|
28747
30559
|
};
|
|
28748
30560
|
const eventCollectionDisplaySchemaShape = {
|
|
28749
30561
|
events: z.array(publicEventSchema),
|
|
@@ -28778,7 +30590,15 @@ const eventCollectionHydrationSchema = z.object({
|
|
|
28778
30590
|
prefetchedEvents: z.boolean(),
|
|
28779
30591
|
eventSurface: eventSurfaceScopeSchema$1,
|
|
28780
30592
|
filterEventPresets: z.string().nullable(),
|
|
28781
|
-
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
|
+
})
|
|
28782
30602
|
});
|
|
28783
30603
|
function buildEventCollectionDisplay(source) {
|
|
28784
30604
|
return {
|
|
@@ -28823,14 +30643,19 @@ function buildEventCollectionPresentationDisplay(source) {
|
|
|
28823
30643
|
emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
|
|
28824
30644
|
};
|
|
28825
30645
|
}
|
|
28826
|
-
function buildEventCollectionHydration(source) {
|
|
30646
|
+
function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
|
|
30647
|
+
const timeZone = toBookingTimeZone(source.bookingTimeZone);
|
|
28827
30648
|
return {
|
|
28828
30649
|
siteId: source.siteId,
|
|
28829
30650
|
stage: source.stage,
|
|
28830
30651
|
prefetchedEvents: source.events != null,
|
|
28831
30652
|
eventSurface: normalizeEventSurfaceScope(source.eventSurface),
|
|
28832
30653
|
filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
|
|
28833
|
-
scheduleScope: normalizeEventScheduleScope(source.scheduleScope)
|
|
30654
|
+
scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
|
|
30655
|
+
calendarContext: {
|
|
30656
|
+
timeZone,
|
|
30657
|
+
initialToday: getLocalScheduleDate(now, timeZone)
|
|
30658
|
+
}
|
|
28834
30659
|
};
|
|
28835
30660
|
}
|
|
28836
30661
|
//#endregion
|
|
@@ -30821,7 +32646,7 @@ function inferLegacyOfferingsPreviewGroupOrder(overrides) {
|
|
|
30821
32646
|
return keys.length >= 2 ? keys : [];
|
|
30822
32647
|
}
|
|
30823
32648
|
function normalizeOfferingsPreviewContentForWrite(value) {
|
|
30824
|
-
if (!isRecord$
|
|
32649
|
+
if (!isRecord$6(value)) return null;
|
|
30825
32650
|
const groupOrderValue = value.groupOrder;
|
|
30826
32651
|
if (Array.isArray(groupOrderValue)) {
|
|
30827
32652
|
const normalized = normalizeOfferingsPreviewGroupOrder(groupOrderValue);
|
|
@@ -30834,7 +32659,7 @@ function normalizeOfferingsPreviewContentForWrite(value) {
|
|
|
30834
32659
|
...value,
|
|
30835
32660
|
groupOrder: []
|
|
30836
32661
|
};
|
|
30837
|
-
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$
|
|
32662
|
+
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$6) : []);
|
|
30838
32663
|
return legacyOrder.length > 0 ? {
|
|
30839
32664
|
...value,
|
|
30840
32665
|
groupOrder: legacyOrder
|
|
@@ -30848,7 +32673,7 @@ function uniqueOfferingsPreviewSourceKeys(values) {
|
|
|
30848
32673
|
}
|
|
30849
32674
|
return keys;
|
|
30850
32675
|
}
|
|
30851
|
-
function isRecord$
|
|
32676
|
+
function isRecord$6(value) {
|
|
30852
32677
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30853
32678
|
}
|
|
30854
32679
|
//#endregion
|
|
@@ -31226,7 +33051,7 @@ function isOfferingsPreviewItemLimit(value) {
|
|
|
31226
33051
|
return value === "1" || value === "2" || value === "3" || value === "4" || value === "5" || value === "6" || value === null;
|
|
31227
33052
|
}
|
|
31228
33053
|
function normalizeOfferingsPreviewGroupOverride(value) {
|
|
31229
|
-
if (!isRecord$
|
|
33054
|
+
if (!isRecord$5(value)) return [];
|
|
31230
33055
|
const override = {};
|
|
31231
33056
|
if (isOfferingsPreviewSourceKey(value.sourceKey) || value.sourceKey === null) override.sourceKey = value.sourceKey;
|
|
31232
33057
|
if (typeof value.title === "string" || value.title === null) override.title = value.title;
|
|
@@ -31249,7 +33074,7 @@ function normalizeSectionStylesContent(value) {
|
|
|
31249
33074
|
}
|
|
31250
33075
|
function normalizeBoxStylesContent(value) {
|
|
31251
33076
|
if (value === null) return null;
|
|
31252
|
-
if (!isRecord$
|
|
33077
|
+
if (!isRecord$5(value)) return void 0;
|
|
31253
33078
|
const { background: _background, ...rest } = value;
|
|
31254
33079
|
const background = parseBackgroundContent(value.background);
|
|
31255
33080
|
return {
|
|
@@ -31257,7 +33082,7 @@ function normalizeBoxStylesContent(value) {
|
|
|
31257
33082
|
...background ? { background } : {}
|
|
31258
33083
|
};
|
|
31259
33084
|
}
|
|
31260
|
-
function isRecord$
|
|
33085
|
+
function isRecord$5(value) {
|
|
31261
33086
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31262
33087
|
}
|
|
31263
33088
|
const embedManifest = createBlockManifest({
|
|
@@ -34478,6 +36303,23 @@ function deriveNewsletterSignupRuntimeSource(values) {
|
|
|
34478
36303
|
tags: parseTrimmedString(normalized.tags)
|
|
34479
36304
|
};
|
|
34480
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
|
+
}
|
|
34481
36323
|
const BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
|
|
34482
36324
|
const SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
|
|
34483
36325
|
function parseTrimmedString(value) {
|
|
@@ -34485,6 +36327,9 @@ function parseTrimmedString(value) {
|
|
|
34485
36327
|
const trimmed = value.trim();
|
|
34486
36328
|
return trimmed.length > 0 ? trimmed : null;
|
|
34487
36329
|
}
|
|
36330
|
+
function isRecord$4(value) {
|
|
36331
|
+
return typeof value === "object" && value !== null;
|
|
36332
|
+
}
|
|
34488
36333
|
//#endregion
|
|
34489
36334
|
//#region ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
|
|
34490
36335
|
/**
|
|
@@ -34720,7 +36565,7 @@ function projectNewsletterFormHydrationTarget(source) {
|
|
|
34720
36565
|
tag: "legacy-direct-list",
|
|
34721
36566
|
listId: source.listId
|
|
34722
36567
|
};
|
|
34723
|
-
default: return assertNever$
|
|
36568
|
+
default: return assertNever$3(source);
|
|
34724
36569
|
}
|
|
34725
36570
|
}
|
|
34726
36571
|
function parseRequiredNewsletterSignupBlockId(value) {
|
|
@@ -36898,7 +38743,7 @@ function isNonProductionEnv() {
|
|
|
36898
38743
|
//#region ../blocks/src/system/data/linkedContentEntries.ts
|
|
36899
38744
|
const LINKED_CONTENT_ENTRY_META_KEY = "__rbLinkedContentEntry";
|
|
36900
38745
|
function coerceLinkedContentEntriesPayload(payload) {
|
|
36901
|
-
if (!isRecord$
|
|
38746
|
+
if (!isRecord$3(payload)) return payload;
|
|
36902
38747
|
const response = payload;
|
|
36903
38748
|
if (!Array.isArray(response.entries)) return payload;
|
|
36904
38749
|
const contentType = parsePublicContentTypeMeta(response.contentType);
|
|
@@ -36906,12 +38751,12 @@ function coerceLinkedContentEntriesPayload(payload) {
|
|
|
36906
38751
|
return response.entries.map((entry) => enrichLinkedContentEntry(entry, contentType));
|
|
36907
38752
|
}
|
|
36908
38753
|
function enrichLinkedContentEntry(entry, contentType) {
|
|
36909
|
-
if (!isRecord$
|
|
38754
|
+
if (!isRecord$3(entry)) return entry;
|
|
36910
38755
|
const entryId = typeof entry.id === "string" ? entry.id : null;
|
|
36911
38756
|
if (!entryId) return entry;
|
|
36912
38757
|
const title = typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title : entryId;
|
|
36913
38758
|
const optimisticHash = typeof entry.optimisticHash === "string" && entry.optimisticHash.length > 0 ? entry.optimisticHash : null;
|
|
36914
|
-
const content = isRecord$
|
|
38759
|
+
const content = isRecord$3(entry.content) ? entry.content : {};
|
|
36915
38760
|
const meta = {
|
|
36916
38761
|
kind: "linked-content-entry",
|
|
36917
38762
|
entryId,
|
|
@@ -36994,7 +38839,7 @@ function resolveLinkedContentEditSupport(contentType) {
|
|
|
36994
38839
|
kind: "unsupported-domain-backed",
|
|
36995
38840
|
reason: metadata.reason
|
|
36996
38841
|
};
|
|
36997
|
-
default: return assertNever$
|
|
38842
|
+
default: return assertNever$3(metadata);
|
|
36998
38843
|
}
|
|
36999
38844
|
}
|
|
37000
38845
|
function contentTypeKeyToLabel(key) {
|
|
@@ -37004,7 +38849,7 @@ function capitalize(value) {
|
|
|
37004
38849
|
return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
|
|
37005
38850
|
}
|
|
37006
38851
|
function parsePublicContentTypeMeta(value) {
|
|
37007
|
-
if (!isRecord$
|
|
38852
|
+
if (!isRecord$3(value)) return null;
|
|
37008
38853
|
if (typeof value.key !== "string" || value.key.trim().length === 0) return null;
|
|
37009
38854
|
return {
|
|
37010
38855
|
key: value.key,
|
|
@@ -37014,7 +38859,7 @@ function parsePublicContentTypeMeta(value) {
|
|
|
37014
38859
|
};
|
|
37015
38860
|
}
|
|
37016
38861
|
function parsePublicContentTypeLinkedEntryEditing(value) {
|
|
37017
|
-
if (!isRecord$
|
|
38862
|
+
if (!isRecord$3(value) || typeof value.kind !== "string") return null;
|
|
37018
38863
|
switch (value.kind) {
|
|
37019
38864
|
case "generic": return { kind: "generic" };
|
|
37020
38865
|
case "unsupported-domain-backed": return {
|
|
@@ -37025,7 +38870,7 @@ function parsePublicContentTypeLinkedEntryEditing(value) {
|
|
|
37025
38870
|
}
|
|
37026
38871
|
}
|
|
37027
38872
|
function parsePublicContentTypeFieldMeta(value) {
|
|
37028
|
-
if (!isRecord$
|
|
38873
|
+
if (!isRecord$3(value)) return [];
|
|
37029
38874
|
if (typeof value.id !== "string" || typeof value.type !== "string") return [];
|
|
37030
38875
|
return [{
|
|
37031
38876
|
id: value.id,
|
|
@@ -37039,7 +38884,7 @@ function parseStringArray(value) {
|
|
|
37039
38884
|
if (!Array.isArray(value)) return null;
|
|
37040
38885
|
return value.filter((item) => typeof item === "string");
|
|
37041
38886
|
}
|
|
37042
|
-
function isRecord$
|
|
38887
|
+
function isRecord$3(value) {
|
|
37043
38888
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37044
38889
|
}
|
|
37045
38890
|
//#endregion
|
|
@@ -37060,10 +38905,10 @@ function normalizeDataLoaders(def) {
|
|
|
37060
38905
|
*/
|
|
37061
38906
|
function normalizeContent(block) {
|
|
37062
38907
|
const source = block.draftContent ?? block.content ?? block.publishedContent ?? {};
|
|
37063
|
-
if (!isObjectRecord(source)) return {};
|
|
38908
|
+
if (!isObjectRecord$1(source)) return {};
|
|
37064
38909
|
if ("data" in source) {
|
|
37065
38910
|
const data = source.data;
|
|
37066
|
-
if (isObjectRecord(data)) return data;
|
|
38911
|
+
if (isObjectRecord$1(data)) return data;
|
|
37067
38912
|
if (data === null || data === void 0) return {};
|
|
37068
38913
|
}
|
|
37069
38914
|
return source;
|
|
@@ -37246,7 +39091,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
|
|
|
37246
39091
|
//#endregion
|
|
37247
39092
|
//#region ../blocks/src/system/data/normalizeLoaderParams.ts
|
|
37248
39093
|
function toStringParams(value) {
|
|
37249
|
-
if (!isObjectRecord(value)) return {};
|
|
39094
|
+
if (!isObjectRecord$1(value)) return {};
|
|
37250
39095
|
const out = {};
|
|
37251
39096
|
for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
|
|
37252
39097
|
return out;
|
|
@@ -37844,7 +39689,7 @@ function describeSiteVerticalConfigIssue(issue) {
|
|
|
37844
39689
|
case "duplicate_preset_id":
|
|
37845
39690
|
case "duplicate_canonical_behaviour":
|
|
37846
39691
|
case "future_preset_selected": return issue.code;
|
|
37847
|
-
default: return assertNever$
|
|
39692
|
+
default: return assertNever$3(issue);
|
|
37848
39693
|
}
|
|
37849
39694
|
}
|
|
37850
39695
|
const VerticalIdSchema = z.string().trim().transform((value, ctx) => {
|
|
@@ -37885,7 +39730,7 @@ z.object({
|
|
|
37885
39730
|
});
|
|
37886
39731
|
//#endregion
|
|
37887
39732
|
//#region ../api/src/utils/isRecord.ts
|
|
37888
|
-
function isRecord$
|
|
39733
|
+
function isRecord$2(value) {
|
|
37889
39734
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37890
39735
|
}
|
|
37891
39736
|
//#endregion
|
|
@@ -38134,7 +39979,7 @@ function sanitizeMarks(marks) {
|
|
|
38134
39979
|
if (!Array.isArray(marks) || marks.length === 0) return;
|
|
38135
39980
|
const sanitized = marks.flatMap((mark) => {
|
|
38136
39981
|
if (mark.type === "bold" || mark.type === "strong" || mark.type === "italic" || mark.type === "em") return [{ type: mark.type }];
|
|
38137
|
-
if (mark.type === "link" && isRecord$
|
|
39982
|
+
if (mark.type === "link" && isRecord$2(mark.attrs) && typeof mark.attrs.href === "string") {
|
|
38138
39983
|
const attrs = { href: mark.attrs.href };
|
|
38139
39984
|
if (typeof mark.attrs.target === "string" && mark.attrs.target.trim().length > 0) attrs.target = mark.attrs.target;
|
|
38140
39985
|
if (typeof mark.attrs.rel === "string" && mark.attrs.rel.trim().length > 0) attrs.rel = mark.attrs.rel;
|
|
@@ -38329,7 +40174,7 @@ const ENTRY_REF_KEYS = [
|
|
|
38329
40174
|
"entryId",
|
|
38330
40175
|
"slug"
|
|
38331
40176
|
];
|
|
38332
|
-
function isRecord(value) {
|
|
40177
|
+
function isRecord$1(value) {
|
|
38333
40178
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
38334
40179
|
}
|
|
38335
40180
|
function extractManualEntryRef(item) {
|
|
@@ -38337,7 +40182,7 @@ function extractManualEntryRef(item) {
|
|
|
38337
40182
|
const trimmed = item.trim();
|
|
38338
40183
|
return trimmed.length > 0 ? trimmed : null;
|
|
38339
40184
|
}
|
|
38340
|
-
if (!isRecord(item)) return null;
|
|
40185
|
+
if (!isRecord$1(item)) return null;
|
|
38341
40186
|
for (const key of ENTRY_REF_KEYS) {
|
|
38342
40187
|
const raw = item[key];
|
|
38343
40188
|
if (typeof raw === "string" && raw.trim().length > 0) return raw.trim();
|
|
@@ -38642,6 +40487,126 @@ function requireSdkTheme(theme, siteId, reason = "cms_theme_absent") {
|
|
|
38642
40487
|
return theme;
|
|
38643
40488
|
}
|
|
38644
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
|
|
38645
40610
|
//#region src/rendering/hooks/usePage.ts
|
|
38646
40611
|
/**
|
|
38647
40612
|
* Client-side React hook to fetch page data.
|
|
@@ -38741,24 +40706,15 @@ function usePage(params) {
|
|
|
38741
40706
|
const { page: pageData } = pageResponse;
|
|
38742
40707
|
const canonicalPagePath = pageData.path ?? path;
|
|
38743
40708
|
const mediaAssets = Array.isArray(pageResponse.mediaAssets) && pageResponse.mediaAssets.length > 0 ? toMediaAssetSidecar(pageResponse.mediaAssets) : void 0;
|
|
38744
|
-
const
|
|
38745
|
-
if (!block || typeof block !== "object") throw new Error("Invalid block format in API response");
|
|
38746
|
-
if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id: expected string or null, got ${typeof block.id}`);
|
|
38747
|
-
if (typeof block.kind !== "string") throw new Error(`Invalid block kind: expected string, got ${typeof block.kind}`);
|
|
38748
|
-
if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose: expected string, got ${typeof block.purpose}`);
|
|
38749
|
-
return {
|
|
38750
|
-
id: block.id,
|
|
38751
|
-
kind: block.kind,
|
|
38752
|
-
purpose: block.purpose
|
|
38753
|
-
};
|
|
38754
|
-
});
|
|
38755
|
-
const pageOutline = {
|
|
40709
|
+
const pageOutline = buildRenderablePageOutline({
|
|
38756
40710
|
name: pageData.name,
|
|
38757
40711
|
path: canonicalPagePath,
|
|
40712
|
+
fallbackPath: path,
|
|
38758
40713
|
purpose: pageData.purpose,
|
|
38759
|
-
blocks
|
|
38760
|
-
|
|
38761
|
-
|
|
40714
|
+
blocks: pageData.blocks,
|
|
40715
|
+
customBlocks: resolveSiteCustomBlocks(site)
|
|
40716
|
+
});
|
|
40717
|
+
const resolvedData = await prefetchBlockData(projectRenderablePageOutline(pageOutline), {
|
|
38762
40718
|
siteId,
|
|
38763
40719
|
pageId: pageId ?? pageData.id,
|
|
38764
40720
|
previewStage: preview ? "preview" : "published"
|