@riverbankcms/sdk 0.60.6 → 0.60.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/_dts/api/src/appointmentSetup.d.ts +2 -2
  2. package/dist/_dts/api/src/bookingConfig.d.ts +6 -0
  3. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +45 -3
  4. package/dist/_dts/api/src/bookingOperations.d.ts +40 -3
  5. package/dist/_dts/api/src/courses.d.ts +1 -5
  6. package/dist/_dts/api/src/endpoints.d.ts +80 -1
  7. package/dist/_dts/api/src/index.d.ts +3 -2
  8. package/dist/_dts/api/src/navigation/contracts.d.ts +9 -9
  9. package/dist/_dts/api/src/navigation/linkValue.d.ts +1 -1
  10. package/dist/_dts/api/src/public/endpoints.d.ts +1 -1
  11. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +15 -1
  12. package/dist/_dts/api/src/resources.d.ts +1 -1
  13. package/dist/_dts/api/src/siteBanner.d.ts +8 -8
  14. package/dist/_dts/api/src/siteOnboarding.d.ts +1 -0
  15. package/dist/_dts/api/src/teamMembers.d.ts +27 -0
  16. package/dist/_dts/blocks/src/index.d.ts +2 -1
  17. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +35 -29
  18. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +1 -5
  19. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +40 -34
  20. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +1 -5
  21. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +1 -1
  22. package/dist/_dts/blocks/src/system/blocks/products/shared.d.ts +2 -2
  23. package/dist/_dts/blocks/src/system/blocks/shared/bookingPaymentTerms.d.ts +9 -9
  24. package/dist/_dts/blocks/src/system/blocks/shared/teamMembers.d.ts +24 -0
  25. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +18 -8
  26. package/dist/_dts/blocks/src/system/constants/background.d.ts +1 -1
  27. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  28. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  29. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +185 -0
  30. package/dist/_dts/blocks/src/system/manifest/index.d.ts +1 -0
  31. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +201 -201
  32. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +2 -84
  33. package/dist/_dts/blocks/src/system/node/schema.d.ts +5 -5
  34. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +1 -1
  35. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +4 -4
  36. package/dist/_dts/blocks/src/system/transforms/registry/ui.d.ts +1 -1
  37. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +3 -3
  38. package/dist/_dts/blocks/src/system/types/link.d.ts +93 -1
  39. package/dist/_dts/content-model/src/content-types/schema.d.ts +8 -8
  40. package/dist/_dts/content-model/src/metadataConfig.d.ts +1 -0
  41. package/dist/_dts/core/src/branded.d.ts +2 -0
  42. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +124 -8
  43. package/dist/_dts/db/src/schemas/forms.d.ts +85 -64
  44. package/dist/_dts/editor-blocks/src/widgets/link/LinkSummary.d.ts +1 -1
  45. package/dist/_dts/editor-blocks/src/widgets/link/LinkWidget.d.ts +1 -1
  46. package/dist/_dts/editor-blocks/src/widgets/link/utils.d.ts +1 -1
  47. package/dist/_dts/sdk/src/client/types.d.ts +9 -2
  48. package/dist/_dts/sdk/src/config/typed-entries.d.ts +36 -1
  49. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  50. package/dist/_dts/sdk/src/config/validation.d.ts +40 -37
  51. package/dist/_dts/sdk/src/contracts/content.d.ts +6 -1
  52. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  53. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +18 -8
  54. package/dist/_dts/sdk/src/data/prefetchBlockData.d.ts +1 -1
  55. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +19 -19
  56. package/dist/_dts/sdk/src/public-api/contracts.d.ts +87 -69
  57. package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
  58. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -5
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/_dts/theme-core/src/accordions/types.d.ts +11 -11
  61. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +10 -10
  62. package/dist/_dts/theme-core/src/buttons/types.d.ts +27 -27
  63. package/dist/_dts/theme-core/src/cards/types.d.ts +17 -17
  64. package/dist/_dts/theme-core/src/inputs/types.d.ts +14 -14
  65. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +2 -2
  66. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +438 -438
  67. package/dist/_dts/theme-core/src/navigation/types.d.ts +16 -16
  68. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +15 -15
  69. package/dist/_dts/theme-core/src/schema.d.ts +662 -662
  70. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +4 -4
  71. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +15 -15
  72. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +7 -7
  73. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +1 -1
  74. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +5 -5
  75. package/dist/_dts/ui/src/badge.d.ts +1 -1
  76. package/dist/_dts/ui/src/button-group.d.ts +1 -1
  77. package/dist/_dts/ui/src/button.d.ts +2 -2
  78. package/dist/_dts/ui/src/callout.d.ts +1 -1
  79. package/dist/_dts/ui/src/card.d.ts +1 -1
  80. package/dist/_dts/ui/src/surface.d.ts +2 -2
  81. package/dist/_dts/ui/src/toggle.d.ts +4 -4
  82. package/dist/cli/index.mjs +951 -451
  83. package/dist/client/client.mjs +39490 -38952
  84. package/dist/client/hooks.mjs +1992 -1741
  85. package/dist/client/rendering/client.mjs +179 -130
  86. package/dist/client/rendering/islands.mjs +68 -43
  87. package/dist/client/rendering.mjs +1812 -1292
  88. package/dist/preview-next/before-render.mjs +147 -1
  89. package/dist/preview-next/client/runtime.mjs +1377 -829
  90. package/dist/preview-next/middleware.mjs +147 -1
  91. package/dist/server/components.mjs +3246 -2751
  92. package/dist/server/config-validation.mjs +2198 -1962
  93. package/dist/server/config.mjs +2198 -1962
  94. package/dist/server/data.mjs +1992 -1741
  95. package/dist/server/index.mjs +168 -2
  96. package/dist/server/next.mjs +3230 -2701
  97. package/dist/server/page-converter.mjs +345 -259
  98. package/dist/server/prebuild.mjs +1 -1
  99. package/dist/server/rendering/server.mjs +3274 -2763
  100. package/dist/server/rendering.mjs +3274 -2763
  101. package/dist/server/routing.mjs +530 -309
  102. package/dist/server/server.mjs +2011 -1742
  103. package/package.json +1 -1
@@ -1522,15 +1522,6 @@ var init_augmentManifest = __esm({
1522
1522
  "../blocks/src/system/manifest/augmentManifest.ts"() {
1523
1523
  }
1524
1524
  });
1525
-
1526
- // ../blocks/src/lib/typeGuards.ts
1527
- function isRecord2(value) {
1528
- return typeof value === "object" && value !== null && !Array.isArray(value);
1529
- }
1530
- var init_typeGuards = __esm({
1531
- "../blocks/src/lib/typeGuards.ts"() {
1532
- }
1533
- });
1534
1525
  var VARIANT_ROLES, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, buttonGlobalSettingsSchema, gradientDirectionSchema, buttonBackgroundSchema, effectApplicationSchema, buttonBorderSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, buttonVariantSchema, buttonSystemSchema;
1535
1526
  var init_types2 = __esm({
1536
1527
  "../theme-core/src/buttons/types.ts"() {
@@ -8163,7 +8154,19 @@ var init_teamMember = __esm({
8163
8154
  bind("photo")
8164
8155
  )
8165
8156
  ]),
8166
- text({ as: "h3" }, bind("name")),
8157
+ link(
8158
+ {
8159
+ href: { $bind: { from: "profilePath" } },
8160
+ className: "rb-team-member-name-link"
8161
+ },
8162
+ [text({ as: "h3" }, bind("name"))],
8163
+ when("profilePath")
8164
+ ),
8165
+ text(
8166
+ { as: "h3" },
8167
+ when("profilePath", { not: true }),
8168
+ bind("name")
8169
+ ),
8167
8170
  text({ as: "p", className: "rb-team-member-role" }, when("role"), bind("role")),
8168
8171
  richText(
8169
8172
  { className: "rb-prose rb-max-w-none" },
@@ -8318,9 +8321,9 @@ function createZodCodec(schema) {
8318
8321
  return decodeSuccess(parsed.data);
8319
8322
  }
8320
8323
  return decodeFailure(
8321
- parsed.error.issues.map((issue) => ({
8322
- path: zodIssuePath(issue.path),
8323
- message: issue.message
8324
+ parsed.error.issues.map((issue2) => ({
8325
+ path: zodIssuePath(issue2.path),
8326
+ message: issue2.message
8324
8327
  }))
8325
8328
  );
8326
8329
  }
@@ -8610,6 +8613,15 @@ var init_colorConversion = __esm({
8610
8613
  }
8611
8614
  });
8612
8615
 
8616
+ // ../blocks/src/lib/typeGuards.ts
8617
+ function isRecord2(value) {
8618
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8619
+ }
8620
+ var init_typeGuards = __esm({
8621
+ "../blocks/src/lib/typeGuards.ts"() {
8622
+ }
8623
+ });
8624
+
8613
8625
  // ../theme-core/src/responsiveDisplay.ts
8614
8626
  function mobileOnlyDisplay(display) {
8615
8627
  return `${BASE_DISPLAY_CLASSES[display]} rb-lg-hidden`;
@@ -8800,7 +8812,9 @@ var init_schemas = __esm({
8800
8812
  courseTeamMemberSummarySchema = z.object({
8801
8813
  id: z.string(),
8802
8814
  name: z.string(),
8803
- summary: z.string().nullable()
8815
+ roleLabel: z.string().nullable(),
8816
+ summary: z.string().nullable(),
8817
+ profilePath: z.string().nullable()
8804
8818
  });
8805
8819
  coursePricingOptionSchema = z.object({
8806
8820
  id: z.string(),
@@ -8911,7 +8925,9 @@ var init_schemas2 = __esm({
8911
8925
  publicTeamMemberSummarySchema = z.object({
8912
8926
  id: z.string(),
8913
8927
  name: z.string(),
8914
- summary: z.string().nullable()
8928
+ roleLabel: z.string().nullable(),
8929
+ summary: z.string().nullable(),
8930
+ profilePath: z.string().nullable()
8915
8931
  });
8916
8932
  publicEventSchema = z.object({
8917
8933
  kind: z.enum(["event", "course_session"]).optional(),
@@ -11175,7 +11191,7 @@ var init_shared6 = __esm({
11175
11191
  });
11176
11192
 
11177
11193
  // ../blocks/src/system/runtime/api/creditProducts.ts
11178
- function assertNever3(value) {
11194
+ function assertNever4(value) {
11179
11195
  throw new Error(`Unhandled credit product case: ${String(value)}`);
11180
11196
  }
11181
11197
  function useCasesFromModules(modules) {
@@ -11208,7 +11224,7 @@ function getCreditProductCreditUnit(useCase) {
11208
11224
  perCreditSuffix: "credit"
11209
11225
  };
11210
11226
  default:
11211
- return assertNever3(useCase);
11227
+ return assertNever4(useCase);
11212
11228
  }
11213
11229
  }
11214
11230
  function deriveCreditProductLabels(products, options = {}) {
@@ -14948,13 +14964,150 @@ var ENDPOINT_DEFINITIONS = {
14948
14964
  "server:internal_error"
14949
14965
  ]
14950
14966
  },
14951
- deleteAppointmentResource: {
14967
+ removeAppointmentResource: {
14952
14968
  path: "/sites/{siteId}/bookings/resources/{resourceId}",
14953
14969
  method: "DELETE",
14954
14970
  auth: "user",
14955
14971
  responseKind: "json",
14956
14972
  errors: ["resource:not_found", "server:internal_error"]
14957
14973
  },
14974
+ createTeamMemberProfile: {
14975
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile",
14976
+ method: "POST",
14977
+ auth: "user",
14978
+ responseKind: "json",
14979
+ errors: [
14980
+ "validation:invalid_input",
14981
+ "resource:not_found",
14982
+ "resource:conflict",
14983
+ "server:internal_error"
14984
+ ]
14985
+ },
14986
+ updateTeamMemberProfilePolicy: {
14987
+ path: "/sites/{siteId}/bookings/resources/profile-policy",
14988
+ method: "PUT",
14989
+ auth: "user",
14990
+ responseKind: "json",
14991
+ errors: ["validation:invalid_input", "server:internal_error"]
14992
+ },
14993
+ updateTeamMemberProfileContent: {
14994
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/content",
14995
+ method: "PUT",
14996
+ tags: [
14997
+ "site-{siteId}",
14998
+ "content-{siteId}-team-member",
14999
+ "content-entry-{entryId}"
15000
+ ],
15001
+ auth: "user",
15002
+ responseKind: "json",
15003
+ errors: [
15004
+ "validation:invalid_input",
15005
+ "resource:not_found",
15006
+ "resource:conflict",
15007
+ "server:internal_error"
15008
+ ]
15009
+ },
15010
+ publishTeamMemberProfile: {
15011
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/publish",
15012
+ method: "POST",
15013
+ tags: [
15014
+ "site-{siteId}",
15015
+ "content-{siteId}-team-member",
15016
+ "content-entry-{entryId}"
15017
+ ],
15018
+ auth: "user",
15019
+ responseKind: "json",
15020
+ errors: [
15021
+ "validation:invalid_input",
15022
+ "resource:not_found",
15023
+ "server:internal_error"
15024
+ ]
15025
+ },
15026
+ discardTeamMemberProfileDraft: {
15027
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/discard",
15028
+ method: "POST",
15029
+ tags: [
15030
+ "site-{siteId}",
15031
+ "content-{siteId}-team-member",
15032
+ "content-entry-{entryId}"
15033
+ ],
15034
+ auth: "user",
15035
+ responseKind: "json",
15036
+ errors: [
15037
+ "validation:invalid_input",
15038
+ "resource:not_found",
15039
+ "resource:conflict",
15040
+ "server:internal_error"
15041
+ ]
15042
+ },
15043
+ unpublishTeamMemberProfile: {
15044
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/unpublish",
15045
+ method: "POST",
15046
+ tags: [
15047
+ "site-{siteId}",
15048
+ "content-{siteId}-team-member",
15049
+ "content-entry-{entryId}"
15050
+ ],
15051
+ auth: "user",
15052
+ responseKind: "json",
15053
+ errors: [
15054
+ "validation:invalid_input",
15055
+ "resource:not_found",
15056
+ "resource:conflict",
15057
+ "server:internal_error"
15058
+ ]
15059
+ },
15060
+ scheduleTeamMemberProfile: {
15061
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/schedule",
15062
+ method: "POST",
15063
+ tags: [
15064
+ "site-{siteId}",
15065
+ "content-{siteId}-team-member",
15066
+ "content-entry-{entryId}"
15067
+ ],
15068
+ auth: "user",
15069
+ responseKind: "json",
15070
+ errors: [
15071
+ "validation:invalid_input",
15072
+ "resource:not_found",
15073
+ "resource:conflict",
15074
+ "server:internal_error"
15075
+ ]
15076
+ },
15077
+ cancelScheduledTeamMemberProfile: {
15078
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/{entryId}/schedule",
15079
+ method: "DELETE",
15080
+ tags: [
15081
+ "site-{siteId}",
15082
+ "content-{siteId}-team-member",
15083
+ "content-entry-{entryId}"
15084
+ ],
15085
+ auth: "user",
15086
+ responseKind: "json",
15087
+ errors: [
15088
+ "validation:invalid_input",
15089
+ "resource:not_found",
15090
+ "resource:conflict",
15091
+ "server:internal_error"
15092
+ ]
15093
+ },
15094
+ updateTeamMemberProfileRouteMetadata: {
15095
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/profile/routes/{routeId}/metadata",
15096
+ method: "PATCH",
15097
+ tags: [
15098
+ TAG_TEMPLATES.siteCollection,
15099
+ TAG_TEMPLATES.siteRoutableContent,
15100
+ TAG_TEMPLATES.routeById
15101
+ ],
15102
+ auth: "user",
15103
+ responseKind: "json",
15104
+ errors: [
15105
+ "validation:invalid_input",
15106
+ "resource:not_found",
15107
+ "resource:conflict",
15108
+ "server:internal_error"
15109
+ ]
15110
+ },
14958
15111
  listAppointmentServices: {
14959
15112
  path: "/sites/{siteId}/bookings/services",
14960
15113
  method: "GET",
@@ -17328,6 +17481,15 @@ var ENDPOINT_DEFINITIONS = {
17328
17481
  auth: "public",
17329
17482
  responseKind: "json"
17330
17483
  },
17484
+ listPublicTeamMembers: {
17485
+ path: "/public/sites/{siteId}/team-members",
17486
+ method: "GET",
17487
+ revalidate: 60,
17488
+ tags: ["public-team-members-{siteId}"],
17489
+ errors: [],
17490
+ auth: "public",
17491
+ responseKind: "json"
17492
+ },
17331
17493
  getPublicCourse: {
17332
17494
  path: "/public/sites/{siteId}/courses/{courseId}",
17333
17495
  method: "GET",
@@ -19703,6 +19865,7 @@ var SUPPORTED_LOADER_ENDPOINTS = [
19703
19865
  "listPublicEvents",
19704
19866
  "getPublicEventDetails",
19705
19867
  "listPublicCourses",
19868
+ "listPublicTeamMembers",
19706
19869
  "listPublicProducts",
19707
19870
  "listPublicPasses",
19708
19871
  "listPublicMemberships",
@@ -20629,11 +20792,11 @@ siteBannerSettingsSchema.superRefine((value, ctx) => {
20629
20792
  return;
20630
20793
  }
20631
20794
  const analysis = analyzeSiteBannerBody(value.body);
20632
- for (const issue of analysis.issues) {
20795
+ for (const issue2 of analysis.issues) {
20633
20796
  ctx.addIssue({
20634
20797
  code: z.ZodIssueCode.custom,
20635
20798
  path: ["body"],
20636
- message: siteBannerBodyIssueMessage(issue)
20799
+ message: siteBannerBodyIssueMessage(issue2)
20637
20800
  });
20638
20801
  }
20639
20802
  });
@@ -20667,8 +20830,8 @@ function analyzeSiteBannerBody(body) {
20667
20830
  issues
20668
20831
  };
20669
20832
  }
20670
- function siteBannerBodyIssueMessage(issue) {
20671
- switch (issue) {
20833
+ function siteBannerBodyIssueMessage(issue2) {
20834
+ switch (issue2) {
20672
20835
  case "empty":
20673
20836
  return "Banner message is required when the banner is enabled.";
20674
20837
  case "too-many-paragraphs":
@@ -20920,324 +21083,35 @@ function isNavigationMenuValidationItem(value) {
20920
21083
  if (!isRecord(value)) return false;
20921
21084
  return typeof value.label === "string";
20922
21085
  }
20923
- var Rfc6902PatchOp = z.discriminatedUnion("op", [
20924
- // Standard RFC-6902 operations
20925
- z.object({
20926
- op: z.literal("add"),
20927
- path: z.string(),
20928
- value: z.unknown()
20929
- }),
20930
- z.object({
20931
- op: z.literal("remove"),
20932
- path: z.string()
20933
- }),
20934
- z.object({
20935
- op: z.literal("replace"),
20936
- path: z.string(),
20937
- value: z.unknown()
20938
- }),
20939
- z.object({
20940
- op: z.literal("move"),
20941
- from: z.string(),
20942
- path: z.string()
20943
- }),
20944
- z.object({
20945
- op: z.literal("copy"),
20946
- from: z.string(),
20947
- path: z.string()
20948
- }),
20949
- // Block-level operations (Phase 2)
20950
- z.object({
20951
- op: z.literal("add_block"),
20952
- blockKind: z.string(),
20953
- afterBlockId: z.string().nullable(),
20954
- content: z.record(z.string(), z.unknown()),
20955
- rationale: z.string()
20956
- }),
20957
- z.object({
20958
- op: z.literal("delete_block"),
20959
- blockId: z.string(),
20960
- rationale: z.string()
20961
- }),
20962
- z.object({
20963
- op: z.literal("reorder_block"),
20964
- blockId: z.string(),
20965
- afterBlockId: z.string().nullable(),
20966
- rationale: z.string()
20967
- })
20968
- ]);
20969
- z.object({
20970
- request: z.string().min(1).max(2e3)
20971
- });
20972
- var MultiPagePatchEnvelope = z.object({
20973
- pageId: z.string(),
20974
- blockId: z.string().optional(),
20975
- // Not present for page-level ops
20976
- blockKind: z.string().optional(),
20977
- blockPurpose: z.string().optional().nullable(),
20978
- ops: z.array(Rfc6902PatchOp),
20979
- rationale: z.string(),
20980
- currentContent: z.record(z.string(), z.unknown()).optional()
20981
- });
20982
- z.object({
20983
- patches: z.array(MultiPagePatchEnvelope),
20984
- assistantMessage: z.string(),
20985
- pagesModified: z.number(),
20986
- toolCallsUsed: z.number()
20987
- });
20988
-
20989
- // ../blocks/src/system/manifest/registry.ts
20990
- var REGISTRY_SYMBOL = /* @__PURE__ */ Symbol.for("@riverbankcms/blocks/manifest-registry");
20991
- var isVitest = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.VITEST === "true";
20992
- var globalScope = globalThis;
20993
- var manifestStore = isVitest ? /* @__PURE__ */ new Map() : globalScope[REGISTRY_SYMBOL] ??= /* @__PURE__ */ new Map();
20994
- function registerManifest(manifest) {
20995
- manifestStore.set(manifest.name, manifest);
20996
- return manifest;
20997
- }
20998
-
20999
- // ../blocks/src/system/manifest/validation.ts
21000
- init_schema2();
21001
-
21002
- // ../blocks/src/system/manifest/richTextSchema.ts
21003
- init_typeGuards();
21004
- var TipTapMarkSchema = z.object({
21005
- type: z.string(),
21006
- attrs: z.record(z.string(), z.unknown()).optional()
21007
- });
21008
- var TipTapNodeSchema = z.lazy(
21009
- () => z.object({
21010
- type: z.string(),
21011
- content: z.array(TipTapNodeSchema).optional(),
21012
- text: z.string().optional(),
21013
- attrs: z.record(z.string(), z.unknown()).optional(),
21014
- marks: z.array(TipTapMarkSchema).optional()
21015
- })
21016
- );
21017
- var RichTextValueSchema = z.union([
21018
- // New format: TipTap document directly
21019
- TipTapNodeSchema,
21020
- // Legacy format: wrapped in { doc: {...} }
21021
- z.object({
21022
- doc: TipTapNodeSchema
21023
- })
21024
- ]);
21025
- function buildRichTextSchema(options) {
21026
- let schema = RichTextValueSchema;
21027
- return schema;
21028
- }
21029
-
21030
- // ../blocks/src/system/manifest/validation.ts
21031
- function isEmpty(value) {
21032
- if (typeof value === "string" && value.trim() === "") return true;
21033
- if (value === null || value === void 0) return true;
21034
- if (Array.isArray(value) && value.length === 0) return true;
21035
- if (isEmptyRichTextDoc(value)) return true;
21036
- return false;
21037
- }
21038
- function isEmptyRichTextDoc(value) {
21039
- if (!value || typeof value !== "object") return false;
21040
- const obj = value;
21041
- const doc = "doc" in obj ? obj.doc : obj;
21042
- if (!doc || typeof doc !== "object") return false;
21043
- const docObj = doc;
21044
- if (docObj.type !== "doc") return false;
21045
- const content = docObj.content;
21046
- if (!Array.isArray(content) || content.length === 0) return true;
21047
- if (content.length === 1) {
21048
- const first = content[0];
21049
- if (first.type === "paragraph" && (!first.content || first.content.length === 0)) {
21050
- return true;
21051
- }
21052
- }
21053
- return false;
21054
- }
21055
- function preprocessEmptyValues(content) {
21056
- if (!content || typeof content !== "object" || Array.isArray(content)) {
21057
- return {};
21058
- }
21059
- const result = {};
21060
- for (const [key, value] of Object.entries(content)) {
21061
- result[key] = isEmpty(value) ? void 0 : value;
21062
- }
21063
- return result;
21064
- }
21065
- function createManifestValidator(manifestOrFields, options = {}) {
21066
- const allowNull = options.allowNull ?? true;
21067
- const isDraft = options.mode === "draft";
21068
- const allowIncomplete = isDraft || (options.allowIncomplete ?? false);
21069
- const shape = {};
21070
- const fields3 = Array.isArray(manifestOrFields) ? manifestOrFields : manifestOrFields.fields ?? [];
21071
- for (const field of fields3) {
21072
- shape[field.id] = buildFieldSchema(field, allowNull, allowIncomplete);
21073
- }
21074
- const baseSchema = z.object(shape).catchall(z.unknown()).passthrough();
21075
- if (isDraft) {
21076
- return z.preprocess(preprocessEmptyValues, baseSchema);
21077
- }
21078
- return baseSchema;
21079
- }
21080
- function buildFieldSchema(field, allowNull, allowIncomplete = false) {
21081
- const required = Boolean(field.required);
21082
- let schema;
21083
- switch (field.type) {
21084
- case "text":
21085
- schema = buildTextSchema(field);
21086
- break;
21087
- case "richText":
21088
- schema = buildRichTextSchema2();
21089
- break;
21090
- case "media": {
21091
- const baseMediaSchema = z.record(z.string(), z.unknown());
21092
- const isRequired = Boolean(field.required);
21093
- schema = isRequired ? baseMediaSchema : baseMediaSchema.nullable();
21094
- break;
21095
- }
21096
- case "boolean":
21097
- schema = z.boolean();
21098
- break;
21099
- case "slug":
21100
- schema = buildSlugSchema(field);
21101
- break;
21102
- case "url":
21103
- schema = buildUrlSchema(field);
21104
- break;
21105
- case "link":
21106
- schema = buildLinkSchema();
21107
- break;
21108
- case "select":
21109
- schema = buildSelectSchema(field);
21110
- break;
21111
- case "reference":
21112
- schema = buildReferenceSchema(field);
21113
- break;
21114
- case "repeater":
21115
- schema = buildRepeaterSchema(field, allowNull, allowIncomplete);
21116
- break;
21117
- case "group":
21118
- schema = buildGroupSchema(field, allowNull, allowIncomplete);
21119
- break;
21120
- default:
21121
- schema = z.unknown();
21122
- break;
21123
- }
21124
- return finalizeSchema(schema, required, allowNull, allowIncomplete);
21125
- }
21126
- function buildFriendlyStringSchema(field) {
21127
- return z.string({
21128
- error: (issue) => issue.input === void 0 || issue.input === null ? "This field is required" : `${field.label} needs text`
21129
- });
21130
- }
21131
- function buildTextSchema(field) {
21132
- const ui = field.ui ?? {};
21133
- const inputType = ui?.inputType;
21134
- let schema;
21135
- if (inputType === "number") {
21136
- schema = z.coerce.number({
21137
- error: (issue) => issue.input === void 0 ? `${field.label} is required` : `${field.label} needs a number`
21138
- });
21139
- if (typeof ui?.min === "number") {
21140
- schema = schema.min(
21141
- ui.min,
21142
- `${field.label} must be ${ui.min} or more`
21143
- );
21144
- }
21145
- if (typeof ui?.max === "number") {
21146
- schema = schema.max(
21147
- ui.max,
21148
- `${field.label} must be ${ui.max} or less`
21149
- );
21150
- }
21151
- } else {
21152
- schema = buildFriendlyStringSchema(field);
21153
- if (inputType === "email") {
21154
- schema = schema.email("Enter a valid email address");
21155
- }
21156
- if (inputType === "tel") {
21157
- const TEL_RE = /^[+()0-9\s\-]{3,}$/;
21158
- schema = schema.regex(
21159
- TEL_RE,
21160
- "Enter a valid phone number"
21161
- );
21162
- }
21163
- if (ui?.pattern) {
21164
- try {
21165
- const re = new RegExp(ui.pattern);
21166
- schema = schema.regex(
21167
- re,
21168
- `${field.label} is not in the right format`
21169
- );
21170
- } catch {
21171
- }
21172
- }
21173
- if (field.maxLength) {
21174
- schema = schema.max(
21175
- field.maxLength,
21176
- `${field.label} must be ${field.maxLength} characters or less`
21177
- );
21178
- }
21179
- if (field.required) {
21180
- schema = schema.min(1, { message: `${field.label} is required` }).refine((v) => v.trim().length > 0, { message: `${field.label} is required` });
21181
- }
21182
- }
21183
- return schema;
21184
- }
21185
- function buildRichTextSchema2() {
21186
- return buildRichTextSchema();
21187
- }
21188
- var SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
21189
- function buildSlugSchema(field) {
21190
- const message = `${field.label} can only use lowercase letters, numbers, and dashes`;
21191
- let schema = buildFriendlyStringSchema(field).regex(SLUG_PATTERN, message);
21192
- if (field.maxLength) {
21193
- schema = schema.max(
21194
- field.maxLength,
21195
- `${field.label} must be ${field.maxLength} characters or less`
21196
- );
21197
- }
21198
- if (field.required) {
21199
- schema = schema.min(1, { message: `${field.label} is required` });
21200
- }
21201
- return schema;
21202
- }
21203
- var ALLOWED_URL_PROTOCOLS = ["http:", "https:"];
21204
- function buildUrlSchema(field) {
21205
- const message = "Enter a valid web address";
21206
- const validate = (value) => {
21207
- if (!value) {
21208
- return !field.required;
21209
- }
21210
- if (field.allowRelative && value.startsWith("/")) {
21211
- return true;
21212
- }
21213
- try {
21214
- const parsed = new URL(value);
21215
- return ALLOWED_URL_PROTOCOLS.includes(
21216
- parsed.protocol
21217
- );
21218
- } catch {
21219
- return false;
21220
- }
21221
- };
21222
- let schema = buildFriendlyStringSchema(field).trim().refine(validate, message);
21223
- if (field.required) {
21224
- schema = schema.min(1, { message: `${field.label} is required` });
21225
- }
21226
- return schema;
21227
- }
21228
21086
  var nullableString = z.union([z.string().min(1), z.null()]);
21229
- var internalLinkSchema = z.object({
21087
+ var resolvedInternalLinkKeys = ["entityId", "entityType", "href", "title", "typeLabel"];
21088
+ var internalRouteOnlyLinkSchema = z.object({
21089
+ kind: z.literal("internal"),
21090
+ routeId: z.string().min(1)
21091
+ }).passthrough().superRefine((value, ctx) => {
21092
+ const hasResolvedMetadata = resolvedInternalLinkKeys.some((key) => value[key] != null);
21093
+ if (!hasResolvedMetadata) return;
21094
+ ctx.addIssue({
21095
+ code: "custom",
21096
+ message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
21097
+ });
21098
+ });
21099
+ var internalResolvedLinkSchema = z.object({
21230
21100
  kind: z.literal("internal"),
21231
21101
  routeId: z.string().min(1),
21232
- entityId: z.string().min(1).optional(),
21233
- entityType: z.enum(["page", "content"]).optional(),
21234
- href: nullableString.optional(),
21235
- title: nullableString.optional(),
21236
- typeLabel: nullableString.optional(),
21102
+ entityId: z.string().min(1),
21103
+ entityType: z.enum(["page", "content"]),
21104
+ href: z.string().min(1),
21105
+ title: z.string().min(1),
21106
+ typeLabel: z.string().min(1),
21237
21107
  contentTypeKey: nullableString.optional(),
21238
21108
  contentTypeName: nullableString.optional(),
21239
21109
  updatedAt: nullableString.optional()
21240
21110
  }).passthrough();
21111
+ var internalLinkSchema = z.union([
21112
+ internalResolvedLinkSchema,
21113
+ internalRouteOnlyLinkSchema
21114
+ ]);
21241
21115
  var externalLinkSchema2 = z.object({
21242
21116
  kind: z.literal("external"),
21243
21117
  href: z.string().min(1)
@@ -21262,84 +21136,556 @@ var linkSchema = z.union([
21262
21136
  pageLinkSchema2,
21263
21137
  entryLinkSchema2
21264
21138
  ]);
21265
- function buildLinkSchema() {
21266
- return linkSchema;
21139
+
21140
+ // ../blocks/src/system/manifest/fieldValidation/index.ts
21141
+ init_schema2();
21142
+ var TEL_RE = /^[+()0-9\s-]{3,}$/;
21143
+ var SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
21144
+ var ALLOWED_URL_PROTOCOLS = ["http:", "https:"];
21145
+ function assertNever2(value) {
21146
+ throw new Error(`Unhandled field validation variant: ${JSON.stringify(value)}`);
21267
21147
  }
21268
- function assertNeverSelectSource2(value) {
21269
- throw new Error(`Unhandled select source: ${JSON.stringify(value)}`);
21148
+ function validationContext(options = {}) {
21149
+ const isDraft = options.mode === "draft";
21150
+ return {
21151
+ allowNull: options.allowNull ?? true,
21152
+ allowIncomplete: isDraft || (options.allowIncomplete ?? false)
21153
+ };
21270
21154
  }
21271
- function buildSelectSchema(field) {
21272
- const source = normalizeSelectSource(field);
21273
- const singleValueSchema = (() => {
21274
- switch (source.kind) {
21275
- case "sdk":
21276
- case "site":
21277
- return buildFriendlyStringSchema(field);
21278
- case "static": {
21279
- const values = field.options.map((option) => option.value);
21280
- return buildFriendlyStringSchema(field).refine(
21281
- (value) => values.includes(value),
21282
- `Choose one of the available options for ${field.label}`
21283
- );
21284
- }
21285
- default:
21286
- return assertNeverSelectSource2(source);
21287
- }
21288
- })();
21289
- if (field.multiple) {
21290
- const arraySchema = z.array(singleValueSchema);
21291
- return field.required ? arraySchema.min(1, { message: "This field is required" }) : arraySchema.nullable();
21155
+ function fieldIssueToMessage(issue2) {
21156
+ switch (issue2.kind) {
21157
+ case "required":
21158
+ return "This field is required";
21159
+ case "wrongType":
21160
+ return `${issue2.label} needs ${issue2.expected}`;
21161
+ case "tooLong":
21162
+ return `Use ${issue2.maximum} characters or fewer`;
21163
+ case "invalidEmail":
21164
+ return "Enter a valid email address";
21165
+ case "invalidPhone":
21166
+ return "Enter a valid phone number";
21167
+ case "invalidPattern":
21168
+ return "Check the format and try again";
21169
+ case "invalidUrl":
21170
+ return "Enter a valid web address";
21171
+ case "invalidNumber":
21172
+ return `${issue2.label} needs a number`;
21173
+ case "tooSmall":
21174
+ return `${issue2.label} must be ${issue2.minimum} or more`;
21175
+ case "tooLarge":
21176
+ return `${issue2.label} must be ${issue2.maximum} or less`;
21177
+ case "invalidSlug":
21178
+ return `${issue2.label} can only use lowercase letters, numbers, and dashes`;
21179
+ case "invalidOption":
21180
+ return `Choose one of the available options for ${issue2.label}`;
21181
+ case "tooFewItems":
21182
+ return `${issue2.label} must have at least ${issue2.minimum} ${pluralize(issue2.itemLabel, issue2.minimum)}`;
21183
+ case "tooManyItems":
21184
+ return `${issue2.label} must have at most ${issue2.maximum} ${pluralize(issue2.itemLabel, issue2.maximum)}`;
21185
+ case "invalidRichText":
21186
+ return `${issue2.label} must be valid rich text`;
21187
+ case "invalidMedia":
21188
+ return `${issue2.label} must be a valid media item`;
21189
+ case "invalidLink":
21190
+ return `${issue2.label} must be a valid link`;
21191
+ case "invalidReference":
21192
+ return `${issue2.label} must reference a valid item`;
21193
+ default:
21194
+ return assertNever2(issue2);
21292
21195
  }
21293
- return field.required ? singleValueSchema : singleValueSchema.nullable();
21294
21196
  }
21295
- function buildReferenceSchema(field) {
21296
- let schema = z.string({
21297
- error: (issue) => issue.input === void 0 || issue.input === null ? "This field is required" : `${field.label} needs text`
21298
- });
21299
- if (field.required) {
21300
- schema = schema.min(1, { message: `${field.label} is required` });
21197
+ function pluralize(label, count) {
21198
+ if (count === 1) return label;
21199
+ return label.endsWith("s") ? label : `${label}s`;
21200
+ }
21201
+ function deriveFieldValidationPlan(field, path21 = [field.id]) {
21202
+ const required = Boolean(field.required);
21203
+ switch (field.type) {
21204
+ case "text": {
21205
+ const inputType = field.ui?.inputType;
21206
+ if (inputType === "number") {
21207
+ const constraints2 = commonConstraints(required, { kind: "numberType" });
21208
+ if (typeof field.ui?.min === "number") constraints2.push({ kind: "numberMin", minimum: field.ui.min });
21209
+ if (typeof field.ui?.max === "number") constraints2.push({ kind: "numberMax", maximum: field.ui.max });
21210
+ return makePlan("number", "number", field, path21, required, constraints2);
21211
+ }
21212
+ const constraints = commonConstraints(required, { kind: "textType" });
21213
+ if (inputType === "email") constraints.push({ kind: "emailFormat" });
21214
+ if (inputType === "tel") constraints.push({ kind: "phoneFormat" });
21215
+ if (field.ui?.pattern) constraints.push({ kind: "patternFormat", pattern: field.ui.pattern });
21216
+ if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
21217
+ return makePlan("string", "string", field, path21, required, constraints);
21218
+ }
21219
+ case "number": {
21220
+ const constraints = commonConstraints(required, { kind: "numberType" });
21221
+ if (typeof field.min === "number") constraints.push({ kind: "numberMin", minimum: field.min });
21222
+ if (typeof field.max === "number") constraints.push({ kind: "numberMax", maximum: field.max });
21223
+ return makePlan("number", "number", field, path21, required, constraints);
21224
+ }
21225
+ case "slug": {
21226
+ const constraints = commonConstraints(required, { kind: "textType" }, { kind: "slugFormat" });
21227
+ if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
21228
+ return makePlan("string", "string", field, path21, required, constraints);
21229
+ }
21230
+ case "url":
21231
+ return makePlan("string", "string", field, path21, required, commonConstraints(
21232
+ required,
21233
+ { kind: "textType" },
21234
+ { kind: "urlFormat", allowRelative: Boolean(field.allowRelative) }
21235
+ ));
21236
+ case "reference":
21237
+ return makePlan("string", "string", field, path21, required, commonConstraints(required, { kind: "referenceText" }));
21238
+ case "date":
21239
+ case "time":
21240
+ case "datetime":
21241
+ return makePlan("string", "string", field, path21, required, commonConstraints(required, { kind: "textType" }));
21242
+ case "select":
21243
+ return makePlan("select", "select", field, path21, required, commonConstraints(required, {
21244
+ kind: "selectOption",
21245
+ source: resolveSelectConstraintSource(field),
21246
+ multiple: Boolean(field.multiple)
21247
+ }));
21248
+ case "richText":
21249
+ return makePlan("richText", "object", field, path21, required, commonConstraints(required, { kind: "richTextDoc" }));
21250
+ case "media":
21251
+ return makePlan("media", "object", field, path21, required, commonConstraints(required, { kind: "mediaObject" }));
21252
+ case "link":
21253
+ return makePlan("link", "object", field, path21, required, commonConstraints(required, { kind: "linkObject" }));
21254
+ case "boolean":
21255
+ return makePlan("boolean", "boolean", field, path21, required, requiredConstraints(required));
21256
+ case "repeater":
21257
+ return {
21258
+ ...makePlan("repeater", "array", field, path21, required, commonConstraints(required, { kind: "arrayType" })),
21259
+ ...field.polymorphic && field.itemTypes ? { repeatedItemVariants: deriveRepeatedItemVariants(field, [...path21, 0]) } : { repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path21, 0]) },
21260
+ constraints: withRepeaterItemConstraints(field, commonConstraints(required, { kind: "arrayType" }))
21261
+ };
21262
+ case "group":
21263
+ case "modal":
21264
+ return {
21265
+ ...makePlan("group", "object", field, path21, required, requiredConstraints(required)),
21266
+ children: deriveNestedFieldPlans(field.schema?.fields ?? [], path21),
21267
+ allowNullChildren: field.type === "group" && field.ui?.widget === "locationPicker"
21268
+ };
21269
+ case "tabGroup":
21270
+ return {
21271
+ ...makePlan("group", "object", field, path21, required, requiredConstraints(required)),
21272
+ children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path21))
21273
+ };
21274
+ case "presetOrCustom":
21275
+ case "contentTypeSelect":
21276
+ case "entryPicker":
21277
+ return makePlan("passthrough", "unknown", field, path21, false, []);
21278
+ default:
21279
+ return assertNever2(field);
21301
21280
  }
21302
- return schema;
21303
21281
  }
21304
- function buildRepeaterSchema(field, allowNull, allowIncomplete) {
21305
- const parsed = fieldSchema.array().parse(field.schema?.fields ?? []);
21306
- const childShape = {};
21307
- for (const child of parsed) {
21282
+ function commonConstraints(required, ...specific) {
21283
+ return required ? [{ kind: "required" }, ...specific] : [...specific];
21284
+ }
21285
+ function requiredConstraints(required) {
21286
+ return required ? [{ kind: "required" }] : [];
21287
+ }
21288
+ function makePlan(kind, valueKind, field, path21, required, constraints) {
21289
+ return {
21290
+ kind,
21291
+ valueKind,
21292
+ fieldId: field.id,
21293
+ label: field.label,
21294
+ fieldType: field.type,
21295
+ path: path21,
21296
+ required,
21297
+ constraints
21298
+ };
21299
+ }
21300
+ function withRepeaterItemConstraints(field, constraints) {
21301
+ const next = [...constraints];
21302
+ if (typeof field.minItems === "number") next.push({ kind: "minItems", minimum: field.minItems });
21303
+ if (typeof field.maxItems === "number") next.push({ kind: "maxItems", maximum: field.maxItems });
21304
+ return next;
21305
+ }
21306
+ function deriveRepeatedItemVariants(field, parentPath) {
21307
+ return Object.entries(field.itemTypes ?? {}).map(([typeId, itemType]) => ({
21308
+ typeId,
21309
+ fields: deriveNestedFieldPlans(getFlattenedRepeaterFields(itemType.fields), parentPath)
21310
+ }));
21311
+ }
21312
+ function deriveNestedFieldPlans(fields3, parentPath) {
21313
+ return fields3.map((field) => deriveFieldValidationPlan(field, [...parentPath, field.id]));
21314
+ }
21315
+ function getRepeaterFields(field) {
21316
+ const fields3 = field.polymorphic && field.itemTypes ? Object.values(field.itemTypes).flatMap((itemType) => itemType.fields) : field.schema?.fields ?? [];
21317
+ return getFlattenedRepeaterFields(fields3);
21318
+ }
21319
+ function getFlattenedRepeaterFields(fields3) {
21320
+ return fields3.flatMap((child) => {
21308
21321
  if (child.type === "group" && child.ui?.flattenInRepeater) {
21309
- const groupParsed = fieldSchema.array().parse(child.schema?.fields ?? []);
21310
- for (const gc of groupParsed) {
21311
- childShape[gc.id] = buildFieldSchema(gc, allowNull, allowIncomplete);
21312
- }
21313
- } else {
21314
- childShape[child.id] = buildFieldSchema(child, allowNull, allowIncomplete);
21322
+ return child.schema?.fields ?? [];
21315
21323
  }
21324
+ return child;
21325
+ });
21326
+ }
21327
+ function resolveSelectConstraintSource(field) {
21328
+ const source = normalizeSelectSource(field);
21329
+ switch (source.kind) {
21330
+ case "static":
21331
+ return { kind: "static", values: field.options.map((option) => option.value) };
21332
+ case "site":
21333
+ case "sdk":
21334
+ return { kind: "runtime", source: source.kind };
21335
+ default:
21336
+ return assertNever2(source);
21316
21337
  }
21317
- let schema = z.object(childShape).catchall(z.unknown()).passthrough();
21318
- let arraySchema = z.array(schema);
21319
- if (typeof field.minItems === "number") {
21320
- arraySchema = arraySchema.min(field.minItems);
21338
+ }
21339
+ function normalizeFieldValue(plan, value, ctx) {
21340
+ switch (plan.kind) {
21341
+ case "number":
21342
+ return normalizeNumberInput(value, ctx.allowNull);
21343
+ case "string":
21344
+ return acceptsOptionalBlankAsMissing(plan, value) ? void 0 : value;
21345
+ case "group":
21346
+ return normalizeObjectChildren(plan.children, value, childValidationContext(plan, ctx));
21347
+ case "repeater":
21348
+ return normalizeRepeaterItems(plan, value, ctx);
21349
+ case "boolean":
21350
+ case "richText":
21351
+ case "media":
21352
+ case "link":
21353
+ case "select":
21354
+ case "passthrough":
21355
+ return value;
21356
+ default:
21357
+ return assertNever2(plan);
21321
21358
  }
21322
- if (typeof field.maxItems === "number") {
21323
- arraySchema = arraySchema.max(field.maxItems);
21359
+ }
21360
+ function normalizeObjectChildren(children, value, ctx) {
21361
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
21362
+ const normalized = { ...value };
21363
+ for (const child of children) {
21364
+ normalized[child.fieldId] = normalizeFieldValue(child, normalized[child.fieldId], ctx);
21324
21365
  }
21325
- return arraySchema;
21366
+ return normalized;
21367
+ }
21368
+ function normalizeRepeaterItems(plan, value, ctx) {
21369
+ if (!Array.isArray(value)) return value;
21370
+ return value.map((item) => {
21371
+ if (!item || typeof item !== "object" || Array.isArray(item)) return item;
21372
+ const itemRecord = item;
21373
+ const fields3 = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemRecord._type)?.fields : plan.repeatedItemPlan;
21374
+ if (!fields3) return item;
21375
+ return normalizeObjectChildren(fields3, itemRecord, ctx);
21376
+ });
21377
+ }
21378
+ function normalizeNumberInput(value, allowNull) {
21379
+ if (value === "") return void 0;
21380
+ if (typeof value === "string" && value.trim() !== "") return Number(value);
21381
+ return value;
21382
+ }
21383
+ function acceptsOptionalBlankAsMissing(plan, value) {
21384
+ if (plan.required || typeof value !== "string" || value.trim() !== "") return false;
21385
+ return plan.constraints.some(
21386
+ (constraint) => constraint.kind === "urlFormat" || constraint.kind === "slugFormat" || constraint.kind === "emailFormat" || constraint.kind === "phoneFormat" || constraint.kind === "patternFormat"
21387
+ );
21326
21388
  }
21327
- function buildGroupSchema(field, allowNull, allowIncomplete) {
21328
- const parsed = fieldSchema.array().parse(field.schema?.fields ?? []);
21329
- const childShape = {};
21330
- for (const child of parsed) {
21331
- childShape[child.id] = buildFieldSchema(child, allowNull, allowIncomplete);
21389
+ function validateNormalizedFieldValue(plan, value, ctx) {
21390
+ if (value === null && (ctx.allowNull || acceptsOptionalNullValue(plan))) return [];
21391
+ if (isMissingForPlan(plan, value)) {
21392
+ return shouldRequireValue(plan, value, ctx) ? [requiredIssue(plan, value)] : [];
21332
21393
  }
21333
- return z.object(childShape).catchall(z.unknown()).passthrough();
21394
+ switch (plan.kind) {
21395
+ case "string":
21396
+ return validateStringPlan(plan, value);
21397
+ case "number":
21398
+ return validateNumberPlan(plan, value);
21399
+ case "boolean":
21400
+ return typeof value === "boolean" ? [] : [issue(plan, "wrongType", { expected: "a true/false value" })];
21401
+ case "select":
21402
+ return validateSelectPlan(plan, value);
21403
+ case "richText":
21404
+ return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
21405
+ case "media":
21406
+ return isPlainObject(value) ? [] : [issue(plan, "invalidMedia")];
21407
+ case "link":
21408
+ return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
21409
+ case "repeater":
21410
+ return validateRepeaterPlan(plan, value, ctx);
21411
+ case "group":
21412
+ return validateGroupPlan(plan, value, ctx);
21413
+ case "passthrough":
21414
+ return [];
21415
+ default:
21416
+ return assertNever2(plan);
21417
+ }
21418
+ }
21419
+ function shouldRequireValue(plan, value, ctx) {
21420
+ if (!plan.required || ctx.allowIncomplete) return false;
21421
+ if (value === null && ctx.allowNull) return false;
21422
+ return true;
21423
+ }
21424
+ function acceptsOptionalNullValue(plan) {
21425
+ return !plan.required && (plan.kind === "media" || plan.kind === "number");
21426
+ }
21427
+ function isMissingForPlan(plan, value) {
21428
+ if (value === void 0) return true;
21429
+ if (value === null) return plan.required;
21430
+ if (typeof value === "string" && value.trim() === "") return true;
21431
+ if (Array.isArray(value) && value.length === 0) return true;
21432
+ return false;
21433
+ }
21434
+ function validateStringPlan(plan, value) {
21435
+ if (typeof value !== "string") return [issue(plan, "wrongType", { expected: "text" })];
21436
+ return plan.constraints.flatMap((constraint) => validateStringConstraint(plan, constraint, value));
21437
+ }
21438
+ function validateStringConstraint(plan, constraint, value) {
21439
+ switch (constraint.kind) {
21440
+ case "required":
21441
+ case "textType":
21442
+ case "referenceText":
21443
+ return [];
21444
+ case "maxLength":
21445
+ return value.length > constraint.maximum ? [issue(plan, "tooLong", { maximum: constraint.maximum })] : [];
21446
+ case "emailFormat":
21447
+ return z.email().safeParse(value).success ? [] : [issue(plan, "invalidEmail")];
21448
+ case "phoneFormat":
21449
+ return TEL_RE.test(value) ? [] : [issue(plan, "invalidPhone")];
21450
+ case "patternFormat": {
21451
+ const re = compilePattern(constraint.pattern);
21452
+ return re && !re.test(value) ? [issue(plan, "invalidPattern")] : [];
21453
+ }
21454
+ case "urlFormat":
21455
+ return isValidUrl(value, constraint.allowRelative) ? [] : [issue(plan, "invalidUrl")];
21456
+ case "slugFormat":
21457
+ return SLUG_PATTERN.test(value) ? [] : [issue(plan, "invalidSlug")];
21458
+ default:
21459
+ return assertNever2(constraint);
21460
+ }
21461
+ }
21462
+ function validateNumberPlan(plan, value) {
21463
+ if (!isValidNumber(value)) return [issue(plan, "invalidNumber")];
21464
+ return plan.constraints.flatMap((constraint) => validateNumberConstraint(plan, constraint, Number(value)));
21465
+ }
21466
+ function validateNumberConstraint(plan, constraint, value) {
21467
+ switch (constraint.kind) {
21468
+ case "required":
21469
+ case "numberType":
21470
+ return [];
21471
+ case "numberMin":
21472
+ return value < constraint.minimum ? [issue(plan, "tooSmall", { minimum: constraint.minimum })] : [];
21473
+ case "numberMax":
21474
+ return value > constraint.maximum ? [issue(plan, "tooLarge", { maximum: constraint.maximum })] : [];
21475
+ default:
21476
+ return assertNever2(constraint);
21477
+ }
21478
+ }
21479
+ function validateSelectPlan(plan, value) {
21480
+ const constraint = plan.constraints.find((candidate) => candidate.kind === "selectOption");
21481
+ if (!constraint || constraint.source.kind === "runtime") return [];
21482
+ return isValidSelectValue(value, constraint.source.values, constraint.multiple) ? [] : [issue(plan, "invalidOption")];
21483
+ }
21484
+ function validateRepeaterPlan(plan, value, ctx) {
21485
+ if (!Array.isArray(value)) return [issue(plan, "wrongType", { expected: "a list" })];
21486
+ const constraintIssues = plan.constraints.flatMap((constraint) => {
21487
+ switch (constraint.kind) {
21488
+ case "required":
21489
+ case "arrayType":
21490
+ return [];
21491
+ case "minItems":
21492
+ return value.length < constraint.minimum ? [issue(plan, "tooFewItems", { minimum: constraint.minimum, itemLabel: "item" })] : [];
21493
+ case "maxItems":
21494
+ return value.length > constraint.maximum ? [issue(plan, "tooManyItems", { maximum: constraint.maximum, itemLabel: "item" })] : [];
21495
+ default:
21496
+ return assertNever2(constraint);
21497
+ }
21498
+ });
21499
+ return [
21500
+ ...constraintIssues,
21501
+ ...value.flatMap((item, index) => validateRepeaterItem(plan, item, index, ctx))
21502
+ ];
21503
+ }
21504
+ function validateRepeaterItem(plan, item, index, ctx) {
21505
+ if (!isPlainObject(item)) return [];
21506
+ const itemType = item._type;
21507
+ const fields3 = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemType)?.fields : plan.repeatedItemPlan;
21508
+ if (!fields3) return [];
21509
+ return fields3.flatMap((childPlan) => {
21510
+ const indexedPlan = withIndexedPath(childPlan, plan.path, index);
21511
+ return validateNormalizedFieldValue(indexedPlan, item[childPlan.fieldId], ctx);
21512
+ });
21513
+ }
21514
+ function validateGroupPlan(plan, value, ctx) {
21515
+ if (!isPlainObject(value)) return [issue(plan, "wrongType", { expected: "an object" })];
21516
+ const childCtx = childValidationContext(plan, ctx);
21517
+ return plan.children.flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
21518
+ }
21519
+ function childValidationContext(plan, ctx) {
21520
+ return plan.allowNullChildren ? { ...ctx, allowNull: true } : ctx;
21521
+ }
21522
+ function withIndexedPath(plan, parentPath, index) {
21523
+ const suffix = plan.path.slice(parentPath.length + 1);
21524
+ return {
21525
+ ...plan,
21526
+ path: [...parentPath, index, plan.fieldId, ...suffix]
21527
+ };
21528
+ }
21529
+ function issue(plan, kind, extra) {
21530
+ return {
21531
+ kind,
21532
+ path: plan.path,
21533
+ fieldId: plan.fieldId,
21534
+ label: plan.label,
21535
+ ...extra ?? {}
21536
+ };
21334
21537
  }
21335
- function finalizeSchema(schema, required, allowNull, allowIncomplete = false) {
21336
- if (required) {
21337
- if (allowIncomplete) {
21338
- return allowNull ? schema.or(z.null()).optional() : schema.optional();
21538
+ function requiredIssue(plan, value) {
21539
+ if (typeof value === "string") return issue(plan, "required", { emptyOrigin: "string" });
21540
+ if (Array.isArray(value)) return issue(plan, "required", { emptyOrigin: "array" });
21541
+ return issue(plan, "required");
21542
+ }
21543
+ function fieldPlanToZod(plan, options = {}) {
21544
+ const ctx = validationContext(options);
21545
+ return z.any().transform((value) => normalizeFieldValue(plan, value, ctx)).superRefine((value, zodCtx) => {
21546
+ for (const validationIssue of validateNormalizedFieldValue(plan, value, ctx)) {
21547
+ addFieldIssueToZodContext(zodCtx, validationIssue);
21339
21548
  }
21340
- return allowNull ? schema.or(z.null()) : schema;
21549
+ });
21550
+ }
21551
+ function addFieldIssueToZodContext(zodCtx, validationIssue) {
21552
+ const message = fieldIssueToMessage(validationIssue);
21553
+ switch (validationIssue.kind) {
21554
+ case "required":
21555
+ if (validationIssue.emptyOrigin) {
21556
+ zodCtx.addIssue({
21557
+ code: "too_small",
21558
+ origin: validationIssue.emptyOrigin,
21559
+ minimum: 1,
21560
+ inclusive: true,
21561
+ message
21562
+ });
21563
+ return;
21564
+ }
21565
+ zodCtx.addIssue({ code: "invalid_type", expected: "nonoptional", message });
21566
+ return;
21567
+ case "tooLong":
21568
+ zodCtx.addIssue({
21569
+ code: "too_big",
21570
+ origin: "string",
21571
+ maximum: validationIssue.maximum,
21572
+ inclusive: true,
21573
+ message
21574
+ });
21575
+ return;
21576
+ case "invalidOption":
21577
+ zodCtx.addIssue({ code: "invalid_value", values: [], message });
21578
+ return;
21579
+ case "wrongType":
21580
+ case "invalidEmail":
21581
+ case "invalidPhone":
21582
+ case "invalidPattern":
21583
+ case "invalidUrl":
21584
+ case "invalidNumber":
21585
+ case "tooSmall":
21586
+ case "tooLarge":
21587
+ case "invalidSlug":
21588
+ case "tooFewItems":
21589
+ case "tooManyItems":
21590
+ case "invalidRichText":
21591
+ case "invalidMedia":
21592
+ case "invalidLink":
21593
+ case "invalidReference":
21594
+ zodCtx.addIssue({ code: "custom", message });
21595
+ return;
21596
+ default:
21597
+ assertNever2(validationIssue);
21598
+ }
21599
+ }
21600
+ function compilePattern(pattern) {
21601
+ try {
21602
+ return new RegExp(pattern);
21603
+ } catch {
21604
+ return null;
21605
+ }
21606
+ }
21607
+ function isValidNumber(value) {
21608
+ return typeof value === "number" && Number.isFinite(value);
21609
+ }
21610
+ function isValidUrl(value, allowRelative) {
21611
+ if (!value) return false;
21612
+ if (allowRelative && value.startsWith("/")) return true;
21613
+ try {
21614
+ const parsed = new URL(value);
21615
+ return ALLOWED_URL_PROTOCOLS.includes(parsed.protocol);
21616
+ } catch {
21617
+ return false;
21618
+ }
21619
+ }
21620
+ function isValidSelectValue(value, values, multiple) {
21621
+ if (multiple) {
21622
+ return Array.isArray(value) && value.every((item) => typeof item === "string" && values.includes(item));
21341
21623
  }
21342
- return allowNull ? schema.optional().nullable() : schema.optional();
21624
+ return typeof value === "string" && values.includes(value);
21625
+ }
21626
+ function isEmptyValue(value) {
21627
+ if (value === null || value === void 0) return true;
21628
+ if (typeof value === "string" && value.trim() === "") return true;
21629
+ if (Array.isArray(value) && value.length === 0) return true;
21630
+ if (isEmptyRichTextDoc(value)) return true;
21631
+ return false;
21632
+ }
21633
+ function isPlainObject(value) {
21634
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
21635
+ }
21636
+ function isValidRichTextDoc(value) {
21637
+ const doc = richTextDoc(value);
21638
+ return Boolean(isPlainObject(doc) && doc.type === "doc");
21639
+ }
21640
+ function isEmptyRichTextDoc(value) {
21641
+ const doc = richTextDoc(value);
21642
+ if (!isPlainObject(doc)) return false;
21643
+ if (doc.type !== "doc") return false;
21644
+ const content = doc.content;
21645
+ if (!Array.isArray(content) || content.length === 0) return true;
21646
+ if (content.length !== 1) return false;
21647
+ const first = content[0];
21648
+ return first?.type === "paragraph" && (!Array.isArray(first.content) || first.content.length === 0);
21649
+ }
21650
+ function richTextDoc(value) {
21651
+ if (!isPlainObject(value)) return value;
21652
+ return isPlainObject(value.doc) ? value.doc : value;
21653
+ }
21654
+
21655
+ // ../blocks/src/system/manifest/registry.ts
21656
+ var REGISTRY_SYMBOL = /* @__PURE__ */ Symbol.for("@riverbankcms/blocks/manifest-registry");
21657
+ var isVitest = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.VITEST === "true";
21658
+ var globalScope = globalThis;
21659
+ var manifestStore = isVitest ? /* @__PURE__ */ new Map() : globalScope[REGISTRY_SYMBOL] ??= /* @__PURE__ */ new Map();
21660
+ function registerManifest(manifest) {
21661
+ manifestStore.set(manifest.name, manifest);
21662
+ return manifest;
21663
+ }
21664
+ function preprocessEmptyValues(content) {
21665
+ if (!content || typeof content !== "object" || Array.isArray(content)) {
21666
+ return {};
21667
+ }
21668
+ const result = {};
21669
+ for (const [key, value] of Object.entries(content)) {
21670
+ result[key] = isEmptyValue(value) ? void 0 : value;
21671
+ }
21672
+ return result;
21673
+ }
21674
+ function createManifestValidator(manifestOrFields, options = {}) {
21675
+ const isDraft = options.mode === "draft";
21676
+ const shape = {};
21677
+ const fields3 = Array.isArray(manifestOrFields) ? manifestOrFields : manifestOrFields.fields ?? [];
21678
+ for (const field of fields3) {
21679
+ shape[field.id] = buildFieldSchema(field, options);
21680
+ }
21681
+ const baseSchema = z.object(shape).catchall(z.unknown()).passthrough();
21682
+ if (isDraft) {
21683
+ return z.preprocess(preprocessEmptyValues, baseSchema);
21684
+ }
21685
+ return baseSchema;
21686
+ }
21687
+ function buildFieldSchema(field, options) {
21688
+ return fieldPlanToZod(deriveFieldValidationPlan(field), options);
21343
21689
  }
21344
21690
 
21345
21691
  // ../theme-core/src/site-styles/types.ts
@@ -23302,8 +23648,8 @@ z.discriminatedUnion("kind", [
23302
23648
  }).strict()
23303
23649
  ]);
23304
23650
  function validateBlockSequence(snapshots, ctx) {
23305
- for (const issue of collectBlockSequenceIssues(snapshots)) {
23306
- ctx.addIssue(issue);
23651
+ for (const issue2 of collectBlockSequenceIssues(snapshots)) {
23652
+ ctx.addIssue(issue2);
23307
23653
  }
23308
23654
  }
23309
23655
  function collectBlockSequenceIssues(snapshots) {
@@ -24348,7 +24694,7 @@ var sectionStateToneTransform = {
24348
24694
  summary: "Map semantic section-state kind to feedback tone",
24349
24695
  run: (value) => sectionStateToneFromUnknown(value)
24350
24696
  };
24351
- function isPlainObject(value) {
24697
+ function isPlainObject2(value) {
24352
24698
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
24353
24699
  }
24354
24700
  function readString(obj, key) {
@@ -24394,7 +24740,7 @@ var heroContentWrapperClassTransform = {
24394
24740
  summary: "Resolve hero content wrapper className from alignment + max width controls",
24395
24741
  schema: heroContentWrapperClassSchema,
24396
24742
  run: (value, options, context) => {
24397
- const content = isPlainObject(value) ? value : isPlainObject(context.data) ? context.data : {};
24743
+ const content = isPlainObject2(value) ? value : isPlainObject2(context.data) ? context.data : {};
24398
24744
  const alignment = resolveHeroContentAlignment(content);
24399
24745
  const maxWidth = resolveHeroContentMaxWidth(content);
24400
24746
  const textAlignClass = alignment === "center" ? "rb-text-center" : alignment === "right" ? "rb-text-right" : "rb-text-left";
@@ -24413,7 +24759,7 @@ var heroCtaJustifyTransform = {
24413
24759
  kind: "string",
24414
24760
  summary: "Map hero contentAlignment to CTA row justify value",
24415
24761
  run: (value, _options, context) => {
24416
- const content = isPlainObject(value) ? value : isPlainObject(context.data) ? context.data : {};
24762
+ const content = isPlainObject2(value) ? value : isPlainObject2(context.data) ? context.data : {};
24417
24763
  const alignment = resolveHeroContentAlignment(content);
24418
24764
  return alignment === "left" ? "start" : alignment === "right" ? "end" : "center";
24419
24765
  }
@@ -24423,7 +24769,7 @@ var heroStackJustifyFromVerticalAlignmentTransform = {
24423
24769
  kind: "string",
24424
24770
  summary: "Map hero verticalAlignment to stack justify value",
24425
24771
  run: (value, _options, context) => {
24426
- const content = isPlainObject(value) ? value : isPlainObject(context.data) ? context.data : {};
24772
+ const content = isPlainObject2(value) ? value : isPlainObject2(context.data) ? context.data : {};
24427
24773
  const vertical = resolveHeroVerticalAlignment(content);
24428
24774
  return vertical === "top" ? "start" : vertical === "bottom" ? "end" : "center";
24429
24775
  }
@@ -24437,7 +24783,7 @@ var heroGridClassFromVerticalAlignmentTransform = {
24437
24783
  summary: "Append align-items class for hero split layouts based on verticalAlignment",
24438
24784
  schema: heroGridClassFromVerticalAlignmentSchema,
24439
24785
  run: (value, options, context) => {
24440
- const content = isPlainObject(value) ? value : isPlainObject(context.data) ? context.data : {};
24786
+ const content = isPlainObject2(value) ? value : isPlainObject2(context.data) ? context.data : {};
24441
24787
  const vertical = resolveHeroVerticalAlignment(content);
24442
24788
  const itemsClass = vertical === "top" ? "rb-items-start" : vertical === "bottom" ? "rb-items-end" : "rb-items-center";
24443
24789
  return joinClasses3([options.base, itemsClass]);
@@ -29077,7 +29423,25 @@ init_schema2();
29077
29423
  init_defineBlock();
29078
29424
  init_builder();
29079
29425
  init_fragments();
29426
+ init_media();
29080
29427
  var ITEM_NAME2 = "member";
29428
+ var teamMemberPhotoSchema = mediaSchema2.refine((media2) => media2.type === "image", {
29429
+ message: "Team member photos must be image media"
29430
+ }).nullable();
29431
+ var teamMemberDataSchema = z.object({
29432
+ _type: z.literal("teamMember"),
29433
+ id: z.string(),
29434
+ name: z.string(),
29435
+ role: z.string().nullable(),
29436
+ roleLabel: z.string().nullable(),
29437
+ bio: z.string().nullable(),
29438
+ summary: z.string().nullable(),
29439
+ photo: teamMemberPhotoSchema,
29440
+ profilePath: z.string().nullable()
29441
+ });
29442
+ var teamMembersDataSchema = z.array(teamMemberDataSchema);
29443
+ var dynamicSourceWhen = { equals: "site_staff" };
29444
+ var manualSourceWhen = { equals: "site_staff", not: true };
29081
29445
  var headingNode = text(
29082
29446
  { as: "h2" },
29083
29447
  bind("content.heading"),
@@ -29167,7 +29531,15 @@ var teamMemberStackLayout = el(
29167
29531
  ]
29168
29532
  ),
29169
29533
  stack({ gap: "sm", className: "rb-team-member-body rb-flex-1 rb-min-w-0" }, [
29170
- text({ as: "h3" }, bind("name")),
29534
+ link(
29535
+ {
29536
+ href: { $bind: { from: "profilePath" } },
29537
+ className: "rb-team-member-name-link"
29538
+ },
29539
+ [text({ as: "h3" }, bind("name"))],
29540
+ when("profilePath")
29541
+ ),
29542
+ text({ as: "h3" }, when("profilePath", { not: true }), bind("name")),
29171
29543
  text(
29172
29544
  { as: "p", className: "rb-team-member-role" },
29173
29545
  when("role"),
@@ -29181,12 +29553,18 @@ var teamMemberStackLayout = el(
29181
29553
  ])
29182
29554
  ]
29183
29555
  );
29184
- var gridMembersNode = repeaterFragmentLayout({
29556
+ var manualGridMembersNode = when("content.source", manualSourceWhen)(repeaterFragmentLayout({
29185
29557
  collectionPath: "content.members",
29186
29558
  itemName: ITEM_NAME2,
29187
29559
  fragments: { teamMember: teamMemberFragment },
29188
29560
  itemGap: "sm"
29189
- });
29561
+ }));
29562
+ var dynamicGridMembersNode = when("content.source", dynamicSourceWhen)(repeaterFragmentLayout({
29563
+ collectionPath: "data.members",
29564
+ itemName: ITEM_NAME2,
29565
+ fragments: { teamMember: teamMemberFragment },
29566
+ itemGap: "sm"
29567
+ }));
29190
29568
  var gridVariant = wrapVariant3(
29191
29569
  el(
29192
29570
  "grid",
@@ -29200,22 +29578,29 @@ var gridVariant = wrapVariant3(
29200
29578
  },
29201
29579
  gap: { $bind: { from: "content.gap", fallback: "medium" } }
29202
29580
  },
29203
- [gridMembersNode]
29581
+ [manualGridMembersNode, dynamicGridMembersNode]
29204
29582
  )
29205
29583
  );
29206
- var stackMembersNode = repeaterFragmentLayout({
29584
+ var manualStackMembersNode = when("content.source", manualSourceWhen)(repeaterFragmentLayout({
29207
29585
  collectionPath: "content.members",
29208
29586
  itemName: ITEM_NAME2,
29209
29587
  fragments: { teamMember: teamMemberFragment },
29210
29588
  layoutOverrides: { teamMember: teamMemberStackLayout },
29211
29589
  itemGap: "sm"
29212
- });
29590
+ }));
29591
+ var dynamicStackMembersNode = when("content.source", dynamicSourceWhen)(repeaterFragmentLayout({
29592
+ collectionPath: "data.members",
29593
+ itemName: ITEM_NAME2,
29594
+ fragments: { teamMember: teamMemberFragment },
29595
+ layoutOverrides: { teamMember: teamMemberStackLayout },
29596
+ itemGap: "sm"
29597
+ }));
29213
29598
  var stackVariant = wrapVariant3({
29214
29599
  type: "stack",
29215
29600
  props: {
29216
29601
  gap: { $bind: { from: "content.gap", fallback: "medium" } }
29217
29602
  },
29218
- children: [stackMembersNode]
29603
+ children: [manualStackMembersNode, dynamicStackMembersNode]
29219
29604
  });
29220
29605
  var teamMembersManifest = createBlockManifest({
29221
29606
  id: "block.team-members",
@@ -29230,6 +29615,18 @@ var teamMembersManifest = createBlockManifest({
29230
29615
  required: false,
29231
29616
  maxLength: 120
29232
29617
  }),
29618
+ parseFieldDefinition({
29619
+ id: "source",
29620
+ type: "select",
29621
+ label: "Team members",
29622
+ description: "Choose whether to use the site-wide team or a hand-picked list.",
29623
+ defaultValue: "manual",
29624
+ options: [
29625
+ { value: "manual", label: "Choose manually" },
29626
+ { value: "site_staff", label: "Use all site team members" }
29627
+ ],
29628
+ ui: { intent: "behavior" }
29629
+ }),
29233
29630
  parseFieldDefinition({
29234
29631
  id: "layoutAlign",
29235
29632
  type: "select",
@@ -29332,18 +29729,24 @@ var teamMembersManifest = createBlockManifest({
29332
29729
  ],
29333
29730
  ui: { intent: "display" }
29334
29731
  }),
29335
- fragmentsToRepeaterField(
29336
- "members",
29337
- "Team members",
29338
- { teamMember: teamMemberFragment },
29339
- {
29340
- minItems: 0,
29341
- maxItems: 50,
29342
- itemLabel: "Team member",
29343
- itemLabelSource: "name",
29344
- description: "Add people to this section."
29732
+ {
29733
+ ...fragmentsToRepeaterField(
29734
+ "members",
29735
+ "Team members",
29736
+ { teamMember: teamMemberFragment },
29737
+ {
29738
+ minItems: 0,
29739
+ maxItems: 50,
29740
+ itemLabel: "Team member",
29741
+ itemLabelSource: "name",
29742
+ description: "Add people to this section."
29743
+ }
29744
+ ),
29745
+ ui: {
29746
+ intent: "content",
29747
+ visibleWhen: { field: "source", equals: "manual" }
29345
29748
  }
29346
- )
29749
+ }
29347
29750
  ],
29348
29751
  layout: gridVariant,
29349
29752
  variants: {
@@ -29369,7 +29772,20 @@ var teamMembersManifest = createBlockManifest({
29369
29772
  styleTokens: { spacing: "lg" }
29370
29773
  });
29371
29774
  var teamMembersBlockDefinition = {
29372
- manifest: teamMembersManifest
29775
+ manifest: teamMembersManifest,
29776
+ dataSchemas: {
29777
+ members: teamMembersDataSchema
29778
+ },
29779
+ dataLoaders: {
29780
+ members: {
29781
+ endpoint: "listPublicTeamMembers",
29782
+ params: {
29783
+ siteId: { $bind: { from: "$root.siteId" } },
29784
+ stage: { $bind: { from: "$root.previewStage", fallback: "published" } }
29785
+ },
29786
+ mode: "server"
29787
+ }
29788
+ }
29373
29789
  };
29374
29790
 
29375
29791
  // ../blocks/src/system/blocks/location-map.ts
@@ -31781,6 +32197,71 @@ init_shadow2();
31781
32197
  // ../blocks/src/index.ts
31782
32198
  init_blocks();
31783
32199
  init_colorStyles();
32200
+ var Rfc6902PatchOp = z.discriminatedUnion("op", [
32201
+ // Standard RFC-6902 operations
32202
+ z.object({
32203
+ op: z.literal("add"),
32204
+ path: z.string(),
32205
+ value: z.unknown()
32206
+ }),
32207
+ z.object({
32208
+ op: z.literal("remove"),
32209
+ path: z.string()
32210
+ }),
32211
+ z.object({
32212
+ op: z.literal("replace"),
32213
+ path: z.string(),
32214
+ value: z.unknown()
32215
+ }),
32216
+ z.object({
32217
+ op: z.literal("move"),
32218
+ from: z.string(),
32219
+ path: z.string()
32220
+ }),
32221
+ z.object({
32222
+ op: z.literal("copy"),
32223
+ from: z.string(),
32224
+ path: z.string()
32225
+ }),
32226
+ // Block-level operations (Phase 2)
32227
+ z.object({
32228
+ op: z.literal("add_block"),
32229
+ blockKind: z.string(),
32230
+ afterBlockId: z.string().nullable(),
32231
+ content: z.record(z.string(), z.unknown()),
32232
+ rationale: z.string()
32233
+ }),
32234
+ z.object({
32235
+ op: z.literal("delete_block"),
32236
+ blockId: z.string(),
32237
+ rationale: z.string()
32238
+ }),
32239
+ z.object({
32240
+ op: z.literal("reorder_block"),
32241
+ blockId: z.string(),
32242
+ afterBlockId: z.string().nullable(),
32243
+ rationale: z.string()
32244
+ })
32245
+ ]);
32246
+ z.object({
32247
+ request: z.string().min(1).max(2e3)
32248
+ });
32249
+ var MultiPagePatchEnvelope = z.object({
32250
+ pageId: z.string(),
32251
+ blockId: z.string().optional(),
32252
+ // Not present for page-level ops
32253
+ blockKind: z.string().optional(),
32254
+ blockPurpose: z.string().optional().nullable(),
32255
+ ops: z.array(Rfc6902PatchOp),
32256
+ rationale: z.string(),
32257
+ currentContent: z.record(z.string(), z.unknown()).optional()
32258
+ });
32259
+ z.object({
32260
+ patches: z.array(MultiPagePatchEnvelope),
32261
+ assistantMessage: z.string(),
32262
+ pagesModified: z.number(),
32263
+ toolCallsUsed: z.number()
32264
+ });
31784
32265
 
31785
32266
  // src/types/block-kinds.ts
31786
32267
  var SYSTEM_BLOCK_KINDS = [
@@ -32009,7 +32490,7 @@ var fieldBindingSchema = z.object({
32009
32490
  var metaBindingSchema = z.object({
32010
32491
  source: z.literal("meta"),
32011
32492
  path: z.enum(TEMPLATE_BINDING_META_PATHS, {
32012
- error: (issue) => describeInvalidTemplateBindingMetaPath(String(issue.input))
32493
+ error: (issue2) => describeInvalidTemplateBindingMetaPath(String(issue2.input))
32013
32494
  })
32014
32495
  });
32015
32496
  var literalBindingSchema = z.object({
@@ -32020,7 +32501,7 @@ var transformBindingSchema = z.object({
32020
32501
  source: z.literal("transform"),
32021
32502
  path: z.string().min(1, "Transform path is required"),
32022
32503
  transform: z.enum(BINDING_TRANSFORM_VALUES, {
32023
- error: (issue) => describeInvalidBindingTransform(String(issue.input))
32504
+ error: (issue2) => describeInvalidBindingTransform(String(issue2.input))
32024
32505
  })
32025
32506
  });
32026
32507
  var baseBindingSchema = z.discriminatedUnion("source", [
@@ -32412,6 +32893,7 @@ var SUPPORTED_LOADER_ENDPOINTS2 = [
32412
32893
  "getPublishedEntryPreview",
32413
32894
  "listPublicEvents",
32414
32895
  "listPublicCourses",
32896
+ "listPublicTeamMembers",
32415
32897
  "listPublicProducts",
32416
32898
  "listPublicPasses",
32417
32899
  "listPublicMemberships",
@@ -34425,9 +34907,9 @@ async function pushConfigAction(output, options) {
34425
34907
  const parseResult = riverbankSiteConfigSchema.safeParse(rawConfig);
34426
34908
  if (!parseResult.success) {
34427
34909
  output.error("Invalid config", {
34428
- issues: parseResult.error.issues.map((issue) => ({
34429
- path: issue.path.join("."),
34430
- message: issue.message
34910
+ issues: parseResult.error.issues.map((issue2) => ({
34911
+ path: issue2.path.join("."),
34912
+ message: issue2.message
34431
34913
  }))
34432
34914
  });
34433
34915
  }
@@ -35361,7 +35843,7 @@ async function readSettings(contentDir) {
35361
35843
  if (!parsed.success) {
35362
35844
  throw new Error(
35363
35845
  `${filePath}: invalid settings.json
35364
- ` + parsed.error.issues.map((issue) => ` - ${issue.path.join(".") || "(root)"}: ${issue.message}`).join("\n")
35846
+ ` + parsed.error.issues.map((issue2) => ` - ${issue2.path.join(".") || "(root)"}: ${issue2.message}`).join("\n")
35365
35847
  );
35366
35848
  }
35367
35849
  return parsed.data;
@@ -38202,15 +38684,15 @@ function validateBlockContent(data, manifest, customFields) {
38202
38684
  validator.parse(data);
38203
38685
  } catch (error) {
38204
38686
  if (error instanceof ZodError) {
38205
- for (const issue of error.issues) {
38206
- const fieldPath = issue.path.join(".");
38207
- if (issue.code === "invalid_type" && issue.received === "undefined") {
38687
+ for (const issue2 of error.issues) {
38688
+ const fieldPath = issue2.path.join(".");
38689
+ if (issue2.code === "invalid_type" && issue2.received === "undefined") {
38208
38690
  continue;
38209
38691
  }
38210
38692
  warnings.push({
38211
38693
  type: "invalid_content",
38212
38694
  field: fieldPath || "(root)",
38213
- message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue.message}`
38695
+ message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue2.message}`
38214
38696
  });
38215
38697
  }
38216
38698
  }
@@ -41075,7 +41557,7 @@ async function handleThemePushForAllScope(params) {
41075
41557
  }
41076
41558
  const validation = themeSchema2.safeParse(localTheme.theme);
41077
41559
  if (!validation.success) {
41078
- const errors = validation.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
41560
+ const errors = validation.error.issues.map((issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`).join("\n");
41079
41561
  output.warn(
41080
41562
  `Skipping theme push - invalid theme at content/themes/${themeName}.json:
41081
41563
  ${errors}`
@@ -41788,7 +42270,7 @@ ${available.map((t) => ` - ${t.name} (content/themes/${t.name}.json)`).join("\n
41788
42270
  }
41789
42271
  const validation = themeSchema.safeParse(localTheme.theme);
41790
42272
  if (!validation.success) {
41791
- const errors = validation.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
42273
+ const errors = validation.error.issues.map((issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`).join("\n");
41792
42274
  output.error(
41793
42275
  `Invalid theme file at content/themes/${themeName}.json:
41794
42276
  ${errors}`
@@ -44876,7 +45358,7 @@ var SimpleCache = class {
44876
45358
  };
44877
45359
 
44878
45360
  // src/version.ts
44879
- var SDK_VERSION = "0.60.6";
45361
+ var SDK_VERSION = "0.60.9";
44880
45362
 
44881
45363
  // src/client/error.ts
44882
45364
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -45915,6 +46397,24 @@ function createRiverbankClient(config2) {
45915
46397
  return await apiClient({ endpoint: "listPublicCourses", params: apiParams, options: { signal: sig } });
45916
46398
  }, { signal });
45917
46399
  },
46400
+ async listPublicTeamMembers(params) {
46401
+ const { siteId, stage, signal } = params;
46402
+ if (!siteId) {
46403
+ throw new Error("listPublicTeamMembers() requires siteId");
46404
+ }
46405
+ const cacheKey = `public-team-members:${siteId}:${stage ?? ""}`;
46406
+ return resilientFetch(cacheKey, async (sig) => {
46407
+ const apiParams = {
46408
+ siteId,
46409
+ ...stage && { stage }
46410
+ };
46411
+ return await apiClient({
46412
+ endpoint: "listPublicTeamMembers",
46413
+ params: apiParams,
46414
+ options: { signal: sig }
46415
+ });
46416
+ }, { signal });
46417
+ },
45918
46418
  async listPublicProducts(params) {
45919
46419
  const { siteId, stage, categorySelector, signal } = params;
45920
46420
  if (!siteId) {
@@ -46661,9 +47161,9 @@ Examples:
46661
47161
  const parseResult = verifyConfigSchema.safeParse(rawConfig);
46662
47162
  if (!parseResult.success) {
46663
47163
  return output.error("Invalid config format", {
46664
- issues: parseResult.error.issues.map((issue) => ({
46665
- path: issue.path.join("."),
46666
- message: issue.message
47164
+ issues: parseResult.error.issues.map((issue2) => ({
47165
+ path: issue2.path.join("."),
47166
+ message: issue2.message
46667
47167
  })),
46668
47168
  suggestion: "Ensure your config exports a valid riverbank config object"
46669
47169
  });
@@ -47191,8 +47691,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
47191
47691
  client
47192
47692
  });
47193
47693
  const mediaIssues = mapMediaGuardDiagnosticsToAuditIssues(mediaGuardResult.diagnostics);
47194
- errors.push(...mediaIssues.filter((issue) => issue.severity === "error"));
47195
- warnings.push(...mediaIssues.filter((issue) => issue.severity === "warning"));
47694
+ errors.push(...mediaIssues.filter((issue2) => issue2.severity === "error"));
47695
+ warnings.push(...mediaIssues.filter((issue2) => issue2.severity === "warning"));
47196
47696
  }
47197
47697
  if (!isJsonOutput) {
47198
47698
  output.info("Checking for duplicate page paths...");
@@ -47216,8 +47716,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
47216
47716
  }
47217
47717
  errors.push(...auditEventReferences(localContent.events, auditCtx));
47218
47718
  const courseRefIssues = auditCourseReferences(localContent.courses, auditCtx);
47219
- errors.push(...courseRefIssues.filter((issue) => issue.severity === "error"));
47220
- warnings.push(...courseRefIssues.filter((issue) => issue.severity === "warning"));
47719
+ errors.push(...courseRefIssues.filter((issue2) => issue2.severity === "error"));
47720
+ warnings.push(...courseRefIssues.filter((issue2) => issue2.severity === "warning"));
47221
47721
  const success = errors.length === 0;
47222
47722
  const result = { success, errors, warnings };
47223
47723
  if (isJsonOutput) {
@@ -47232,14 +47732,14 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
47232
47732
  output.info("");
47233
47733
  if (errors.length > 0) {
47234
47734
  output.warn(`Found ${errors.length} error(s):`);
47235
- for (const issue of errors) {
47236
- output.info(` [ERROR] ${issue.message}`);
47735
+ for (const issue2 of errors) {
47736
+ output.info(` [ERROR] ${issue2.message}`);
47237
47737
  }
47238
47738
  }
47239
47739
  if (warnings.length > 0) {
47240
47740
  output.warn(`Found ${warnings.length} warning(s):`);
47241
- for (const issue of warnings) {
47242
- output.info(` [WARN] ${issue.message}`);
47741
+ for (const issue2 of warnings) {
47742
+ output.info(` [WARN] ${issue2.message}`);
47243
47743
  }
47244
47744
  }
47245
47745
  if (success && warnings.length === 0) {
@@ -51271,7 +51771,7 @@ Examples:
51271
51771
  $ riverbankcms course delete beginner-yoga --yes
51272
51772
  `
51273
51773
  ).addCommand(listCommand7).addCommand(getCommand6).addCommand(upsertCommand6).addCommand(cancelCommand2).addCommand(deleteCommand3);
51274
- function isPlainObject2(value) {
51774
+ function isPlainObject3(value) {
51275
51775
  return !!value && typeof value === "object" && !Array.isArray(value);
51276
51776
  }
51277
51777
  function migrateLegacyEntryTitleInPlace(entry) {
@@ -51279,7 +51779,7 @@ function migrateLegacyEntryTitleInPlace(entry) {
51279
51779
  const titleValue = entry.title;
51280
51780
  delete entry.title;
51281
51781
  let migratedToDataTitle = false;
51282
- if (typeof titleValue === "string" && isPlainObject2(entry.data)) {
51782
+ if (typeof titleValue === "string" && isPlainObject3(entry.data)) {
51283
51783
  const data = entry.data;
51284
51784
  if (!("title" in data)) {
51285
51785
  data.title = titleValue;
@@ -51305,7 +51805,7 @@ async function backupLegacyFile(contentDir, legacyFilePath, dryRun) {
51305
51805
  }
51306
51806
  async function migrateLegacyEntriesFile(contentDir, legacyFilePath, options) {
51307
51807
  const raw = await readJsonFile(legacyFilePath);
51308
- if (!isPlainObject2(raw)) {
51808
+ if (!isPlainObject3(raw)) {
51309
51809
  throw new Error(`Legacy entries file is not an object: ${legacyFilePath}`);
51310
51810
  }
51311
51811
  const contentType = raw.contentType;
@@ -51326,14 +51826,14 @@ async function migrateLegacyEntriesFile(contentDir, legacyFilePath, options) {
51326
51826
  let legacyTitlesMigrated = 0;
51327
51827
  let legacyTitleFilesUpdated = 0;
51328
51828
  for (const entryUnknown of entries) {
51329
- if (!isPlainObject2(entryUnknown)) {
51829
+ if (!isPlainObject3(entryUnknown)) {
51330
51830
  throw new Error(`Invalid legacy entry (expected object): ${legacyFilePath}`);
51331
51831
  }
51332
51832
  const identifier = entryUnknown.identifier;
51333
51833
  if (typeof identifier !== "string" || identifier.length === 0) {
51334
51834
  throw new Error(`Invalid legacy entry identifier in: ${legacyFilePath}`);
51335
51835
  }
51336
- if (!isPlainObject2(entryUnknown.data)) {
51836
+ if (!isPlainObject3(entryUnknown.data)) {
51337
51837
  throw new Error(`Invalid legacy entry data (expected object) for "${identifier}" in: ${legacyFilePath}`);
51338
51838
  }
51339
51839
  const { updated, migratedToDataTitle } = migrateLegacyEntryTitleInPlace(entryUnknown);
@@ -51368,7 +51868,7 @@ async function migrateLegacyTitlesInDirectory(typeDir, options) {
51368
51868
  for (const filePath of files) {
51369
51869
  scanned += 1;
51370
51870
  const raw = await readJsonFile(filePath);
51371
- if (!isPlainObject2(raw)) continue;
51871
+ if (!isPlainObject3(raw)) continue;
51372
51872
  const { updated, migratedToDataTitle } = migrateLegacyEntryTitleInPlace(raw);
51373
51873
  if (!updated) continue;
51374
51874
  updatedFiles += 1;