@riverbankcms/sdk 0.91.0 → 0.93.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.
Files changed (118) hide show
  1. package/dist/{PreviewEditorSidebar-3TT47WCF.mjs → PreviewEditorSidebar-D3PAF7NW.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-ORCLLUNZ.mjs → PreviewEditorUI-G5JVJEIJ.mjs} +3 -3
  3. package/dist/SdkPreviewModeRuntime-NHTLRNQD.mjs +8 -0
  4. package/dist/_dts/api/src/bookingConfig.d.ts +13 -1
  5. package/dist/_dts/api/src/bookingOperations.d.ts +1 -0
  6. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  7. package/dist/_dts/api/src/common/envelope.d.ts +10 -0
  8. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
  9. package/dist/_dts/api/src/index.d.ts +2 -2
  10. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +6 -0
  11. package/dist/_dts/api/src/request.d.ts +1 -1
  12. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +32 -0
  13. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +12 -1
  14. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +12 -0
  15. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +4 -1
  16. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +44 -0
  17. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +8 -0
  18. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +8 -1
  19. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
  20. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -0
  21. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
  22. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +40 -0
  23. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.reserved-fields.d.ts +1 -1
  24. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +29 -0
  25. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
  26. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +6 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +8 -0
  28. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +8 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +1 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +1 -1
  31. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +1 -0
  32. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -0
  33. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +14 -14
  34. package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +1 -1
  35. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +5 -15
  36. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +46 -0
  37. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +43 -36
  38. package/dist/_dts/content-model/src/entry-slots/types.d.ts +110 -2
  39. package/dist/_dts/core/src/branded.d.ts +3 -0
  40. package/dist/_dts/core/src/event-pricing.d.ts +18 -1
  41. package/dist/_dts/core/src/money-input.d.ts +34 -4
  42. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +70 -0
  43. package/dist/_dts/media-core/src/fileAssetCompatibility.d.ts +1 -1
  44. package/dist/_dts/media-core/src/filePersistence.d.ts +5 -1
  45. package/dist/_dts/media-core/src/fileStorage.d.ts +1 -0
  46. package/dist/_dts/media-core/src/fileUploadFinalization.d.ts +29 -1
  47. package/dist/_dts/media-core/src/index.d.ts +1 -0
  48. package/dist/_dts/media-core/src/legacyMediaValue.d.ts +11 -0
  49. package/dist/_dts/media-core/src/videoPrep.d.ts +15 -6
  50. package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +5 -5
  51. package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +2 -1
  52. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +2 -0
  53. package/dist/_dts/sdk/src/cli/commands/push/execute/localMediaReporting.d.ts +23 -0
  54. package/dist/_dts/sdk/src/cli/commands/push/scopes/commandBackedDatedOfferingScope.d.ts +54 -0
  55. package/dist/_dts/sdk/src/cli/commands/push/scopes/mediaPrep.d.ts +7 -2
  56. package/dist/_dts/sdk/src/cli/commands/push/scopes/types.d.ts +6 -0
  57. package/dist/_dts/sdk/src/cli/media/local-sync.d.ts +35 -0
  58. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +23 -1
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/{chunk-GDT2QGIL.mjs → chunk-A63UXN3P.mjs} +21 -19
  61. package/dist/{chunk-U5YM4AWE.mjs → chunk-AJZGT6YG.mjs} +1 -1
  62. package/dist/{chunk-AFPMCLS7.mjs → chunk-AQ6RT6LZ.mjs} +2 -2
  63. package/dist/{chunk-ZA2S7H34.mjs → chunk-NT76QGIJ.mjs} +98 -1
  64. package/dist/{chunk-RQUZYSES.mjs → chunk-PCNCETBI.mjs} +1196 -426
  65. package/dist/{chunk-S3YHJWEU.mjs → chunk-XIK2HYI3.mjs} +7 -7
  66. package/dist/cli/index.mjs +749 -166
  67. package/dist/client/{accordion-AFX37652.mjs → accordion-RNQIPG55.mjs} +2 -2
  68. package/dist/client/{bookingForm-32V5QCOW.mjs → bookingForm-HYEEVRLP.mjs} +89 -14
  69. package/dist/client/bookings.mjs +243 -17
  70. package/dist/client/{carousel-TJGQJ7ER.mjs → carousel-W7DQ3YPU.mjs} +3 -3
  71. package/dist/client/{cart-JUU2JEW4.mjs → cart-PXJ3SXXO.mjs} +7 -7
  72. package/dist/client/{checkout-RD6BTFX4.mjs → checkout-X3JYSOXI.mjs} +7 -7
  73. package/dist/client/{chunk-MLBNVN4H.mjs → chunk-6SYGVVWA.mjs} +67 -4
  74. package/dist/client/{chunk-E6VIWZUG.mjs → chunk-DUOHLWLF.mjs} +3 -3
  75. package/dist/client/{chunk-6QZIBNGV.mjs → chunk-IXDSXF2D.mjs} +154 -16
  76. package/dist/client/{chunk-CKXEUWWA.mjs → chunk-J6TMMMXW.mjs} +3 -3
  77. package/dist/client/{chunk-PMNAV6LO.mjs → chunk-JNE6UI6U.mjs} +7 -6
  78. package/dist/client/{chunk-ISAUXU5R.mjs → chunk-OLAOAZEO.mjs} +1 -1
  79. package/dist/client/{chunk-RWYFG625.mjs → chunk-PCHACQEB.mjs} +30 -2
  80. package/dist/client/{chunk-FMZZHAIR.mjs → chunk-PICR3NTQ.mjs} +52 -5
  81. package/dist/client/{chunk-6RN62XBV.mjs → chunk-Q47XGAGS.mjs} +1 -1
  82. package/dist/client/{chunk-WHZQDPBZ.mjs → chunk-TNGL2WJF.mjs} +1 -0
  83. package/dist/client/{chunk-C4LP6BPG.mjs → chunk-WERRJXNJ.mjs} +1 -1
  84. package/dist/client/{chunk-RMOFBBNA.mjs → chunk-YYVGSYBO.mjs} +6 -6
  85. package/dist/client/client.mjs +641 -54
  86. package/dist/client/{courseRegistration-X63QAIVV.mjs → courseRegistration-QZ67PVHO.mjs} +111 -11
  87. package/dist/client/{eventCalendar-5T24GCZL.mjs → eventCalendar-V3BDHQNT.mjs} +9 -9
  88. package/dist/client/{eventCombined-AZVTF22X.mjs → eventCombined-XYFRN2RG.mjs} +9 -9
  89. package/dist/client/{eventDetails-7GPFNLGF.mjs → eventDetails-TFE5TWKV.mjs} +9 -9
  90. package/dist/client/{eventListing-QEUMTMUM.mjs → eventListing-IQ6AGWZ6.mjs} +9 -9
  91. package/dist/client/{eventRegistration-P2EDKCQZ.mjs → eventRegistration-WGJVFKQJ.mjs} +9 -9
  92. package/dist/client/{form-NUJ7H4IN.mjs → form-6UZY6RUA.mjs} +3 -3
  93. package/dist/client/{headerSection-JB7LECPL.mjs → headerSection-RSFXY6V3.mjs} +3 -3
  94. package/dist/client/hooks.mjs +57 -5
  95. package/dist/client/{locationMap-UEYWUCSW.mjs → locationMap-24FH67I4.mjs} +3 -3
  96. package/dist/client/{newsletterForm-S2YZQ2X7.mjs → newsletterForm-QVL3MLTN.mjs} +3 -3
  97. package/dist/client/{productDetail-H5MADGG7.mjs → productDetail-ZDYN3G4T.mjs} +7 -7
  98. package/dist/client/{productList-DK7YON7H.mjs → productList-4BMJLQHZ.mjs} +7 -7
  99. package/dist/client/rendering/client.mjs +503 -36
  100. package/dist/client/rendering/islands.mjs +19 -19
  101. package/dist/client/rendering.mjs +583 -39
  102. package/dist/client/{shop-6PA7RDRJ.mjs → shop-U5C634FF.mjs} +7 -7
  103. package/dist/preview-next/client/runtime.mjs +5 -5
  104. package/dist/{sdk-runtime-JP5347OB.mjs → sdk-runtime-VGV46WVB.mjs} +6 -6
  105. package/dist/server/components.mjs +287 -68
  106. package/dist/server/config-validation.mjs +58 -5
  107. package/dist/server/config.mjs +58 -5
  108. package/dist/server/data.mjs +57 -5
  109. package/dist/server/index.mjs +104 -29
  110. package/dist/server/next.mjs +347 -85
  111. package/dist/server/page-converter.mjs +22 -5
  112. package/dist/server/prebuild.mjs +1 -1
  113. package/dist/server/rendering/server.mjs +287 -68
  114. package/dist/server/rendering.mjs +287 -68
  115. package/dist/server/routing.mjs +131 -67
  116. package/dist/server/server.mjs +189 -94
  117. package/package.json +1 -1
  118. package/dist/SdkPreviewModeRuntime-GMCDQPZZ.mjs +0 -8
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { ApiRequestError } from './chunk-ZA2S7H34.mjs';
2
+ import { unwrapResponse, ApiRequestError, ApiEnvelopeError, extractApiEnvelopeErrorDetails } from './chunk-NT76QGIJ.mjs';
3
3
  import { __commonJS, __export, __toESM } from './chunk-R7POPVJR.mjs';
4
4
  import * as React61 from 'react';
5
5
  import React61__default, { createContext, forwardRef, useContext, createElement, useRef, useMemo, useEffect, useState, useCallback, useImperativeHandle, useLayoutEffect, memo, createRef, Component as Component$1, useDebugValue, useId as useId$1, useSyncExternalStore, isValidElement, cloneElement, useReducer, startTransition } from 'react';
@@ -129,6 +129,8 @@ function expectParsedBrandedId(result) {
129
129
  }
130
130
  var unsafeAsSiteId = (id) => id;
131
131
  var unsafeAsMediaAssetId = (id) => id;
132
+ var unsafeAsStoragePath = (value) => value;
133
+ var unsafeAsPositiveByteCount = (value) => value;
132
134
  var unsafeAsFormId = (id) => id;
133
135
  var unsafeAsPassId = (id) => id;
134
136
  var unsafeAsCustomerPassId = (id) => id;
@@ -207,6 +209,7 @@ function publicEventPricingType(pricing) {
207
209
  return "free";
208
210
  case "single_paid":
209
211
  case "ticket_types":
212
+ case "sliding_scale":
210
213
  case "course":
211
214
  return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
212
215
  case "external":
@@ -219,6 +222,7 @@ function publicEventPricingCurrency(pricing) {
219
222
  case "free_registration":
220
223
  case "single_paid":
221
224
  case "ticket_types":
225
+ case "sliding_scale":
222
226
  return pricing.currency;
223
227
  case "course":
224
228
  return pricing.display.display.currency;
@@ -236,6 +240,8 @@ function publicEventPricingMode(pricing) {
236
240
  return "single";
237
241
  case "ticket_types":
238
242
  return "ticket_types";
243
+ case "sliding_scale":
244
+ return "sliding_scale";
239
245
  case "drop_in":
240
246
  case "course":
241
247
  case "external":
@@ -269,6 +275,8 @@ function formatCoursePriceDisplayLabel(display, options) {
269
275
  return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
270
276
  case "from":
271
277
  return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
278
+ case "range":
279
+ return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
272
280
  default:
273
281
  return assertNever(display);
274
282
  }
@@ -30334,68 +30342,24 @@ function resolveBlockTitle(manifest, blockContent, blockKind) {
30334
30342
  showSubtitle
30335
30343
  };
30336
30344
  }
30337
- var nullableString = z.union([z.string().min(1), z.null()]);
30338
- var resolvedInternalLinkKeys = ["entityId", "entityType", "href", "title", "typeLabel"];
30339
- var internalRouteOnlyLinkSchema = z.object({
30340
- kind: z.literal("internal"),
30341
- routeId: z.string().min(1)
30342
- }).passthrough().superRefine((value, ctx) => {
30343
- const hasResolvedMetadata = resolvedInternalLinkKeys.some((key) => value[key] != null);
30344
- if (!hasResolvedMetadata) return;
30345
- ctx.addIssue({
30346
- code: "custom",
30347
- message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
30348
- });
30349
- });
30350
- var internalResolvedLinkSchema = z.object({
30351
- kind: z.literal("internal"),
30352
- routeId: z.string().min(1),
30353
- entityId: z.string().min(1),
30354
- entityType: z.enum(["page", "content"]),
30355
- href: z.string().min(1),
30356
- title: z.string().min(1),
30357
- typeLabel: z.string().min(1),
30358
- contentTypeKey: nullableString.optional(),
30359
- contentTypeName: nullableString.optional(),
30360
- updatedAt: nullableString.optional()
30361
- }).passthrough();
30362
- var internalLinkSchema = z.union([
30363
- internalResolvedLinkSchema,
30364
- internalRouteOnlyLinkSchema
30365
- ]);
30366
- var externalLinkSchema = z.object({
30367
- kind: z.literal("external"),
30368
- href: z.string().min(1)
30369
- }).passthrough();
30370
- var customLinkSchema = z.object({
30371
- kind: z.literal("url"),
30372
- href: z.string().min(1)
30373
- }).passthrough();
30374
- var pageLinkSchema = z.object({
30375
- kind: z.literal("page"),
30376
- identifier: z.string().min(1)
30377
- }).passthrough();
30378
- var entryLinkSchema = z.object({
30379
- kind: z.literal("entry"),
30380
- contentType: z.string().min(1),
30381
- identifier: z.string().min(1)
30382
- }).passthrough();
30383
- var linkSchema = z.union([
30384
- internalLinkSchema,
30385
- externalLinkSchema,
30386
- customLinkSchema,
30387
- pageLinkSchema,
30388
- entryLinkSchema
30389
- ]);
30390
- function isInternalResolvedLinkValue(value) {
30391
- return value?.kind === "internal" && "entityId" in value && "entityType" in value && "href" in value && "title" in value && "typeLabel" in value && typeof value.entityId === "string" && typeof value.entityType === "string" && typeof value.href === "string" && typeof value.title === "string" && typeof value.typeLabel === "string";
30392
- }
30393
30345
 
30394
30346
  // ../media-core/src/types.ts
30395
30347
  var SVG_MIME_TYPE = "image/svg+xml";
30396
30348
  function isSvgMimeType(mimeType) {
30397
30349
  return mimeType === SVG_MIME_TYPE;
30398
30350
  }
30351
+
30352
+ // ../media-core/src/fileSafety.ts
30353
+ var CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
30354
+ function containsUnsafePathSegmentCharacter(value) {
30355
+ return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
30356
+ }
30357
+ function isReservedPathSegment(value) {
30358
+ return value === "." || value === "..";
30359
+ }
30360
+ function isUnsafePathSegment(segment) {
30361
+ return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
30362
+ }
30399
30363
  function classifyKnownMimeType(mimeType) {
30400
30364
  const normalized = normalizeMimeType(mimeType);
30401
30365
  switch (normalized) {
@@ -30462,6 +30426,15 @@ function classifyKnownMimeType(mimeType) {
30462
30426
  function normalizeMimeType(mimeType) {
30463
30427
  return (mimeType ?? "").split(";", 1)[0]?.trim().toLowerCase() ?? "";
30464
30428
  }
30429
+ function parseStoragePath(value) {
30430
+ return joinStoragePathSegments(value.split("/"));
30431
+ }
30432
+ function joinStoragePathSegments(segments) {
30433
+ if (segments.some(isUnsafePathSegment)) {
30434
+ return err("unsafe-path-segment");
30435
+ }
30436
+ return ok(unsafeAsStoragePath(segments.join("/")));
30437
+ }
30465
30438
 
30466
30439
  // ../media-core/src/typeGuards.ts
30467
30440
  function isRecord(value) {
@@ -30473,11 +30446,20 @@ function asRecord(value) {
30473
30446
 
30474
30447
  // ../media-core/src/videoPrep.ts
30475
30448
  var VIDEO_PREP_LIMITS = {
30476
- maxRawByteCount: 500 * 1024 * 1024,
30477
- inlineContentMaxDurationSeconds: 60,
30478
- backgroundVideoMaxDurationSeconds: 30,
30449
+ maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
30450
+ inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
30451
+ backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
30479
30452
  targetMaxDimensionPixels: 1080
30480
30453
  };
30454
+ function unsafeAsPositiveVideoDurationSeconds(value) {
30455
+ return value;
30456
+ }
30457
+ function asPositiveVideoDurationSeconds(value) {
30458
+ if (!Number.isFinite(value) || value <= 0) {
30459
+ return err("not-positive-video-duration-seconds");
30460
+ }
30461
+ return ok(unsafeAsPositiveVideoDurationSeconds(value));
30462
+ }
30481
30463
  function deriveVideoPrepPolicy(intent) {
30482
30464
  switch (intent.tag) {
30483
30465
  case "files-and-media":
@@ -30528,14 +30510,16 @@ function evaluateVideoSlotAssetPolicy(asset, policy) {
30528
30510
  if (!isVideoMimeType(asset.mimeType)) {
30529
30511
  return { tag: "not-video" };
30530
30512
  }
30531
- const durationSeconds = asset.durationSeconds;
30532
- if (!Number.isFinite(durationSeconds) || durationSeconds == null || durationSeconds <= 0) {
30513
+ const durationSeconds = asPositiveVideoDurationSeconds(
30514
+ asset.durationSeconds ?? Number.NaN
30515
+ );
30516
+ if (!durationSeconds.ok) {
30533
30517
  return { tag: "duration-unknown", maxSeconds: policy.maxDurationSeconds };
30534
30518
  }
30535
- if (durationSeconds > policy.maxDurationSeconds) {
30519
+ if (durationSeconds.value > policy.maxDurationSeconds) {
30536
30520
  return {
30537
30521
  tag: "duration-too-long",
30538
- actualSeconds: durationSeconds,
30522
+ actualSeconds: durationSeconds.value,
30539
30523
  maxSeconds: policy.maxDurationSeconds
30540
30524
  };
30541
30525
  }
@@ -30591,10 +30575,10 @@ var RELATIVE_STORAGE_PATH_PREFIXES = [
30591
30575
  "imports/"
30592
30576
  ];
30593
30577
  function isRelativeDirectImageStoragePath(storagePath) {
30594
- return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
30578
+ return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
30595
30579
  }
30596
30580
  function isSiteScopedDirectImageStoragePath(storagePath) {
30597
- return storagePath.startsWith("sites/");
30581
+ return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
30598
30582
  }
30599
30583
  function encodeStoragePath(storagePath) {
30600
30584
  return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
@@ -30913,6 +30897,79 @@ function mediaIdentifierOrFallback(current, fallback2) {
30913
30897
  if (typeof current === "string" && current.trim().length > 0) return current;
30914
30898
  return fallback2 ?? (typeof current === "string" ? current : void 0);
30915
30899
  }
30900
+
30901
+ // ../media-core/src/legacyMediaValue.ts
30902
+ function legacyStringMediaTypeForField(field) {
30903
+ if (field.type === "file") {
30904
+ return field.fileKinds?.[0] ?? "document";
30905
+ }
30906
+ return field.mediaKinds?.[0] ?? "image";
30907
+ }
30908
+ function normalizeLegacyStringMediaValueForField(value, field) {
30909
+ if (typeof value !== "string") return value;
30910
+ const src = value.trim();
30911
+ if (!src) return value;
30912
+ return {
30913
+ type: legacyStringMediaTypeForField(field),
30914
+ src
30915
+ };
30916
+ }
30917
+ var nullableString = z.union([z.string().min(1), z.null()]);
30918
+ var resolvedInternalLinkKeys = ["entityId", "entityType", "href", "title", "typeLabel"];
30919
+ var internalRouteOnlyLinkSchema = z.object({
30920
+ kind: z.literal("internal"),
30921
+ routeId: z.string().min(1)
30922
+ }).passthrough().superRefine((value, ctx) => {
30923
+ const hasResolvedMetadata = resolvedInternalLinkKeys.some((key) => value[key] != null);
30924
+ if (!hasResolvedMetadata) return;
30925
+ ctx.addIssue({
30926
+ code: "custom",
30927
+ message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
30928
+ });
30929
+ });
30930
+ var internalResolvedLinkSchema = z.object({
30931
+ kind: z.literal("internal"),
30932
+ routeId: z.string().min(1),
30933
+ entityId: z.string().min(1),
30934
+ entityType: z.enum(["page", "content"]),
30935
+ href: z.string().min(1),
30936
+ title: z.string().min(1),
30937
+ typeLabel: z.string().min(1),
30938
+ contentTypeKey: nullableString.optional(),
30939
+ contentTypeName: nullableString.optional(),
30940
+ updatedAt: nullableString.optional()
30941
+ }).passthrough();
30942
+ var internalLinkSchema = z.union([
30943
+ internalResolvedLinkSchema,
30944
+ internalRouteOnlyLinkSchema
30945
+ ]);
30946
+ var externalLinkSchema = z.object({
30947
+ kind: z.literal("external"),
30948
+ href: z.string().min(1)
30949
+ }).passthrough();
30950
+ var customLinkSchema = z.object({
30951
+ kind: z.literal("url"),
30952
+ href: z.string().min(1)
30953
+ }).passthrough();
30954
+ var pageLinkSchema = z.object({
30955
+ kind: z.literal("page"),
30956
+ identifier: z.string().min(1)
30957
+ }).passthrough();
30958
+ var entryLinkSchema = z.object({
30959
+ kind: z.literal("entry"),
30960
+ contentType: z.string().min(1),
30961
+ identifier: z.string().min(1)
30962
+ }).passthrough();
30963
+ var linkSchema = z.union([
30964
+ internalLinkSchema,
30965
+ externalLinkSchema,
30966
+ customLinkSchema,
30967
+ pageLinkSchema,
30968
+ entryLinkSchema
30969
+ ]);
30970
+ function isInternalResolvedLinkValue(value) {
30971
+ return value?.kind === "internal" && "entityId" in value && "entityType" in value && "href" in value && "title" in value && "typeLabel" in value && typeof value.entityId === "string" && typeof value.entityType === "string" && typeof value.href === "string" && typeof value.title === "string" && typeof value.typeLabel === "string";
30972
+ }
30916
30973
  var transformStepSchema = z.object({
30917
30974
  id: z.string().min(1, "Transform requires an identifier"),
30918
30975
  options: z.record(z.string(), z.unknown()).optional()
@@ -32946,7 +33003,10 @@ function deriveFieldValidationPlan(field, path = [field.id]) {
32946
33003
  return makePlan("richText", "object", field, path, required, commonConstraints(required, { kind: "richTextDoc" }));
32947
33004
  case "media":
32948
33005
  case "file":
32949
- return makePlan("media", "object", field, path, required, commonConstraints(required, { kind: "mediaObject" }));
33006
+ return {
33007
+ ...makePlan("media", "object", field, path, required, commonConstraints(required, { kind: "mediaObject" })),
33008
+ legacyStringType: legacyStringMediaTypeForField(field)
33009
+ };
32950
33010
  case "link":
32951
33011
  return makePlan("link", "object", field, path, required, commonConstraints(required, { kind: "linkObject" }));
32952
33012
  case "boolean":
@@ -33131,15 +33191,23 @@ function normalizeFieldValue(plan, value, ctx) {
33131
33191
  return normalizeRepeaterItems(plan, value, ctx);
33132
33192
  case "boolean":
33133
33193
  case "richText":
33134
- case "media":
33135
33194
  case "link":
33136
33195
  case "select":
33137
33196
  case "passthrough":
33138
33197
  return value;
33198
+ case "media":
33199
+ return normalizeMediaInput(plan, value);
33139
33200
  default:
33140
33201
  return assertNever4(plan);
33141
33202
  }
33142
33203
  }
33204
+ function normalizeMediaInput(plan, value) {
33205
+ return normalizeLegacyStringMediaValueForField(value, {
33206
+ type: plan.fieldType,
33207
+ mediaKinds: plan.fieldType === "media" ? [plan.legacyStringType] : void 0,
33208
+ fileKinds: plan.fieldType === "file" ? [plan.legacyStringType] : void 0
33209
+ });
33210
+ }
33143
33211
  function normalizeObjectChildren(children, value, ctx) {
33144
33212
  if (!value || typeof value !== "object" || Array.isArray(value)) return value;
33145
33213
  const normalized = {
@@ -33403,6 +33471,21 @@ function fieldPlanToZod(plan, options = {}) {
33403
33471
  }
33404
33472
  });
33405
33473
  }
33474
+ function fieldPresenceForPlan(plan) {
33475
+ return plan.required ? { kind: "required" } : { kind: "optional" };
33476
+ }
33477
+ function fieldPlanToObjectPropertyZod(plan, options = {}) {
33478
+ const schema = fieldPlanToZod(plan, options);
33479
+ const presence = fieldPresenceForPlan(plan);
33480
+ switch (presence.kind) {
33481
+ case "required":
33482
+ return schema;
33483
+ case "optional":
33484
+ return schema.optional();
33485
+ default:
33486
+ return assertNever4(presence);
33487
+ }
33488
+ }
33406
33489
  function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
33407
33490
  const message2 = fieldIssueToMessage(validationIssue);
33408
33491
  const path = relativeZodIssuePath(validationIssue.path, rootPath);
@@ -33669,7 +33752,7 @@ function createManifestValidator(manifestOrFields, options = {}) {
33669
33752
  function deriveContentZodFromPlans(plans, options) {
33670
33753
  const shape = {};
33671
33754
  for (const plan of plans) {
33672
- shape[plan.fieldId] = fieldPlanToZod(plan, options);
33755
+ shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
33673
33756
  }
33674
33757
  return z.object(shape).catchall(z.unknown()).passthrough();
33675
33758
  }
@@ -60130,9 +60213,12 @@ var coursePricingOptionSchema = z.object({
60130
60213
  });
60131
60214
  var coursePricingSchema = z.object({
60132
60215
  bookingRequirement: z.enum(["none", "required"]),
60133
- pricingStrategy: z.enum(["free", "single", "tiered"]),
60216
+ pricingStrategy: z.enum(["free", "single", "tiered", "sliding_scale"]),
60134
60217
  currency: z.string(),
60135
60218
  singlePriceAmount: z.number().nullable(),
60219
+ slidingMinAmount: z.number().nullable().optional(),
60220
+ slidingMaxAmount: z.number().nullable().optional(),
60221
+ slidingSuggestedAmount: z.number().nullable().optional(),
60136
60222
  paymentTerms: blockBookingPaymentTermsSchema,
60137
60223
  options: z.array(coursePricingOptionSchema)
60138
60224
  });
@@ -60286,6 +60372,19 @@ var publicEventPricingSchema = z.discriminatedUnion("kind", [
60286
60372
  ticketTypes: z.array(publicEventTicketTypeSchema),
60287
60373
  display: publicEventTicketTypePriceDisplaySchema
60288
60374
  }),
60375
+ z.object({
60376
+ kind: z.literal("sliding_scale"),
60377
+ minAmount: z.number(),
60378
+ maxAmount: z.number(),
60379
+ suggestedAmount: z.number().nullable(),
60380
+ currency: z.string(),
60381
+ display: z.object({
60382
+ kind: z.literal("range"),
60383
+ minAmount: z.number(),
60384
+ maxAmount: z.number(),
60385
+ currency: z.string()
60386
+ })
60387
+ }),
60289
60388
  z.object({
60290
60389
  kind: z.literal("course"),
60291
60390
  display: z.object({ kind: z.literal("course"), display: publicCoursePriceDisplaySchema })
@@ -60694,7 +60793,7 @@ function isRecord7(value) {
60694
60793
  }
60695
60794
  function isPublicEventPricing(value) {
60696
60795
  if (!isRecord7(value) || typeof value.kind !== "string") return false;
60697
- return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
60796
+ return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
60698
60797
  }
60699
60798
  function isPublicEventTicketType(value) {
60700
60799
  return isRecord7(value) && typeof value.id === "string";
@@ -61335,7 +61434,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
61335
61434
  return left.name.localeCompare(right.name);
61336
61435
  });
61337
61436
  }
61338
- function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
61437
+ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
61438
+ const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
61439
+ const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
61339
61440
  const currency = course.pricing?.currency ?? course.currency;
61340
61441
  if (!course.pricing) {
61341
61442
  const legacyAmount = course.priceCents ?? 0;
@@ -61345,6 +61446,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
61345
61446
  selectableOptions: [],
61346
61447
  requiresSelection: false,
61347
61448
  selectedOption: null,
61449
+ slidingScale: null,
61450
+ selectedSlidingAmount: null,
61348
61451
  selectedPriceAmount: legacyAmount,
61349
61452
  selectedRequiresPayment: legacyAmount > 0,
61350
61453
  hasPaidSelection: legacyAmount > 0,
@@ -61359,6 +61462,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
61359
61462
  selectableOptions: [],
61360
61463
  requiresSelection: false,
61361
61464
  selectedOption: null,
61465
+ slidingScale: null,
61466
+ selectedSlidingAmount: null,
61362
61467
  selectedPriceAmount: 0,
61363
61468
  selectedRequiresPayment: false,
61364
61469
  hasPaidSelection: false,
@@ -61372,6 +61477,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
61372
61477
  selectableOptions: [],
61373
61478
  requiresSelection: false,
61374
61479
  selectedOption: null,
61480
+ slidingScale: null,
61481
+ selectedSlidingAmount: null,
61375
61482
  selectedPriceAmount: amount,
61376
61483
  selectedRequiresPayment: amount > 0,
61377
61484
  hasPaidSelection: amount > 0,
@@ -61381,7 +61488,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
61381
61488
  case "tiered": {
61382
61489
  const selectableOptions = getSelectableCoursePricingOptionsForNow(
61383
61490
  course,
61384
- resolvePlanningDateInput(nowInput)
61491
+ resolvePlanningDateInput(effectiveNowInput)
61385
61492
  );
61386
61493
  const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
61387
61494
  const lowestAmount = selectableOptions.reduce((lowest, option) => {
@@ -61397,12 +61504,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
61397
61504
  selectableOptions,
61398
61505
  requiresSelection: selectableOptions.length > 1,
61399
61506
  selectedOption,
61507
+ slidingScale: null,
61508
+ selectedSlidingAmount: null,
61400
61509
  selectedPriceAmount: selectedOption?.priceAmount ?? null,
61401
61510
  selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
61402
61511
  hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
61403
61512
  hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
61404
61513
  };
61405
61514
  }
61515
+ case "sliding_scale": {
61516
+ const minAmount = course.pricing.slidingMinAmount ?? null;
61517
+ const maxAmount = course.pricing.slidingMaxAmount ?? null;
61518
+ if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
61519
+ return {
61520
+ currency,
61521
+ display: { kind: "unavailable", currency },
61522
+ selectableOptions: [],
61523
+ requiresSelection: true,
61524
+ selectedOption: null,
61525
+ slidingScale: null,
61526
+ selectedSlidingAmount: null,
61527
+ selectedPriceAmount: null,
61528
+ selectedRequiresPayment: false,
61529
+ hasPaidSelection: false,
61530
+ hasFreeSelection: false
61531
+ };
61532
+ }
61533
+ const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
61534
+ return {
61535
+ currency,
61536
+ display: { kind: "range", minAmount, maxAmount, currency },
61537
+ selectableOptions: [],
61538
+ requiresSelection: normalizedSelectedAmount === null,
61539
+ selectedOption: null,
61540
+ slidingScale: {
61541
+ minAmount,
61542
+ maxAmount,
61543
+ suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
61544
+ },
61545
+ selectedSlidingAmount: normalizedSelectedAmount,
61546
+ selectedPriceAmount: normalizedSelectedAmount,
61547
+ selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
61548
+ hasPaidSelection: maxAmount > 0,
61549
+ hasFreeSelection: minAmount === 0
61550
+ };
61551
+ }
61406
61552
  }
61407
61553
  }
61408
61554
  function formatCoursePriceDisplay(display, locale) {
@@ -73711,6 +73857,7 @@ var BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
73711
73857
  "selectedDate",
73712
73858
  "selectedSlot",
73713
73859
  "discountCode",
73860
+ "selectedSlidingAmountInput",
73714
73861
  "selectedCollectionOptionKind",
73715
73862
  "selectedAppointmentPackageId"
73716
73863
  ];
@@ -73994,6 +74141,32 @@ function readOptionalString(value) {
73994
74141
  function readOptionalNumber(value) {
73995
74142
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
73996
74143
  }
74144
+ function getBookingServiceSlidingScale(service) {
74145
+ const pricing = service?.pricing;
74146
+ if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
74147
+ return null;
74148
+ }
74149
+ return {
74150
+ minAmount: pricing.slidingMinAmount,
74151
+ maxAmount: pricing.slidingMaxAmount,
74152
+ suggestedAmount: pricing.slidingSuggestedAmount ?? null,
74153
+ currency: pricing.currency
74154
+ };
74155
+ }
74156
+ function parseBookingCurrencyInputToCents(value) {
74157
+ const trimmed = value?.trim() ?? "";
74158
+ if (!trimmed) return null;
74159
+ if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
74160
+ const parsed = Number(trimmed);
74161
+ if (!Number.isFinite(parsed) || parsed < 0) return null;
74162
+ return Math.round(parsed * 100);
74163
+ }
74164
+ function formatBookingCentsAsCurrencyInput(amount) {
74165
+ return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
74166
+ }
74167
+ function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
74168
+ return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
74169
+ }
73997
74170
  function readStringArray(value) {
73998
74171
  if (!Array.isArray(value)) return void 0;
73999
74172
  const strings = value.filter((item) => typeof item === "string");
@@ -74182,6 +74355,20 @@ function prepareBookingSubmission(input) {
74182
74355
  };
74183
74356
  }
74184
74357
  const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
74358
+ const slidingScale = getBookingServiceSlidingScale(selectedService);
74359
+ const selectedSlidingAmount = parseBookingCurrencyInputToCents(
74360
+ input.data.selectedSlidingAmountInput
74361
+ );
74362
+ if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
74363
+ return {
74364
+ ok: false,
74365
+ error: {
74366
+ tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
74367
+ serviceId,
74368
+ serviceTitle: selectedService.title || serviceId
74369
+ }
74370
+ };
74371
+ }
74185
74372
  if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
74186
74373
  return {
74187
74374
  ok: false,
@@ -74209,6 +74396,7 @@ function prepareBookingSubmission(input) {
74209
74396
  ...common,
74210
74397
  kind: "standard",
74211
74398
  ...discountCode ? { discountCode } : {},
74399
+ ...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
74212
74400
  ...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
74213
74401
  altchaSolution: input.altchaSolution ?? null
74214
74402
  }
@@ -74222,6 +74410,10 @@ function formatBookingSubmissionPreparationError(error) {
74222
74410
  return `Service not found: ${error.serviceId}`;
74223
74411
  case "payment-option-required":
74224
74412
  return `Please choose how you want to pay for "${error.serviceTitle}".`;
74413
+ case "sliding-amount-required":
74414
+ return `Please choose an amount for "${error.serviceTitle}".`;
74415
+ case "sliding-amount-out-of-range":
74416
+ return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
74225
74417
  case "payment-option-unsupported":
74226
74418
  return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
74227
74419
  case "service-missing-duration":
@@ -74318,6 +74510,7 @@ var bookingServiceSchema = z.object({
74318
74510
  title: z.string(),
74319
74511
  description: z.string().nullable().optional().transform((value) => value ?? void 0),
74320
74512
  durationMinutes: z.number().optional(),
74513
+ pricing: z.custom().optional(),
74321
74514
  priceAmount: z.number().nullable().optional(),
74322
74515
  priceCurrency: z.string().nullable().optional(),
74323
74516
  paymentTerms: blockBookingPaymentTermsSchema.optional(),
@@ -95758,6 +95951,40 @@ function isUnknownArray3(value) {
95758
95951
  }
95759
95952
 
95760
95953
  // ../content-editor/src/ui/editorSnapshot.ts
95954
+ function deriveEditorValuePublicationState(snapshot) {
95955
+ const current = snapshot.current ?? snapshot.baseline;
95956
+ const published = snapshot.publishedBaseline;
95957
+ if (!current && !published) {
95958
+ return { kind: "empty", hasUnpublishedChanges: false };
95959
+ }
95960
+ if (current && !published) {
95961
+ return {
95962
+ kind: "unpublished-draft",
95963
+ current,
95964
+ hasUnpublishedChanges: true
95965
+ };
95966
+ }
95967
+ if (!current && published) {
95968
+ return {
95969
+ kind: "published-missing-current",
95970
+ published,
95971
+ hasUnpublishedChanges: true
95972
+ };
95973
+ }
95974
+ if (!recordsEqual(current, published)) {
95975
+ return {
95976
+ kind: "published-with-unpublished-changes",
95977
+ current,
95978
+ published,
95979
+ hasUnpublishedChanges: true
95980
+ };
95981
+ }
95982
+ return {
95983
+ kind: "published-clean",
95984
+ published,
95985
+ hasUnpublishedChanges: false
95986
+ };
95987
+ }
95761
95988
  var BASELINE_SYNC_STATE = { kind: "baseline" };
95762
95989
  var PENDING_SYNC_STATE = { kind: "pending" };
95763
95990
  var blockDefaultsByKind = /* @__PURE__ */ new Map();
@@ -95798,7 +96025,9 @@ function linkedEntryMetaEqual(left, right) {
95798
96025
  }
95799
96026
  function editorValueRecordArraysEqual(left, right) {
95800
96027
  if (left.length !== right.length) return false;
95801
- return left.every((leftValue, index2) => recordsEqual(leftValue, right[index2] ?? null));
96028
+ return left.every(
96029
+ (leftValue, index2) => recordsEqual(leftValue, right[index2] ?? null)
96030
+ );
95802
96031
  }
95803
96032
  function linkedEntrySnapshotValuesEqual(left, right) {
95804
96033
  return snapshotValuesEqual(left, right) && linkedEntryMetaEqual(left.meta, right.meta);
@@ -95998,8 +96227,10 @@ function normalizedBlocksEqual(left, right) {
95998
96227
  if (leftBlock.orderIndex !== rightBlock.orderIndex) return false;
95999
96228
  if (leftBlock.purpose !== rightBlock.purpose) return false;
96000
96229
  if (!recordsEqual(leftBlock.content, rightBlock.content)) return false;
96001
- if (!recordsEqual(leftBlock.draftContent, rightBlock.draftContent)) return false;
96002
- if (!recordsEqual(leftBlock.publishedContent, rightBlock.publishedContent)) return false;
96230
+ if (!recordsEqual(leftBlock.draftContent, rightBlock.draftContent))
96231
+ return false;
96232
+ if (!recordsEqual(leftBlock.publishedContent, rightBlock.publishedContent))
96233
+ return false;
96003
96234
  if (!recordsEqual(leftBlock.bindings, rightBlock.bindings)) return false;
96004
96235
  }
96005
96236
  return true;
@@ -96072,14 +96303,16 @@ function draftsRecordEqualIgnoringOrder(left, right) {
96072
96303
  const leftDraft = left[draftId];
96073
96304
  const rightDraft = right[draftId];
96074
96305
  if (!leftDraft || !rightDraft) return false;
96075
- if (!draftSnapshotContentEqualIgnoringOrder(leftDraft, rightDraft)) return false;
96306
+ if (!draftSnapshotContentEqualIgnoringOrder(leftDraft, rightDraft))
96307
+ return false;
96076
96308
  }
96077
96309
  return true;
96078
96310
  }
96079
96311
  function diffToReorderOnly(previous, next) {
96080
96312
  if (!snapshotValuesEqual(previous.metadata, next.metadata)) return null;
96081
96313
  if (!snapshotValuesEqual(previous.content, next.content)) return null;
96082
- if (!linkedEntriesRecordEqual(previous.linkedEntries, next.linkedEntries)) return null;
96314
+ if (!linkedEntriesRecordEqual(previous.linkedEntries, next.linkedEntries))
96315
+ return null;
96083
96316
  if (previous.blockList.length !== next.blockList.length) return null;
96084
96317
  const previousIds = previous.blockList.map((block) => block.id);
96085
96318
  const nextIds = next.blockList.map((block) => block.id);
@@ -96096,8 +96329,12 @@ function structuralContextMatches(previous, next) {
96096
96329
  return snapshotValueContentEqual(previous.metadata, next.metadata) && snapshotValueContentEqual(previous.content, next.content) && linkedEntriesRecordEqual(previous.linkedEntries, next.linkedEntries);
96097
96330
  }
96098
96331
  function commonDraftsEqualIgnoringOrderAndVersion(previous, next, excludedDraftId) {
96099
- const previousDrafts = { ...previous.drafts };
96100
- const nextDrafts = { ...next.drafts };
96332
+ const previousDrafts = {
96333
+ ...previous.drafts
96334
+ };
96335
+ const nextDrafts = {
96336
+ ...next.drafts
96337
+ };
96101
96338
  delete previousDrafts[excludedDraftId];
96102
96339
  delete nextDrafts[excludedDraftId];
96103
96340
  return draftsRecordEqualIgnoringOrder(previousDrafts, nextDrafts);
@@ -96132,7 +96369,8 @@ function findInsertedBlock(previous, next) {
96132
96369
  const previousAfter = previous.slice(insertionIndex);
96133
96370
  const nextAfter = next.slice(insertionIndex + 1);
96134
96371
  if (!normalizedBlocksEqual(nextBefore, previousBefore)) return null;
96135
- if (!normalizedBlocksEqual(reindexNormalizedBlocks(nextAfter), previousAfter)) return null;
96372
+ if (!normalizedBlocksEqual(reindexNormalizedBlocks(nextAfter), previousAfter))
96373
+ return null;
96136
96374
  return { block: candidate, index: insertionIndex };
96137
96375
  }
96138
96376
  function findRemovedBlock(previous, next) {
@@ -96148,7 +96386,8 @@ function findRemovedBlock(previous, next) {
96148
96386
  const previousAfter = previous.slice(removalIndex + 1);
96149
96387
  const nextAfter = next.slice(removalIndex);
96150
96388
  if (!normalizedBlocksEqual(previousBefore, nextBefore)) return null;
96151
- if (!normalizedBlocksEqual(reindexNormalizedBlocks(previousAfter), nextAfter)) return null;
96389
+ if (!normalizedBlocksEqual(reindexNormalizedBlocks(previousAfter), nextAfter))
96390
+ return null;
96152
96391
  return candidate;
96153
96392
  }
96154
96393
  function deriveInsertEffect(previous, next) {
@@ -96196,12 +96435,10 @@ function reorderNormalizedBlocks(blocks, blockIds) {
96196
96435
  if (reordered.some((block) => block === null)) {
96197
96436
  return blocks;
96198
96437
  }
96199
- return reordered.map(
96200
- (block, index2) => ({
96201
- ...block,
96202
- orderIndex: index2
96203
- })
96204
- );
96438
+ return reordered.map((block, index2) => ({
96439
+ ...block,
96440
+ orderIndex: index2
96441
+ }));
96205
96442
  }
96206
96443
  function reindexNormalizedBlocks(blocks) {
96207
96444
  return blocks.map(
@@ -96229,7 +96466,9 @@ function insertNormalizedBlock(blockList, block, index2) {
96229
96466
  return reindexNormalizedBlocks(next);
96230
96467
  }
96231
96468
  function removeNormalizedBlock(blockList, blockId) {
96232
- return reindexNormalizedBlocks(blockList.filter((block) => block.id !== blockId));
96469
+ return reindexNormalizedBlocks(
96470
+ blockList.filter((block) => block.id !== blockId)
96471
+ );
96233
96472
  }
96234
96473
  function getPersistedBlockList(blocks) {
96235
96474
  return blocks.every(isPersistedBlock) ? blocks : null;
@@ -96308,10 +96547,14 @@ function applyEditorCommand(snapshot, command2) {
96308
96547
  const next = cloneRecord(source) ?? {};
96309
96548
  setAtPath(next, command2.path, command2.value);
96310
96549
  const nextCurrent = unsafeAsEditorMetadataValues(next);
96311
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96312
- current: nextCurrent,
96313
- syncState: createSyncState(snapshot.metadata.baseline, nextCurrent)
96314
- });
96550
+ const nextMetadata = updateValueSnapshot(
96551
+ snapshot.metadata,
96552
+ cloneMetadataValues,
96553
+ {
96554
+ current: nextCurrent,
96555
+ syncState: createSyncState(snapshot.metadata.baseline, nextCurrent)
96556
+ }
96557
+ );
96315
96558
  if (nextMetadata === snapshot.metadata) return snapshot;
96316
96559
  return {
96317
96560
  ...snapshot,
@@ -96320,10 +96563,14 @@ function applyEditorCommand(snapshot, command2) {
96320
96563
  }
96321
96564
  case "replace-metadata": {
96322
96565
  const nextCurrent = cloneMetadataValues(command2.value);
96323
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96324
- current: nextCurrent,
96325
- syncState: createSyncState(snapshot.metadata.baseline, nextCurrent)
96326
- });
96566
+ const nextMetadata = updateValueSnapshot(
96567
+ snapshot.metadata,
96568
+ cloneMetadataValues,
96569
+ {
96570
+ current: nextCurrent,
96571
+ syncState: createSyncState(snapshot.metadata.baseline, nextCurrent)
96572
+ }
96573
+ );
96327
96574
  if (nextMetadata === snapshot.metadata) return snapshot;
96328
96575
  return {
96329
96576
  ...snapshot,
@@ -96335,10 +96582,14 @@ function applyEditorCommand(snapshot, command2) {
96335
96582
  const next = cloneRecord(source) ?? {};
96336
96583
  setAtPath(next, command2.path, command2.value);
96337
96584
  const nextCurrent = unsafeAsEditorContentValues(next);
96338
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96339
- current: nextCurrent,
96340
- syncState: createSyncState(snapshot.content.baseline, nextCurrent)
96341
- });
96585
+ const nextContent = updateValueSnapshot(
96586
+ snapshot.content,
96587
+ cloneContentValues,
96588
+ {
96589
+ current: nextCurrent,
96590
+ syncState: createSyncState(snapshot.content.baseline, nextCurrent)
96591
+ }
96592
+ );
96342
96593
  if (nextContent === snapshot.content) return snapshot;
96343
96594
  return {
96344
96595
  ...snapshot,
@@ -96347,10 +96598,14 @@ function applyEditorCommand(snapshot, command2) {
96347
96598
  }
96348
96599
  case "replace-content": {
96349
96600
  const nextCurrent = cloneContentValues(command2.value);
96350
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96351
- current: nextCurrent,
96352
- syncState: createSyncState(snapshot.content.baseline, nextCurrent)
96353
- });
96601
+ const nextContent = updateValueSnapshot(
96602
+ snapshot.content,
96603
+ cloneContentValues,
96604
+ {
96605
+ current: nextCurrent,
96606
+ syncState: createSyncState(snapshot.content.baseline, nextCurrent)
96607
+ }
96608
+ );
96354
96609
  if (nextContent === snapshot.content) return snapshot;
96355
96610
  return {
96356
96611
  ...snapshot,
@@ -96374,7 +96629,10 @@ function applyEditorCommand(snapshot, command2) {
96374
96629
  command2.blockId,
96375
96630
  (draft) => updateDraftSnapshot(draft, {
96376
96631
  current: cloneBlockValues(command2.value),
96377
- syncState: createSyncState(draft.baseline, cloneBlockValues(command2.value))
96632
+ syncState: createSyncState(
96633
+ draft.baseline,
96634
+ cloneBlockValues(command2.value)
96635
+ )
96378
96636
  })
96379
96637
  );
96380
96638
  case "set-linked-entry-value":
@@ -96394,11 +96652,18 @@ function applyEditorCommand(snapshot, command2) {
96394
96652
  command2.entryId,
96395
96653
  (entry) => updateLinkedEntrySnapshot(entry, {
96396
96654
  current: cloneContentValues(command2.value),
96397
- syncState: createSyncState(entry.baseline, cloneContentValues(command2.value))
96655
+ syncState: createSyncState(
96656
+ entry.baseline,
96657
+ cloneContentValues(command2.value)
96658
+ )
96398
96659
  })
96399
96660
  );
96400
96661
  case "insert-block": {
96401
- const nextBlockList = insertNormalizedBlock(snapshot.blockList, command2.block, command2.index);
96662
+ const nextBlockList = insertNormalizedBlock(
96663
+ snapshot.blockList,
96664
+ command2.block,
96665
+ command2.index
96666
+ );
96402
96667
  const insertedDraft = updateDraftSnapshot(command2.draft, {
96403
96668
  meta: { orderIndex: command2.index }
96404
96669
  });
@@ -96406,7 +96671,10 @@ function applyEditorCommand(snapshot, command2) {
96406
96671
  ...snapshot.drafts,
96407
96672
  [command2.block.id]: insertedDraft
96408
96673
  };
96409
- const nextDrafts = syncDraftOrderWithBlocks(nextDraftsWithInsert, nextBlockList);
96674
+ const nextDrafts = syncDraftOrderWithBlocks(
96675
+ nextDraftsWithInsert,
96676
+ nextBlockList
96677
+ );
96410
96678
  if (normalizedBlocksEqual(nextBlockList, snapshot.blockList) && draftsRecordEqual(nextDrafts, snapshot.drafts)) {
96411
96679
  return snapshot;
96412
96680
  }
@@ -96417,11 +96685,19 @@ function applyEditorCommand(snapshot, command2) {
96417
96685
  };
96418
96686
  }
96419
96687
  case "remove-block": {
96420
- const currentBlock = snapshot.blockList.find((block) => block.id === command2.blockId);
96688
+ const currentBlock = snapshot.blockList.find(
96689
+ (block) => block.id === command2.blockId
96690
+ );
96421
96691
  if (!currentBlock) return snapshot;
96422
- const nextBlockList = removeNormalizedBlock(snapshot.blockList, command2.blockId);
96692
+ const nextBlockList = removeNormalizedBlock(
96693
+ snapshot.blockList,
96694
+ command2.blockId
96695
+ );
96423
96696
  const { [command2.blockId]: _removedDraft, ...remainingDrafts } = snapshot.drafts;
96424
- const nextDrafts = syncDraftOrderWithBlocks(remainingDrafts, nextBlockList);
96697
+ const nextDrafts = syncDraftOrderWithBlocks(
96698
+ remainingDrafts,
96699
+ nextBlockList
96700
+ );
96425
96701
  if (normalizedBlocksEqual(nextBlockList, snapshot.blockList) && draftsRecordEqual(nextDrafts, snapshot.drafts)) {
96426
96702
  return snapshot;
96427
96703
  }
@@ -96434,9 +96710,14 @@ function applyEditorCommand(snapshot, command2) {
96434
96710
  case "reorder-blocks": {
96435
96711
  const persistedBlocks = getPersistedBlockList(snapshot.blockList);
96436
96712
  if (!persistedBlocks) {
96437
- throw new Error("reorder-blocks requires every block in the structure list to be persisted");
96713
+ throw new Error(
96714
+ "reorder-blocks requires every block in the structure list to be persisted"
96715
+ );
96438
96716
  }
96439
- const nextBlocks = reorderNormalizedBlocks(persistedBlocks, command2.blockIds);
96717
+ const nextBlocks = reorderNormalizedBlocks(
96718
+ persistedBlocks,
96719
+ command2.blockIds
96720
+ );
96440
96721
  const nextDrafts = syncDraftOrderWithBlocks(snapshot.drafts, nextBlocks);
96441
96722
  if (normalizedBlocksEqual(nextBlocks, snapshot.blockList) && draftsRecordEqual(nextDrafts, snapshot.drafts)) {
96442
96723
  return snapshot;
@@ -96481,6 +96762,8 @@ function applySystemOperation(snapshot, operation) {
96481
96762
  return setMetadataPublishedBaseline(snapshot, operation.published);
96482
96763
  case "set-content-published-baseline":
96483
96764
  return setContentPublishedBaseline(snapshot, operation.published);
96765
+ case "apply-publish-success":
96766
+ return applyPublishSuccessTransition(snapshot, operation.transition);
96484
96767
  case "autosave-metadata-succeeded":
96485
96768
  return autosaveMetadataSucceeded(
96486
96769
  snapshot,
@@ -96502,9 +96785,19 @@ function applySystemOperation(snapshot, operation) {
96502
96785
  case "clear-content-error":
96503
96786
  return clearContentError(snapshot);
96504
96787
  case "init-new-draft-block":
96505
- return initNewDraftBlock(snapshot, operation.blockId, operation.baseline, operation.meta);
96788
+ return initNewDraftBlock(
96789
+ snapshot,
96790
+ operation.blockId,
96791
+ operation.baseline,
96792
+ operation.meta
96793
+ );
96506
96794
  case "update-draft-block-baseline":
96507
- return updateDraftBlockBaseline(snapshot, operation.blockId, operation.baseline, operation.meta);
96795
+ return updateDraftBlockBaseline(
96796
+ snapshot,
96797
+ operation.blockId,
96798
+ operation.baseline,
96799
+ operation.meta
96800
+ );
96508
96801
  case "remove-draft-block":
96509
96802
  return removeDraftBlock(snapshot, operation.blockId);
96510
96803
  case "set-draft-published-baselines":
@@ -96537,7 +96830,11 @@ function applySystemOperation(snapshot, operation) {
96537
96830
  operation.optimisticHash
96538
96831
  );
96539
96832
  case "save-linked-entry-failed":
96540
- return saveLinkedEntryFailed(snapshot, operation.entryId, operation.message);
96833
+ return saveLinkedEntryFailed(
96834
+ snapshot,
96835
+ operation.entryId,
96836
+ operation.message
96837
+ );
96541
96838
  case "clear-linked-entry-error":
96542
96839
  return clearLinkedEntryError(snapshot, operation.entryId);
96543
96840
  case "replace-block-list":
@@ -96550,12 +96847,16 @@ function hydrateMetadataSnapshot(snapshot, baseline, current, published) {
96550
96847
  const nextBaseline = cloneMetadataValues(baseline);
96551
96848
  const nextCurrent = cloneMetadataValues(current ?? baseline ?? null);
96552
96849
  const nextPublished = published !== void 0 ? cloneMetadataValues(published) : snapshot.metadata.publishedBaseline;
96553
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96554
- baseline: nextBaseline,
96555
- current: nextCurrent,
96556
- publishedBaseline: nextPublished,
96557
- syncState: createSyncState(nextBaseline, nextCurrent)
96558
- });
96850
+ const nextMetadata = updateValueSnapshot(
96851
+ snapshot.metadata,
96852
+ cloneMetadataValues,
96853
+ {
96854
+ baseline: nextBaseline,
96855
+ current: nextCurrent,
96856
+ publishedBaseline: nextPublished,
96857
+ syncState: createSyncState(nextBaseline, nextCurrent)
96858
+ }
96859
+ );
96559
96860
  if (nextMetadata === snapshot.metadata) return snapshot;
96560
96861
  return {
96561
96862
  ...snapshot,
@@ -96566,12 +96867,16 @@ function hydrateContentSnapshot(snapshot, baseline, current, published) {
96566
96867
  const nextBaseline = cloneContentValues(baseline);
96567
96868
  const nextCurrent = cloneContentValues(current ?? baseline ?? null);
96568
96869
  const nextPublished = published !== void 0 ? cloneContentValues(published) : snapshot.content.publishedBaseline;
96569
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96570
- baseline: nextBaseline,
96571
- current: nextCurrent,
96572
- publishedBaseline: nextPublished,
96573
- syncState: createSyncState(nextBaseline, nextCurrent)
96574
- });
96870
+ const nextContent = updateValueSnapshot(
96871
+ snapshot.content,
96872
+ cloneContentValues,
96873
+ {
96874
+ baseline: nextBaseline,
96875
+ current: nextCurrent,
96876
+ publishedBaseline: nextPublished,
96877
+ syncState: createSyncState(nextBaseline, nextCurrent)
96878
+ }
96879
+ );
96575
96880
  if (nextContent === snapshot.content) return snapshot;
96576
96881
  return {
96577
96882
  ...snapshot,
@@ -96579,9 +96884,13 @@ function hydrateContentSnapshot(snapshot, baseline, current, published) {
96579
96884
  };
96580
96885
  }
96581
96886
  function setMetadataPublishedBaseline(snapshot, published) {
96582
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96583
- publishedBaseline: cloneMetadataValues(published)
96584
- });
96887
+ const nextMetadata = updateValueSnapshot(
96888
+ snapshot.metadata,
96889
+ cloneMetadataValues,
96890
+ {
96891
+ publishedBaseline: cloneMetadataValues(published)
96892
+ }
96893
+ );
96585
96894
  if (nextMetadata === snapshot.metadata) return snapshot;
96586
96895
  return {
96587
96896
  ...snapshot,
@@ -96589,24 +96898,53 @@ function setMetadataPublishedBaseline(snapshot, published) {
96589
96898
  };
96590
96899
  }
96591
96900
  function setContentPublishedBaseline(snapshot, published) {
96592
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96593
- publishedBaseline: cloneContentValues(published)
96594
- });
96901
+ const nextContent = updateValueSnapshot(
96902
+ snapshot.content,
96903
+ cloneContentValues,
96904
+ {
96905
+ publishedBaseline: cloneContentValues(published)
96906
+ }
96907
+ );
96595
96908
  if (nextContent === snapshot.content) return snapshot;
96596
96909
  return {
96597
96910
  ...snapshot,
96598
96911
  content: nextContent
96599
96912
  };
96600
96913
  }
96914
+ function applyPublishSuccessTransition(snapshot, transition) {
96915
+ const nextMetadataSnapshot = hydrateMetadataSnapshot(
96916
+ snapshot,
96917
+ transition.metadata.baseline,
96918
+ transition.metadata.current,
96919
+ transition.metadata.published
96920
+ );
96921
+ const nextContentSnapshot = nextMetadataSnapshot.content.version === transition.content.versionAtPublishStart && transition.content.published !== null ? hydrateContentSnapshot(
96922
+ nextMetadataSnapshot,
96923
+ transition.content.published,
96924
+ transition.content.published,
96925
+ transition.content.published
96926
+ ) : setContentPublishedBaseline(
96927
+ nextMetadataSnapshot,
96928
+ transition.content.published
96929
+ );
96930
+ return transition.blockPublishedBaselines ? setDraftPublishedBaselines(
96931
+ nextContentSnapshot,
96932
+ transition.blockPublishedBaselines
96933
+ ) : nextContentSnapshot;
96934
+ }
96601
96935
  function autosaveMetadataSucceeded(snapshot, savedValues, acknowledgedVersion) {
96602
96936
  const currentMetadata = snapshot.metadata;
96603
96937
  const savedBaseline = cloneMetadataValues(savedValues);
96604
96938
  const hasNewerEdits = currentMetadata.version > acknowledgedVersion;
96605
- const nextMetadata = updateValueSnapshot(currentMetadata, cloneMetadataValues, {
96606
- baseline: savedBaseline,
96607
- current: hasNewerEdits ? currentMetadata.current : savedBaseline,
96608
- syncState: hasNewerEdits ? createSyncState(savedBaseline, currentMetadata.current) : BASELINE_SYNC_STATE
96609
- });
96939
+ const nextMetadata = updateValueSnapshot(
96940
+ currentMetadata,
96941
+ cloneMetadataValues,
96942
+ {
96943
+ baseline: savedBaseline,
96944
+ current: hasNewerEdits ? currentMetadata.current : savedBaseline,
96945
+ syncState: hasNewerEdits ? createSyncState(savedBaseline, currentMetadata.current) : BASELINE_SYNC_STATE
96946
+ }
96947
+ );
96610
96948
  if (nextMetadata === currentMetadata) return snapshot;
96611
96949
  return {
96612
96950
  ...snapshot,
@@ -96629,9 +96967,13 @@ function autosaveContentSucceeded(snapshot, savedValues, acknowledgedVersion) {
96629
96967
  };
96630
96968
  }
96631
96969
  function autosaveMetadataFailed(snapshot, message2) {
96632
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96633
- syncState: { kind: "failed", error: message2 ?? "Save failed" }
96634
- });
96970
+ const nextMetadata = updateValueSnapshot(
96971
+ snapshot.metadata,
96972
+ cloneMetadataValues,
96973
+ {
96974
+ syncState: { kind: "failed", error: message2 ?? "Save failed" }
96975
+ }
96976
+ );
96635
96977
  if (nextMetadata === snapshot.metadata) return snapshot;
96636
96978
  return {
96637
96979
  ...snapshot,
@@ -96639,9 +96981,13 @@ function autosaveMetadataFailed(snapshot, message2) {
96639
96981
  };
96640
96982
  }
96641
96983
  function autosaveContentFailed(snapshot, message2) {
96642
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96643
- syncState: { kind: "failed", error: message2 ?? "Save failed" }
96644
- });
96984
+ const nextContent = updateValueSnapshot(
96985
+ snapshot.content,
96986
+ cloneContentValues,
96987
+ {
96988
+ syncState: { kind: "failed", error: message2 ?? "Save failed" }
96989
+ }
96990
+ );
96645
96991
  if (nextContent === snapshot.content) return snapshot;
96646
96992
  return {
96647
96993
  ...snapshot,
@@ -96649,9 +96995,16 @@ function autosaveContentFailed(snapshot, message2) {
96649
96995
  };
96650
96996
  }
96651
96997
  function clearMetadataError(snapshot) {
96652
- const nextMetadata = updateValueSnapshot(snapshot.metadata, cloneMetadataValues, {
96653
- syncState: createSyncState(snapshot.metadata.baseline, snapshot.metadata.current)
96654
- });
96998
+ const nextMetadata = updateValueSnapshot(
96999
+ snapshot.metadata,
97000
+ cloneMetadataValues,
97001
+ {
97002
+ syncState: createSyncState(
97003
+ snapshot.metadata.baseline,
97004
+ snapshot.metadata.current
97005
+ )
97006
+ }
97007
+ );
96655
97008
  if (nextMetadata === snapshot.metadata) return snapshot;
96656
97009
  return {
96657
97010
  ...snapshot,
@@ -96659,9 +97012,16 @@ function clearMetadataError(snapshot) {
96659
97012
  };
96660
97013
  }
96661
97014
  function clearContentError(snapshot) {
96662
- const nextContent = updateValueSnapshot(snapshot.content, cloneContentValues, {
96663
- syncState: createSyncState(snapshot.content.baseline, snapshot.content.current)
96664
- });
97015
+ const nextContent = updateValueSnapshot(
97016
+ snapshot.content,
97017
+ cloneContentValues,
97018
+ {
97019
+ syncState: createSyncState(
97020
+ snapshot.content.baseline,
97021
+ snapshot.content.current
97022
+ )
97023
+ }
97024
+ );
96665
97025
  if (nextContent === snapshot.content) return snapshot;
96666
97026
  return {
96667
97027
  ...snapshot,
@@ -96675,8 +97035,14 @@ function getSnapshotStatus(syncState) {
96675
97035
  return syncState.kind;
96676
97036
  }
96677
97037
  function buildDraftSnapshotFromBaseline(blockId, baseline, meta, existing) {
96678
- const normalizedBaseline = applyBlockDefaults(extractBlockData(baseline), meta.kind);
96679
- const normalizedPublished = applyBlockDefaults(extractBlockData(meta.publishedContent), meta.kind);
97038
+ const normalizedBaseline = applyBlockDefaults(
97039
+ extractBlockData(baseline),
97040
+ meta.kind
97041
+ );
97042
+ const normalizedPublished = applyBlockDefaults(
97043
+ extractBlockData(meta.publishedContent),
97044
+ meta.kind
97045
+ );
96680
97046
  const nextBaseline = cloneBlockValues(normalizedBaseline);
96681
97047
  const existingSyncState = existing?.syncState.kind;
96682
97048
  const shouldPreserveCurrent = existingSyncState === "pending" || existingSyncState === "failed";
@@ -96698,7 +97064,12 @@ function buildDraftSnapshotFromBaseline(blockId, baseline, meta, existing) {
96698
97064
  }
96699
97065
  function initNewDraftBlock(snapshot, blockId, baseline, meta) {
96700
97066
  const existing = snapshot.drafts[blockId];
96701
- const nextDraft = buildDraftSnapshotFromBaseline(blockId, baseline, meta, existing);
97067
+ const nextDraft = buildDraftSnapshotFromBaseline(
97068
+ blockId,
97069
+ baseline,
97070
+ meta,
97071
+ existing
97072
+ );
96702
97073
  if (existing && draftValuesEqual(existing, nextDraft)) {
96703
97074
  return snapshot;
96704
97075
  }
@@ -96713,26 +97084,37 @@ function initNewDraftBlock(snapshot, blockId, baseline, meta) {
96713
97084
  function updateDraftBlockBaseline(snapshot, blockId, baseline, meta) {
96714
97085
  const existing = snapshot.drafts[blockId];
96715
97086
  if (!existing) {
96716
- throw new Error(`update-draft-block-baseline requires an existing draft for ${blockId}`);
96717
- }
96718
- const nextDraft = buildDraftSnapshotFromBaseline(blockId, baseline, {
96719
- kind: meta?.kind ?? existing.meta.kind,
96720
- purpose: meta?.purpose !== void 0 ? meta.purpose : existing.meta.purpose,
96721
- orderIndex: meta?.orderIndex !== void 0 ? meta.orderIndex : existing.meta.orderIndex,
96722
- publishedContent: meta?.publishedContent !== void 0 ? meta.publishedContent : existing.meta.publishedContent
96723
- }, existing);
97087
+ throw new Error(
97088
+ `update-draft-block-baseline requires an existing draft for ${blockId}`
97089
+ );
97090
+ }
97091
+ const nextDraft = buildDraftSnapshotFromBaseline(
97092
+ blockId,
97093
+ baseline,
97094
+ {
97095
+ kind: meta?.kind ?? existing.meta.kind,
97096
+ purpose: meta?.purpose !== void 0 ? meta.purpose : existing.meta.purpose,
97097
+ orderIndex: meta?.orderIndex !== void 0 ? meta.orderIndex : existing.meta.orderIndex,
97098
+ publishedContent: meta?.publishedContent !== void 0 ? meta.publishedContent : existing.meta.publishedContent
97099
+ },
97100
+ existing
97101
+ );
96724
97102
  if (draftValuesEqual(existing, nextDraft)) {
96725
97103
  return snapshot;
96726
97104
  }
96727
- const nextBlockList = updatePersistedBlockInList(snapshot.blockList, blockId, (block) => ({
96728
- ...block,
96729
- kind: nextDraft.meta.kind,
96730
- orderIndex: nextDraft.meta.orderIndex,
96731
- purpose: nextDraft.meta.purpose,
96732
- content: nextDraft.baseline,
96733
- draftContent: nextDraft.current ?? nextDraft.baseline,
96734
- publishedContent: nextDraft.meta.publishedContent
96735
- }));
97105
+ const nextBlockList = updatePersistedBlockInList(
97106
+ snapshot.blockList,
97107
+ blockId,
97108
+ (block) => ({
97109
+ ...block,
97110
+ kind: nextDraft.meta.kind,
97111
+ orderIndex: nextDraft.meta.orderIndex,
97112
+ purpose: nextDraft.meta.purpose,
97113
+ content: nextDraft.baseline,
97114
+ draftContent: nextDraft.current ?? nextDraft.baseline,
97115
+ publishedContent: nextDraft.meta.publishedContent
97116
+ })
97117
+ );
96736
97118
  return {
96737
97119
  ...snapshot,
96738
97120
  blockList: nextBlockList,
@@ -96752,14 +97134,19 @@ function removeDraftBlock(snapshot, blockId) {
96752
97134
  };
96753
97135
  }
96754
97136
  function setDraftPublishedBaselines(snapshot, blocks) {
96755
- let nextDrafts = { ...snapshot.drafts };
97137
+ let nextDrafts = {
97138
+ ...snapshot.drafts
97139
+ };
96756
97140
  let nextBlockList = snapshot.blockList;
96757
97141
  let changed = false;
96758
97142
  for (const block of blocks) {
96759
97143
  const draft = nextDrafts[block.id];
96760
97144
  if (!draft) continue;
96761
97145
  const kindForDefaults = block.kind ?? draft.meta.kind;
96762
- const normalizedPublished = applyBlockDefaults(extractBlockData(block.publishedContent), kindForDefaults);
97146
+ const normalizedPublished = applyBlockDefaults(
97147
+ extractBlockData(block.publishedContent),
97148
+ kindForDefaults
97149
+ );
96763
97150
  const nextDraft = updateDraftSnapshot(draft, {
96764
97151
  meta: {
96765
97152
  publishedContent: cloneBlockValues(normalizedPublished ?? null)
@@ -96767,11 +97154,15 @@ function setDraftPublishedBaselines(snapshot, blocks) {
96767
97154
  });
96768
97155
  if (nextDraft === draft) continue;
96769
97156
  nextDrafts[block.id] = nextDraft;
96770
- nextBlockList = updatePersistedBlockInList(nextBlockList, block.id, (currentBlock) => ({
96771
- ...currentBlock,
96772
- kind: kindForDefaults,
96773
- publishedContent: nextDraft.meta.publishedContent
96774
- }));
97157
+ nextBlockList = updatePersistedBlockInList(
97158
+ nextBlockList,
97159
+ block.id,
97160
+ (currentBlock) => ({
97161
+ ...currentBlock,
97162
+ kind: kindForDefaults,
97163
+ publishedContent: nextDraft.meta.publishedContent
97164
+ })
97165
+ );
96775
97166
  changed = true;
96776
97167
  }
96777
97168
  if (!changed) return snapshot;
@@ -96796,11 +97187,15 @@ function autosaveDraftSucceeded(snapshot, blockId, savedValues, acknowledgedVers
96796
97187
  if (nextDraft === draft) {
96797
97188
  return snapshot;
96798
97189
  }
96799
- const nextBlockList = updatePersistedBlockInList(snapshot.blockList, blockId, (block) => ({
96800
- ...block,
96801
- content: nextDraft.baseline,
96802
- draftContent: nextDraft.current ?? nextDraft.baseline
96803
- }));
97190
+ const nextBlockList = updatePersistedBlockInList(
97191
+ snapshot.blockList,
97192
+ blockId,
97193
+ (block) => ({
97194
+ ...block,
97195
+ content: nextDraft.baseline,
97196
+ draftContent: nextDraft.current ?? nextDraft.baseline
97197
+ })
97198
+ );
96804
97199
  return {
96805
97200
  ...snapshot,
96806
97201
  blockList: nextBlockList,
@@ -96955,15 +97350,54 @@ function inspectDrafts(snapshot) {
96955
97350
  function getLinkedEntrySnapshot(snapshot, entryId) {
96956
97351
  return snapshot.linkedEntries[entryId] ?? null;
96957
97352
  }
97353
+ function deriveDraftValuePublicationState(draft) {
97354
+ return deriveEditorValuePublicationState({
97355
+ version: draft.version,
97356
+ baseline: draft.baseline,
97357
+ current: draft.current,
97358
+ publishedBaseline: draft.meta.publishedContent,
97359
+ syncState: draft.syncState
97360
+ });
97361
+ }
97362
+ function getFirstUnpublishedDraftChange(snapshot) {
97363
+ for (const draft of inspectDrafts(snapshot)) {
97364
+ const publicationState = deriveDraftValuePublicationState(draft);
97365
+ switch (publicationState.kind) {
97366
+ case "empty":
97367
+ case "published-clean":
97368
+ continue;
97369
+ case "unpublished-draft":
97370
+ return {
97371
+ blockId: draft.id,
97372
+ kind: draft.meta.kind,
97373
+ reason: "missing_published",
97374
+ currentContent: publicationState.current,
97375
+ publishedContent: null
97376
+ };
97377
+ case "published-missing-current":
97378
+ return {
97379
+ blockId: draft.id,
97380
+ kind: draft.meta.kind,
97381
+ reason: "missing_current",
97382
+ currentContent: null,
97383
+ publishedContent: publicationState.published
97384
+ };
97385
+ case "published-with-unpublished-changes":
97386
+ return {
97387
+ blockId: draft.id,
97388
+ kind: draft.meta.kind,
97389
+ reason: "different",
97390
+ currentContent: publicationState.current,
97391
+ publishedContent: publicationState.published
97392
+ };
97393
+ default:
97394
+ return assertNever9(publicationState);
97395
+ }
97396
+ }
97397
+ return null;
97398
+ }
96958
97399
  function hasUnpublishedDraftChanges(snapshot) {
96959
- return inspectDrafts(snapshot).some((draft) => {
96960
- const currentContent = draft.current ?? draft.baseline;
96961
- const published = draft.meta.publishedContent;
96962
- if (!currentContent && !published) return false;
96963
- if (currentContent && !published) return true;
96964
- if (!currentContent && published) return true;
96965
- return !recordsEqual(currentContent, published);
96966
- });
97400
+ return getFirstUnpublishedDraftChange(snapshot) !== null;
96967
97401
  }
96968
97402
 
96969
97403
  // ../content-editor/src/ui/editorHistory.ts
@@ -97216,11 +97650,21 @@ function deriveBlockValidationSummary({
97216
97650
  // ../content-editor/src/ui/editorUiStore.ts
97217
97651
  var TEXT_COALESCE_IDLE_MS = 500;
97218
97652
  function hasUnpublishedChanges(snapshot) {
97219
- const currentContent = snapshot.current ?? snapshot.baseline;
97220
- const published = snapshot.publishedBaseline;
97221
- if (!currentContent && !published) return false;
97222
- if (currentContent && !published) return true;
97223
- return !recordsEqual(currentContent, published);
97653
+ return deriveEditorValuePublicationState(snapshot).hasUnpublishedChanges;
97654
+ }
97655
+ function toEditorPublishSuccessTransition(transition) {
97656
+ return {
97657
+ metadata: {
97658
+ baseline: transition.metadata.baseline ? unsafeAsEditorMetadataValues(transition.metadata.baseline) : null,
97659
+ current: transition.metadata.current ? unsafeAsEditorMetadataValues(transition.metadata.current) : null,
97660
+ published: transition.metadata.published ? unsafeAsEditorMetadataValues(transition.metadata.published) : null
97661
+ },
97662
+ content: {
97663
+ published: transition.content.published ? unsafeAsEditorContentValues(transition.content.published) : null,
97664
+ versionAtPublishStart: transition.content.versionAtPublishStart
97665
+ },
97666
+ blockPublishedBaselines: transition.blockPublishedBaselines
97667
+ };
97224
97668
  }
97225
97669
  function normalizeDraftBlockBaselineInput(value) {
97226
97670
  const extracted = extractBlockData(value);
@@ -97365,7 +97809,10 @@ function createEditorUiStore(options = {}) {
97365
97809
  triggerUpdate();
97366
97810
  return true;
97367
97811
  };
97368
- const applyUserEditorOperation = (operation) => commitUserSnapshot(operation.command, applyUserOperation(editorSnapshot, operation));
97812
+ const applyUserEditorOperation = (operation) => commitUserSnapshot(
97813
+ operation.command,
97814
+ applyUserOperation(editorSnapshot, operation)
97815
+ );
97369
97816
  const applySystemEditorOperation = (operation) => replacePresentSnapshot(applySystemOperation(editorSnapshot, operation));
97370
97817
  const replacePresentSnapshot = (nextSnapshot) => {
97371
97818
  if (editorHistorySnapshotsEqual(editorSnapshot, nextSnapshot)) {
@@ -97391,10 +97838,14 @@ function createEditorUiStore(options = {}) {
97391
97838
  }
97392
97839
  };
97393
97840
  const computeDraftSyncState = () => {
97394
- const metadataStatus = getSnapshotStatus(editorSnapshot.metadata.syncState);
97841
+ const metadataStatus = getSnapshotStatus(
97842
+ editorSnapshot.metadata.syncState
97843
+ );
97395
97844
  const contentStatus = getSnapshotStatus(editorSnapshot.content.syncState);
97396
- if (metadataStatus === "failed" || contentStatus === "failed") return "failed";
97397
- if (metadataStatus === "pending" || contentStatus === "pending") return "pending";
97845
+ if (metadataStatus === "failed" || contentStatus === "failed")
97846
+ return "failed";
97847
+ if (metadataStatus === "pending" || contentStatus === "pending")
97848
+ return "pending";
97398
97849
  for (const draft of inspectDrafts(editorSnapshot)) {
97399
97850
  const status = getSnapshotStatus(draft.syncState);
97400
97851
  if (status === "failed") return "failed";
@@ -97463,7 +97914,10 @@ function createEditorUiStore(options = {}) {
97463
97914
  });
97464
97915
  },
97465
97916
  autosaveFailed: (message2) => {
97466
- applySystemEditorOperation({ type: "autosave-metadata-failed", message: message2 });
97917
+ applySystemEditorOperation({
97918
+ type: "autosave-metadata-failed",
97919
+ message: message2
97920
+ });
97467
97921
  },
97468
97922
  clearError: () => {
97469
97923
  applySystemEditorOperation({ type: "clear-metadata-error" });
@@ -97667,7 +98121,9 @@ function createEditorUiStore(options = {}) {
97667
98121
  initNewBlock: (blockId, baseline, meta) => {
97668
98122
  const normalizedBaseline = normalizeDraftBlockBaselineInput(baseline);
97669
98123
  if (getDraftSnapshot(editorSnapshot, blockId)) {
97670
- throw new Error(`drafts.initNewBlock expected a missing draft (${blockId})`);
98124
+ throw new Error(
98125
+ `drafts.initNewBlock expected a missing draft (${blockId})`
98126
+ );
97671
98127
  }
97672
98128
  const changed = applySystemEditorOperation({
97673
98129
  type: "init-new-draft-block",
@@ -97687,7 +98143,9 @@ function createEditorUiStore(options = {}) {
97687
98143
  updateBlockBaseline: (blockId, baseline, meta) => {
97688
98144
  const normalizedBaseline = normalizeDraftBlockBaselineInput(baseline);
97689
98145
  if (!getDraftSnapshot(editorSnapshot, blockId)) {
97690
- throw new Error(`drafts.updateBlockBaseline expected an existing draft (${blockId})`);
98146
+ throw new Error(
98147
+ `drafts.updateBlockBaseline expected an existing draft (${blockId})`
98148
+ );
97691
98149
  }
97692
98150
  const changed = applySystemEditorOperation({
97693
98151
  type: "update-draft-block-baseline",
@@ -97703,7 +98161,10 @@ function createEditorUiStore(options = {}) {
97703
98161
  }
97704
98162
  },
97705
98163
  setBlockPublishedBaselinesFromBlocks: (blocks) => {
97706
- const changed = applySystemEditorOperation({ type: "set-draft-published-baselines", blocks });
98164
+ const changed = applySystemEditorOperation({
98165
+ type: "set-draft-published-baselines",
98166
+ blocks
98167
+ });
97707
98168
  if (changed) {
97708
98169
  notifyDraftChanges(blocks.map((block) => block.id));
97709
98170
  }
@@ -97824,44 +98285,7 @@ function createEditorUiStore(options = {}) {
97824
98285
  }
97825
98286
  },
97826
98287
  hasUnpublishedBlockChanges: () => hasUnpublishedDraftChanges(editorSnapshot),
97827
- getFirstUnpublishedBlockChange: () => {
97828
- for (const draft of inspectDrafts(editorSnapshot)) {
97829
- const currentContent = draft.current ?? draft.baseline;
97830
- const published = draft.meta.publishedContent;
97831
- if (!currentContent && !published) continue;
97832
- if (currentContent && !published) {
97833
- return {
97834
- blockId: draft.id,
97835
- kind: draft.meta.kind,
97836
- reason: "missing_published",
97837
- currentContent,
97838
- publishedContent: null
97839
- };
97840
- }
97841
- if (!currentContent && published) {
97842
- return {
97843
- blockId: draft.id,
97844
- kind: draft.meta.kind,
97845
- reason: "missing_current",
97846
- currentContent: null,
97847
- publishedContent: published
97848
- };
97849
- }
97850
- if (!recordsEqual(
97851
- currentContent,
97852
- published
97853
- )) {
97854
- return {
97855
- blockId: draft.id,
97856
- kind: draft.meta.kind,
97857
- reason: "different",
97858
- currentContent,
97859
- publishedContent: published
97860
- };
97861
- }
97862
- }
97863
- return null;
97864
- },
98288
+ getFirstUnpublishedBlockChange: () => getFirstUnpublishedDraftChange(editorSnapshot),
97865
98289
  markAllBlocksAsPublished: () => {
97866
98290
  const blocks = inspectDrafts(editorSnapshot).map((draft) => ({
97867
98291
  id: draft.id,
@@ -97947,7 +98371,10 @@ function createEditorUiStore(options = {}) {
97947
98371
  const clearHistory = () => {
97948
98372
  clearCoalescingSession();
97949
98373
  const nextHistoryState = createHistoryState(editorSnapshot);
97950
- if (historyState.past.length === 0 && historyState.future.length === 0 && editorHistorySnapshotsEqual(historyState.present, nextHistoryState.present)) {
98374
+ if (historyState.past.length === 0 && historyState.future.length === 0 && editorHistorySnapshotsEqual(
98375
+ historyState.present,
98376
+ nextHistoryState.present
98377
+ )) {
97951
98378
  return;
97952
98379
  }
97953
98380
  historyState = nextHistoryState;
@@ -97988,7 +98415,9 @@ function createEditorUiStore(options = {}) {
97988
98415
  activePreviewField: null,
97989
98416
  focusRequest: null,
97990
98417
  activeBlockId: null,
97991
- setDrawerOpen: (open) => set3((state) => state.drawerOpen === open ? state : { drawerOpen: open }),
98418
+ setDrawerOpen: (open) => set3(
98419
+ (state) => state.drawerOpen === open ? state : { drawerOpen: open }
98420
+ ),
97992
98421
  setPreviewSidebarTab: (tab) => set3(
97993
98422
  (state) => state.previewSidebarTab === tab ? state : { previewSidebarTab: tab }
97994
98423
  ),
@@ -98021,8 +98450,12 @@ function createEditorUiStore(options = {}) {
98021
98450
  itemIndex: typeof payload.itemIndex === "number" ? payload.itemIndex : null
98022
98451
  }
98023
98452
  }),
98024
- clearFocus: () => set3((state) => state.focusRequest === null ? state : { focusRequest: null }),
98025
- setActiveBlockId: (id) => set3((state) => state.activeBlockId === id ? state : { activeBlockId: id }),
98453
+ clearFocus: () => set3(
98454
+ (state) => state.focusRequest === null ? state : { focusRequest: null }
98455
+ ),
98456
+ setActiveBlockId: (id) => set3(
98457
+ (state) => state.activeBlockId === id ? state : { activeBlockId: id }
98458
+ ),
98026
98459
  getDraftSyncState: () => computeDraftSyncState(),
98027
98460
  getUnpublishedState: () => deriveEditorUnpublishedState({
98028
98461
  metadataHasUnpublishedChanges: metadataSlice.hasUnpublishedChanges(),
@@ -98032,6 +98465,12 @@ function createEditorUiStore(options = {}) {
98032
98465
  hasBeenPublishedBefore: editorSnapshot.metadata.publishedBaseline !== null
98033
98466
  }),
98034
98467
  hasAnyUnpublishedChanges: () => get3().getUnpublishedState().hasUnpublishedChanges,
98468
+ applyPublishSuccessTransition: (transition) => {
98469
+ applySystemEditorOperation({
98470
+ type: "apply-publish-success",
98471
+ transition: toEditorPublishSuccessTransition(transition)
98472
+ });
98473
+ },
98035
98474
  history: {
98036
98475
  getState: () => historyState,
98037
98476
  canUndo: () => canUndoHistory(historyState),
@@ -98605,28 +99044,6 @@ function cloneFieldCollection(collection) {
98605
99044
  return JSON.parse(JSON.stringify(collection));
98606
99045
  }
98607
99046
 
98608
- // ../api/src/common/envelope.ts
98609
- function isApiSuccess(result) {
98610
- return result.success === true;
98611
- }
98612
- var ApiEnvelopeError = class extends Error {
98613
- constructor(error) {
98614
- super(error.message);
98615
- this.name = "ApiEnvelopeError";
98616
- this.code = error.code;
98617
- this.requestId = error.requestId;
98618
- this.timestamp = error.timestamp;
98619
- this.status = error.status;
98620
- this.fieldErrors = error.fieldErrors;
98621
- }
98622
- };
98623
- function unwrapResponse(result) {
98624
- if (isApiSuccess(result)) {
98625
- return result.data;
98626
- }
98627
- throw new ApiEnvelopeError(result.error);
98628
- }
98629
-
98630
99047
  // ../api/src/utils/isRecord.ts
98631
99048
  function isRecord16(value) {
98632
99049
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -99286,8 +99703,14 @@ async function waitForAutosavesComplete(uiStore, timeoutMs = 6e4) {
99286
99703
  function getDirtyAutosaveTypes(uiStore, hasRoute) {
99287
99704
  const state = uiStore.getState();
99288
99705
  const snapshots = [
99289
- { scope: { kind: "metadata" }, syncState: state.metadata.getSnapshot().syncState },
99290
- { scope: { kind: "content" }, syncState: state.content.getSnapshot().syncState }
99706
+ {
99707
+ scope: { kind: "metadata" },
99708
+ syncState: state.metadata.getSnapshot().syncState
99709
+ },
99710
+ {
99711
+ scope: { kind: "content" },
99712
+ syncState: state.content.getSnapshot().syncState
99713
+ }
99291
99714
  ];
99292
99715
  if (hasRoute) {
99293
99716
  for (const draft of state.drafts.inspect()) {
@@ -99306,9 +99729,7 @@ function getDirtyAutosaveTypes(uiStore, hasRoute) {
99306
99729
  return uniqueAutosaveSchedulerKeys(deriveDirtyAutosaveScopes(snapshots));
99307
99730
  }
99308
99731
  function hasAutosaveErrors(uiStore) {
99309
- return hasAutosaveStatusFailure(
99310
- getAutosaveStatusesByScheduler(uiStore)
99311
- );
99732
+ return hasAutosaveStatusFailure(getAutosaveStatusesByScheduler(uiStore));
99312
99733
  }
99313
99734
  function autosaveStatusesByScheduler(autosave) {
99314
99735
  return {
@@ -99363,99 +99784,110 @@ function useEntryActions({
99363
99784
  throw new Error(message2);
99364
99785
  }
99365
99786
  }, [uiStore, hasRoute, setErrorMessage]);
99366
- const performPublish = useCallback(async (options) => {
99367
- setErrorMessage(null);
99368
- const validationErrors = validateAllBlocks(uiStore);
99369
- const publishability = derivePublishability({
99370
- unpublishedState: uiStore.getState().getUnpublishedState(),
99371
- validationErrors,
99372
- drawerOpen: uiStore.getState().drawerOpen,
99373
- includeAutosaveFailures: true,
99374
- autosave: getAutosaveStatusesByScheduler(uiStore)
99375
- });
99376
- if (publishability.kind === "blocked") {
99377
- switch (publishability.reason) {
99378
- case "invalidBlocks":
99379
- applyBlockedPublishPlan(
99380
- uiStore,
99381
- publishability.blockedPublishPlan,
99382
- setErrorMessage
99383
- );
99384
- return;
99385
- case "noUnpublishedChanges":
99386
- return;
99387
- case "invalidBlockSummary":
99388
- return;
99389
- case "autosaveFailed":
99390
- setErrorMessage("Cannot publish: failed to save draft changes.");
99391
- throw new Error("Cannot publish: failed to save draft changes.");
99392
- }
99393
- }
99394
- const dirtyTypes = getDirtyAutosaveTypes(uiStore, hasRoute);
99395
- uiStore.getState().autosave.saveNow(dirtyTypes);
99396
- uiStore.getState().autosave.flushAllPending();
99397
- await waitForAutosavesComplete(uiStore);
99398
- const autosavePublishability = derivePublishability({
99399
- unpublishedState: uiStore.getState().getUnpublishedState(),
99400
- validationErrors: [],
99401
- drawerOpen: uiStore.getState().drawerOpen,
99402
- includeAutosaveFailures: true,
99403
- autosave: getAutosaveStatusesByScheduler(uiStore)
99404
- });
99405
- if (autosavePublishability.kind === "blocked" && autosavePublishability.reason === "autosaveFailed") {
99406
- const message2 = "Cannot publish: failed to save draft changes.";
99407
- setErrorMessage(message2);
99408
- throw new Error(message2);
99409
- }
99410
- uiStore.getState().autosave.setMetadataStatus({ status: "saving" });
99411
- try {
99412
- const values = uiStore.getState().metadata.getCurrentValues() || {};
99413
- const publishConfig = latestRef.current.definition.publish;
99414
- const fallbackPayload = options?.mode !== "now" && hasRoute && values.draftStatus === "scheduled" && values.scheduledPublishAt ? { publishAt: values.scheduledPublishAt } : void 0;
99415
- const payload = publishConfig?.buildPayload?.(values, latestRef.current.entry) ?? fallbackPayload;
99416
- const publishResult = await latestRef.current.publishMutation.mutateAsync(payload);
99417
- const nextEntry = publishResult.snapshot;
99418
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
99419
- const snapshot = latestRef.current.syncEntry(nextEntry, {
99420
- clearError: true
99421
- });
99422
- uiStore.getState().autosave.setMetadataStatus({
99423
- status: "success",
99424
- lastSavedAt: timestamp
99787
+ const performPublish = useCallback(
99788
+ async (options) => {
99789
+ setErrorMessage(null);
99790
+ const validationErrors = validateAllBlocks(uiStore);
99791
+ const publishability = derivePublishability({
99792
+ unpublishedState: uiStore.getState().getUnpublishedState(),
99793
+ validationErrors,
99794
+ drawerOpen: uiStore.getState().drawerOpen,
99795
+ includeAutosaveFailures: true,
99796
+ autosave: getAutosaveStatusesByScheduler(uiStore)
99425
99797
  });
99426
- latestRef.current.resetFromSnapshot(snapshot, { keepValues: true });
99427
- uiStore.getState().history.clear();
99428
- uiStore.getState().blockValidation.clearAll();
99429
- const transition = buildPublishSuccessTransition({
99430
- nextEntry,
99431
- routing: latestRef.current.routing,
99432
- publishedContent: publishResult.publishedContent ?? null,
99433
- publishedBlocks: publishResult.publishedBlocks
99798
+ if (publishability.kind === "blocked") {
99799
+ switch (publishability.reason) {
99800
+ case "invalidBlocks":
99801
+ applyBlockedPublishPlan(
99802
+ uiStore,
99803
+ publishability.blockedPublishPlan,
99804
+ setErrorMessage
99805
+ );
99806
+ return;
99807
+ case "noUnpublishedChanges":
99808
+ return;
99809
+ case "invalidBlockSummary":
99810
+ return;
99811
+ case "autosaveFailed":
99812
+ setErrorMessage("Cannot publish: failed to save draft changes.");
99813
+ throw new Error("Cannot publish: failed to save draft changes.");
99814
+ }
99815
+ }
99816
+ const dirtyTypes = getDirtyAutosaveTypes(uiStore, hasRoute);
99817
+ uiStore.getState().autosave.saveNow(dirtyTypes);
99818
+ uiStore.getState().autosave.flushAllPending();
99819
+ await waitForAutosavesComplete(uiStore);
99820
+ const autosavePublishability = derivePublishability({
99821
+ unpublishedState: uiStore.getState().getUnpublishedState(),
99822
+ validationErrors: [],
99823
+ drawerOpen: uiStore.getState().drawerOpen,
99824
+ includeAutosaveFailures: true,
99825
+ autosave: getAutosaveStatusesByScheduler(uiStore)
99434
99826
  });
99435
- uiStore.getState().metadata.setPublishedBaseline(transition.metadataPublishedBaseline);
99436
- uiStore.getState().content.setPublishedBaseline(transition.contentPublishedBaseline);
99437
- if (transition.blockPublishedBaselines) {
99438
- uiStore.getState().drafts.setBlockPublishedBaselinesFromBlocks(
99439
- transition.blockPublishedBaselines
99440
- );
99827
+ if (autosavePublishability.kind === "blocked" && autosavePublishability.reason === "autosaveFailed") {
99828
+ const message2 = "Cannot publish: failed to save draft changes.";
99829
+ setErrorMessage(message2);
99830
+ throw new Error(message2);
99441
99831
  }
99442
- if (isUnpublishedChangesDebugEnabled()) {
99443
- const state = uiStore.getState();
99444
- console.log("[content-editor:useEntryActions.publish] after publish", {
99445
- unpublishedState: state.getUnpublishedState(),
99446
- draftSyncState: state.getDraftSyncState(),
99447
- metadataHasUnpublishedChanges: state.metadata.hasUnpublishedChanges(),
99448
- contentHasUnpublishedChanges: state.content.hasUnpublishedChanges(),
99449
- blocksHaveUnpublishedChanges: state.drafts.hasUnpublishedBlockChanges()
99832
+ uiStore.getState().autosave.setMetadataStatus({ status: "saving" });
99833
+ const contentVersionAtPublishStart = uiStore.getState().content.getSnapshot().version;
99834
+ try {
99835
+ const values = uiStore.getState().metadata.getCurrentValues() || {};
99836
+ const publishConfig = latestRef.current.definition.publish;
99837
+ const fallbackPayload = options?.mode !== "now" && hasRoute && values.draftStatus === "scheduled" && values.scheduledPublishAt ? { publishAt: values.scheduledPublishAt } : void 0;
99838
+ const payload = publishConfig?.buildPayload?.(values, latestRef.current.entry) ?? fallbackPayload;
99839
+ const publishResult = await latestRef.current.publishMutation.mutateAsync(payload);
99840
+ const nextEntry = publishResult.snapshot;
99841
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
99842
+ const snapshot = latestRef.current.syncEntry(nextEntry, {
99843
+ clearError: true
99844
+ });
99845
+ uiStore.getState().autosave.setMetadataStatus({
99846
+ status: "success",
99847
+ lastSavedAt: timestamp
99848
+ });
99849
+ const transition = buildPublishSuccessTransition({
99850
+ nextEntry,
99851
+ routing: latestRef.current.routing,
99852
+ publishedContent: publishResult.publishedContent ?? null,
99853
+ publishedBlocks: publishResult.publishedBlocks
99854
+ });
99855
+ uiStore.getState().applyPublishSuccessTransition({
99856
+ metadata: {
99857
+ baseline: snapshot.baseline,
99858
+ current: snapshot.values,
99859
+ published: transition.metadataPublishedBaseline
99860
+ },
99861
+ content: {
99862
+ published: transition.contentPublishedBaseline,
99863
+ versionAtPublishStart: contentVersionAtPublishStart
99864
+ },
99865
+ blockPublishedBaselines: transition.blockPublishedBaselines
99450
99866
  });
99867
+ uiStore.getState().history.clear();
99868
+ uiStore.getState().blockValidation.clearAll();
99869
+ if (isUnpublishedChangesDebugEnabled()) {
99870
+ const state = uiStore.getState();
99871
+ console.log(
99872
+ "[content-editor:useEntryActions.publish] after publish",
99873
+ {
99874
+ unpublishedState: state.getUnpublishedState(),
99875
+ draftSyncState: state.getDraftSyncState(),
99876
+ metadataHasUnpublishedChanges: state.metadata.hasUnpublishedChanges(),
99877
+ contentHasUnpublishedChanges: state.content.hasUnpublishedChanges(),
99878
+ blocksHaveUnpublishedChanges: state.drafts.hasUnpublishedBlockChanges()
99879
+ }
99880
+ );
99881
+ }
99882
+ } catch (error) {
99883
+ const message2 = error instanceof Error ? error.message : "Failed to publish entry";
99884
+ uiStore.getState().autosave.setMetadataStatus({ status: "error" });
99885
+ setErrorMessage(message2);
99886
+ throw error;
99451
99887
  }
99452
- } catch (error) {
99453
- const message2 = error instanceof Error ? error.message : "Failed to publish entry";
99454
- uiStore.getState().autosave.setMetadataStatus({ status: "error" });
99455
- setErrorMessage(message2);
99456
- throw error;
99457
- }
99458
- }, [hasRoute, uiStore, setErrorMessage]);
99888
+ },
99889
+ [hasRoute, uiStore, setErrorMessage]
99890
+ );
99459
99891
  const performDiscard = useCallback(async () => {
99460
99892
  uiStore.getState().autosave.setMetadataStatus({ status: "saving" });
99461
99893
  setErrorMessage(null);
@@ -100490,7 +100922,7 @@ function useEntrySyncHelpers({
100490
100922
  [createSnapshot, setErrorMessage]
100491
100923
  );
100492
100924
  const resetFromSnapshot = useCallback(
100493
- (snapshot, _resetOptions) => {
100925
+ (snapshot) => {
100494
100926
  uiStore.getState().metadata.hydrate(snapshot.baseline, snapshot.values);
100495
100927
  },
100496
100928
  [uiStore]
@@ -101020,9 +101452,9 @@ function useInternalValue(props2) {
101020
101452
  setErrorMessage
101021
101453
  });
101022
101454
  const resetFromSnapshotWithSkipFlag = useCallback(
101023
- (snapshot, resetOptions) => {
101455
+ (snapshot) => {
101024
101456
  skipAutoSaveRef.current = true;
101025
- resetFromSnapshot(snapshot, resetOptions);
101457
+ resetFromSnapshot(snapshot);
101026
101458
  },
101027
101459
  [resetFromSnapshot]
101028
101460
  );
@@ -126535,6 +126967,7 @@ function createBlockApi(config) {
126535
126967
  body: {
126536
126968
  courseId: data.courseId,
126537
126969
  ...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
126970
+ ...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
126538
126971
  email: data.email,
126539
126972
  name: data.name,
126540
126973
  phone: data.phone,
@@ -127477,6 +127910,7 @@ function useBookingSubmission(_siteId) {
127477
127910
  customFields: data.customFields,
127478
127911
  timezone: data.timezone,
127479
127912
  discountCode: data.discountCode,
127913
+ selectedSlidingAmount: data.selectedSlidingAmount,
127480
127914
  selectedCollectionOptionKind: data.selectedCollectionOptionKind,
127481
127915
  altchaSolution: data.altchaSolution ?? null,
127482
127916
  successUrl: data.successUrl,
@@ -127956,6 +128390,9 @@ function createInitialBookingFlowReducerState(input) {
127956
128390
  fieldValues: collectInitialFieldValues(initialData),
127957
128391
  touchedFields: {},
127958
128392
  discountCode: toOptionalString(initialData.discountCode) ?? "",
128393
+ selectedSlidingAmountInput: toOptionalString(
128394
+ initialData.selectedSlidingAmountInput
128395
+ ) ?? "",
127959
128396
  selectedCollectionOptionKind: toSelectedCollectionOptionKind(
127960
128397
  initialData.selectedCollectionOptionKind
127961
128398
  ),
@@ -128008,6 +128445,7 @@ function bookingFlowReducer(state, event) {
128008
128445
  selectedDate: void 0,
128009
128446
  selectedSlot: null,
128010
128447
  selectedAppointmentPackageId: void 0,
128448
+ selectedSlidingAmountInput: "",
128011
128449
  selectedCollectionOptionKind: void 0,
128012
128450
  validationErrors: clearBookingFormError(state.validationErrors)
128013
128451
  };
@@ -128061,6 +128499,13 @@ function bookingFlowReducer(state, event) {
128061
128499
  selectedAppointmentPackageId: void 0,
128062
128500
  validationErrors: clearBookingFormError(state.validationErrors)
128063
128501
  };
128502
+ case "sliding-amount-changed":
128503
+ return {
128504
+ ...state,
128505
+ selectedSlidingAmountInput: event.value,
128506
+ selectedAppointmentPackageId: void 0,
128507
+ validationErrors: clearBookingFormError(state.validationErrors)
128508
+ };
128064
128509
  case "appointment-package-selected":
128065
128510
  return {
128066
128511
  ...state,
@@ -128163,6 +128608,7 @@ function toBookingFormData(state) {
128163
128608
  selectedDate: state.selectedDate,
128164
128609
  selectedSlot: state.selectedSlot?.startAt,
128165
128610
  discountCode: state.discountCode || void 0,
128611
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
128166
128612
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
128167
128613
  selectedAppointmentPackageId: state.selectedAppointmentPackageId
128168
128614
  };
@@ -128180,7 +128626,8 @@ function buildBookingStepResolution(input) {
128180
128626
  input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
128181
128627
  );
128182
128628
  const selectedService = paymentResolution.service;
128183
- const needsPayment = paymentResolution.mode !== "hidden" || Boolean(
128629
+ const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
128630
+ const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
128184
128631
  input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
128185
128632
  );
128186
128633
  const hasFields = Boolean(input.form.schema?.fields.length);
@@ -128224,6 +128671,18 @@ function validateBookingStep(input) {
128224
128671
  services: input.services,
128225
128672
  defaultServiceId: input.defaultServiceId
128226
128673
  });
128674
+ const slidingScale = getBookingServiceSlidingScale(resolution.service);
128675
+ if (slidingScale && !isBookingServiceSlidingAmountInRange(
128676
+ slidingScale,
128677
+ parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
128678
+ )) {
128679
+ return {
128680
+ ok: false,
128681
+ errors: createFormBookingValidationError(
128682
+ "Please choose an amount within the sliding scale"
128683
+ )
128684
+ };
128685
+ }
128227
128686
  if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
128228
128687
  return { ok: true };
128229
128688
  }
@@ -128633,11 +129092,27 @@ function useHeadlessBookingFlow(options) {
128633
129092
  const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
128634
129093
  const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
128635
129094
  const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
129095
+ const lastSlidingServiceIdRef = useRef(null);
129096
+ useEffect(() => {
129097
+ const selectedId = selectedService?.id ?? null;
129098
+ if (lastSlidingServiceIdRef.current === selectedId) return;
129099
+ lastSlidingServiceIdRef.current = selectedId;
129100
+ const slidingScale = getBookingServiceSlidingScale(selectedService);
129101
+ dispatch({
129102
+ type: "sliding-amount-changed",
129103
+ value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
129104
+ });
129105
+ }, [selectedService]);
128636
129106
  const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
129107
+ const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
129108
+ const selectedSlidingAmount = parseBookingCurrencyInputToCents(
129109
+ state.selectedSlidingAmountInput
129110
+ );
129111
+ const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
128637
129112
  const canLoadAppointmentPackages = Boolean(
128638
- options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
129113
+ options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
128639
129114
  );
128640
- const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
129115
+ const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
128641
129116
  const data = useMemo(() => toBookingFormData(state), [state]);
128642
129117
  const availabilityDatesQuery = useMemo(
128643
129118
  () => buildBookingAvailabilityQuery({
@@ -128867,13 +129342,13 @@ function useHeadlessBookingFlow(options) {
128867
129342
  state.selectedSlot
128868
129343
  ]);
128869
129344
  const appointmentDiscountContext = useMemo(
128870
- () => selectedService && (selectedService.priceAmount ?? 0) > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
128871
- [selectedService?.id, selectedService?.priceAmount]
129345
+ () => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
129346
+ [selectedAppointmentPriceAmount, selectedService?.id]
128872
129347
  );
128873
129348
  const discountUi = useDiscountCodeUi({
128874
129349
  api,
128875
129350
  discountContext: appointmentDiscountContext,
128876
- subtotalCents: selectedService?.priceAmount ?? 0
129351
+ subtotalCents: selectedAppointmentPriceAmount
128877
129352
  });
128878
129353
  const { submit, clearFeedback } = useBookingSubmission(options.siteId);
128879
129354
  const submittingRef = useRef(false);
@@ -129016,6 +129491,7 @@ function useHeadlessBookingFlow(options) {
129016
129491
  type: "appointment-package-selected",
129017
129492
  packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
129018
129493
  }),
129494
+ setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
129019
129495
  setDiscountCode: (code) => {
129020
129496
  dispatch({ type: "discount-code-changed", code });
129021
129497
  latestRef.current.setDiscountCode(code);
@@ -129086,11 +129562,11 @@ function useHeadlessBookingFlow(options) {
129086
129562
  () => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
129087
129563
  serviceTitle: selectedService.title,
129088
129564
  paymentTerms: selectedService.paymentTerms,
129089
- priceAmount: selectedService.priceAmount,
129565
+ priceAmount: selectedAppointmentPriceAmount,
129090
129566
  priceCurrency: selectedService.priceCurrency,
129091
129567
  bookingStartAt: state.selectedSlot?.startAt
129092
129568
  }) : null,
129093
- [paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
129569
+ [paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
129094
129570
  );
129095
129571
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
129096
129572
  const selectedAppointmentPackage = appointmentPackageItems.find(
@@ -129119,6 +129595,9 @@ function useHeadlessBookingFlow(options) {
129119
129595
  selection: null,
129120
129596
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
129121
129597
  selectedAppointmentPackageId: state.selectedAppointmentPackageId,
129598
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput,
129599
+ selectedSlidingAmount,
129600
+ slidingScale: selectedServiceSlidingScale,
129122
129601
  appointmentPackages: appointmentPackagesModel,
129123
129602
  errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
129124
129603
  } : {
@@ -129127,6 +129606,9 @@ function useHeadlessBookingFlow(options) {
129127
129606
  selection: paymentSelection,
129128
129607
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
129129
129608
  selectedAppointmentPackageId: state.selectedAppointmentPackageId,
129609
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput,
129610
+ selectedSlidingAmount,
129611
+ slidingScale: selectedServiceSlidingScale,
129130
129612
  appointmentPackages: appointmentPackagesModel
129131
129613
  };
129132
129614
  return {
@@ -129667,6 +130149,9 @@ var paymentOptionLayoutStyle = {
129667
130149
  var summaryStackStyle = {
129668
130150
  gap: "0.125rem"
129669
130151
  };
130152
+ function formatBookingAmount(amount, currency) {
130153
+ return formatCurrencyAmount(amount, currency, { decimals: "auto" });
130154
+ }
129670
130155
  function HeadlessBookingDefaultForm({
129671
130156
  booking,
129672
130157
  onSubmit
@@ -129943,6 +130428,7 @@ function HeadlessBookingPaymentSelectionStep({
129943
130428
  }
129944
130429
  const packageOptions = booking.payment.appointmentPackages.items;
129945
130430
  const hasPackageOptions = packageOptions.length > 0;
130431
+ const slidingScale = booking.payment.slidingScale;
129946
130432
  return /* @__PURE__ */ jsxs("div", { className: "ab-stack", children: [
129947
130433
  /* @__PURE__ */ jsxs("div", { className: "ab-info-box", children: [
129948
130434
  /* @__PURE__ */ jsx("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
@@ -129953,6 +130439,28 @@ function HeadlessBookingPaymentSelectionStep({
129953
130439
  booking.payment.appointmentPackages.state.message,
129954
130440
  " You can continue with the normal payment option."
129955
130441
  ] }) : null,
130442
+ slidingScale ? /* @__PURE__ */ jsxs("div", { className: "rb-space-y-2", children: [
130443
+ /* @__PURE__ */ jsx("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
130444
+ /* @__PURE__ */ jsxs("p", { className: "rb-caption status-muted", children: [
130445
+ formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
130446
+ " to ",
130447
+ formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
130448
+ slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
130449
+ ] }),
130450
+ /* @__PURE__ */ jsx(
130451
+ "input",
130452
+ {
130453
+ id: "appointment-sliding-amount",
130454
+ type: "number",
130455
+ className: "form-input",
130456
+ min: slidingScale.minAmount / 100,
130457
+ max: slidingScale.maxAmount / 100,
130458
+ step: "0.01",
130459
+ value: booking.payment.selectedSlidingAmountInput,
130460
+ onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
130461
+ }
130462
+ )
130463
+ ] }) : null,
129956
130464
  /* @__PURE__ */ jsxs("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
129957
130465
  packageOptions.map((appointmentPackage) => {
129958
130466
  const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
@@ -131590,6 +132098,7 @@ function useEligibility(params) {
131590
132098
  occurrenceId: params.occurrenceId,
131591
132099
  attendanceMode: params.attendanceMode ?? void 0,
131592
132100
  ticketTypeId: params.ticketTypeId ?? void 0,
132101
+ selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
131593
132102
  email: params.email.trim().toLowerCase(),
131594
132103
  ticketsCount: params.ticketsCount
131595
132104
  });
@@ -131610,7 +132119,7 @@ function useEligibility(params) {
131610
132119
  return () => {
131611
132120
  cancelled = true;
131612
132121
  };
131613
- }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
132122
+ }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
131614
132123
  return {
131615
132124
  state,
131616
132125
  eligibility: state.eligibility,
@@ -131933,6 +132442,41 @@ function TicketCounterLimit(props2) {
131933
132442
  ] }) : null
131934
132443
  ] });
131935
132444
  }
132445
+ function formatCurrencyInputAmount(amount) {
132446
+ const major = amount / 100;
132447
+ return Number.isInteger(major) ? String(major) : major.toFixed(2);
132448
+ }
132449
+ function SlidingScaleAmountField(props2) {
132450
+ const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
132451
+ const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
132452
+ const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
132453
+ return /* @__PURE__ */ jsxs("div", { className: "er-field", children: [
132454
+ /* @__PURE__ */ jsx("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
132455
+ /* @__PURE__ */ jsx(
132456
+ "input",
132457
+ {
132458
+ id: "er-sliding-amount",
132459
+ type: "number",
132460
+ min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
132461
+ max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
132462
+ step: "0.01",
132463
+ inputMode: "decimal",
132464
+ className: "er-input",
132465
+ value: props2.value,
132466
+ onChange: (event) => props2.onChange?.(event.target.value)
132467
+ }
132468
+ ),
132469
+ /* @__PURE__ */ jsxs("p", { className: "er-text er-text--muted", children: [
132470
+ "Choose between ",
132471
+ minLabel,
132472
+ " and ",
132473
+ maxLabel,
132474
+ suggestedLabel ? `; suggested ${suggestedLabel}` : "",
132475
+ "."
132476
+ ] }),
132477
+ props2.message ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: props2.message }) : null
132478
+ ] });
132479
+ }
131936
132480
  function getTicketTypeCounterAvailabilityLabel(input) {
131937
132481
  if (input.selectedRemainingCapacity !== null) {
131938
132482
  return `${input.selectedRemainingCapacity} remaining for this ticket type`;
@@ -131996,6 +132540,10 @@ var TicketSelectionStep = ({
131996
132540
  maxTickets,
131997
132541
  selectedTicketTypeId = null,
131998
132542
  onTicketTypeChange,
132543
+ slidingScale = null,
132544
+ selectedSlidingAmountInput = "",
132545
+ slidingScaleSelectionMessage = null,
132546
+ onSlidingAmountChange,
131999
132547
  onTicketsChange
132000
132548
  }) => {
132001
132549
  const deliveryMode = event?.deliveryMode ?? "in_person";
@@ -132111,6 +132659,16 @@ var TicketSelectionStep = ({
132111
132659
  ] })
132112
132660
  ] })
132113
132661
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
132662
+ slidingScale ? /* @__PURE__ */ jsx(
132663
+ SlidingScaleAmountField,
132664
+ {
132665
+ slidingScale,
132666
+ currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
132667
+ value: selectedSlidingAmountInput,
132668
+ message: slidingScaleSelectionMessage,
132669
+ onChange: onSlidingAmountChange
132670
+ }
132671
+ ) : null,
132114
132672
  /* @__PURE__ */ jsx("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
132115
132673
  /* @__PURE__ */ jsxs("div", { className: "er-ticket-counter-group", children: [
132116
132674
  /* @__PURE__ */ jsx(
@@ -132963,6 +133521,10 @@ function EventRegistrationWizardContent(props2) {
132963
133521
  maxTickets: wizard.maxTicketsNum,
132964
133522
  selectedTicketTypeId: wizard.selectedTicketTypeId,
132965
133523
  onTicketTypeChange: wizard.setSelectedTicketTypeId,
133524
+ slidingScale: wizard.selectedEventSlidingScale,
133525
+ selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
133526
+ slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
133527
+ onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
132966
133528
  onTicketsChange: wizard.setTicketsCount
132967
133529
  }
132968
133530
  )
@@ -133156,7 +133718,7 @@ function EventRegistrationSummaryBar(props2) {
133156
133718
  const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
133157
133719
  const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
133158
133720
  const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
133159
- const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
133721
+ const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
133160
133722
  const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
133161
133723
  const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
133162
133724
  const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
@@ -133556,6 +134118,7 @@ function useEventRegistrationSubmit(options) {
133556
134118
  occurrenceId: submitOccurrenceId,
133557
134119
  attendanceMode: options.selectedAttendanceMode ?? void 0,
133558
134120
  ticketTypeId: options.selectedTicketTypeId ?? void 0,
134121
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
133559
134122
  email: options.formData.email.trim().toLowerCase(),
133560
134123
  name: options.formData.name.trim(),
133561
134124
  ticketsCount: options.ticketsCount,
@@ -133657,6 +134220,35 @@ function useEventRegistrationSubmit(options) {
133657
134220
  }
133658
134221
 
133659
134222
  // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
134223
+ function parseCurrencyInputToCents(value) {
134224
+ const trimmed = value.trim();
134225
+ if (!trimmed) return null;
134226
+ const amount = Number(trimmed);
134227
+ if (!Number.isFinite(amount) || amount < 0) return null;
134228
+ return Math.round(amount * 100);
134229
+ }
134230
+ function formatCentsAsCurrencyInput(amount) {
134231
+ const major = amount / 100;
134232
+ return Number.isInteger(major) ? String(major) : major.toFixed(2);
134233
+ }
134234
+ function getSlidingScaleForEvent(event) {
134235
+ const pricing = event ? resolveRuntimeEventPricing(event) : null;
134236
+ return pricing?.kind === "sliding_scale" ? {
134237
+ minAmount: pricing.minAmount,
134238
+ maxAmount: pricing.maxAmount,
134239
+ suggestedAmount: pricing.suggestedAmount
134240
+ } : null;
134241
+ }
134242
+ function getSlidingScaleSelectionMessage(input) {
134243
+ if (!input.slidingScale) return null;
134244
+ if (input.selectedAmount === null) {
134245
+ return "Choose an amount to continue.";
134246
+ }
134247
+ if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
134248
+ return "Choose an amount within the sliding scale.";
134249
+ }
134250
+ return null;
134251
+ }
133660
134252
  function useEventRegistrationWizard(options) {
133661
134253
  const api = useBlockApi();
133662
134254
  const registrationEvents = useMemo(
@@ -133701,6 +134293,10 @@ function useEventRegistrationWizard(options) {
133701
134293
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
133702
134294
  );
133703
134295
  const [selectedTicketTypeId, setSelectedTicketTypeId] = useState(null);
134296
+ const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState(() => {
134297
+ const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
134298
+ return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
134299
+ });
133704
134300
  const [registrationResult, setRegistrationResult] = useState(null);
133705
134301
  const [errorMessage, setErrorMessage] = useState("");
133706
134302
  const [altchaSolution, setAltchaSolution] = useState(null);
@@ -133737,6 +134333,7 @@ function useEventRegistrationWizard(options) {
133737
134333
  occurrenceId,
133738
134334
  attendanceMode: selectedAttendanceMode,
133739
134335
  ticketTypeId: selectedTicketTypeId,
134336
+ selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
133740
134337
  email: formData.email,
133741
134338
  ticketsCount
133742
134339
  });
@@ -133872,6 +134469,18 @@ function useEventRegistrationWizard(options) {
133872
134469
  }),
133873
134470
  [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
133874
134471
  );
134472
+ const selectedSlidingAmount = useMemo(
134473
+ () => parseCurrencyInputToCents(selectedSlidingAmountInput),
134474
+ [selectedSlidingAmountInput]
134475
+ );
134476
+ const selectedEventSlidingScale = useMemo(
134477
+ () => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
134478
+ [selectedEvent, preSelectedEvent]
134479
+ );
134480
+ const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
134481
+ slidingScale: selectedEventSlidingScale,
134482
+ selectedAmount: selectedSlidingAmount
134483
+ });
133875
134484
  const ticketTypeSelectionRequired = useMemo(() => {
133876
134485
  const event = selectedEvent ?? preSelectedEvent;
133877
134486
  if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
@@ -133940,12 +134549,24 @@ function useEventRegistrationWizard(options) {
133940
134549
  setGuestSectionShake(false);
133941
134550
  };
133942
134551
  const eventRequiresPayment = useMemo(
133943
- () => resolveEventRequiresPayment({
134552
+ () => {
134553
+ if (selectedEventSlidingScale) {
134554
+ return (selectedSlidingAmount ?? 0) > 0;
134555
+ }
134556
+ return resolveEventRequiresPayment({
134557
+ eligibility,
134558
+ selectedTicketType,
134559
+ event: selectedEvent ?? preSelectedEvent
134560
+ });
134561
+ },
134562
+ [
133944
134563
  eligibility,
133945
134564
  selectedTicketType,
133946
- event: selectedEvent ?? preSelectedEvent
133947
- }),
133948
- [eligibility, selectedTicketType, selectedEvent, preSelectedEvent]
134565
+ selectedEvent,
134566
+ preSelectedEvent,
134567
+ selectedEventSlidingScale,
134568
+ selectedSlidingAmount
134569
+ ]
133949
134570
  );
133950
134571
  const handleDetailsComplete = async () => {
133951
134572
  if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
@@ -133954,6 +134575,11 @@ function useEventRegistrationWizard(options) {
133954
134575
  setStep("error");
133955
134576
  return { ok: false, reason: "blocked", message: message2 };
133956
134577
  }
134578
+ if (slidingScaleSelectionMessage) {
134579
+ setErrorMessage(slidingScaleSelectionMessage);
134580
+ setStep("error");
134581
+ return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
134582
+ }
133957
134583
  if (!validateForm()) {
133958
134584
  setGuestSectionShake(true);
133959
134585
  return {
@@ -134038,9 +134664,18 @@ function useEventRegistrationWizard(options) {
134038
134664
  const discountSubtotalCents = useMemo(() => {
134039
134665
  if (discountContext?.type !== "event") return void 0;
134040
134666
  const event = selectedEvent ?? preSelectedEvent;
134041
- const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
134667
+ const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
134042
134668
  return Math.max(0, eventPriceCents * ticketsCount);
134043
- }, [discountContext, selectedTicketType, eligibility, selectedEvent, preSelectedEvent, ticketsCount]);
134669
+ }, [
134670
+ discountContext,
134671
+ selectedTicketType,
134672
+ eligibility,
134673
+ selectedEvent,
134674
+ preSelectedEvent,
134675
+ selectedEventSlidingScale,
134676
+ selectedSlidingAmount,
134677
+ ticketsCount
134678
+ ]);
134044
134679
  const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
134045
134680
  const selectionMethod = paymentSelection.method;
134046
134681
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -134049,6 +134684,7 @@ function useEventRegistrationWizard(options) {
134049
134684
  registrationTarget,
134050
134685
  selectedAttendanceMode,
134051
134686
  selectedTicketTypeId,
134687
+ selectedSlidingAmount,
134052
134688
  ticketsCount,
134053
134689
  formData,
134054
134690
  altchaSolution,
@@ -134063,6 +134699,10 @@ function useEventRegistrationWizard(options) {
134063
134699
  });
134064
134700
  const handleEventSelect = (event) => {
134065
134701
  setSelectedEvent(event);
134702
+ const slidingScale = getSlidingScaleForEvent(event);
134703
+ setSelectedSlidingAmountInput(
134704
+ slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
134705
+ );
134066
134706
  setSelectedAttendanceMode(
134067
134707
  (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
134068
134708
  );
@@ -134072,6 +134712,7 @@ function useEventRegistrationWizard(options) {
134072
134712
  const handleRetry = () => {
134073
134713
  dispatchFlow({ type: "reset", hasPreSelectedContext });
134074
134714
  setSelectedTicketTypeId(null);
134715
+ setSelectedSlidingAmountInput("");
134075
134716
  setSelectedAttendanceMode(
134076
134717
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
134077
134718
  );
@@ -134108,6 +134749,11 @@ function useEventRegistrationWizard(options) {
134108
134749
  setSelectedAttendanceMode,
134109
134750
  selectedTicketTypeId,
134110
134751
  setSelectedTicketTypeId,
134752
+ selectedSlidingAmountInput,
134753
+ setSelectedSlidingAmountInput,
134754
+ selectedSlidingAmount,
134755
+ selectedEventSlidingScale,
134756
+ slidingScaleSelectionMessage,
134111
134757
  selectedTicketType,
134112
134758
  visibleTicketTypes,
134113
134759
  ticketTypeSelectionRequired,
@@ -135188,6 +135834,44 @@ function CoursePricingSelector({
135188
135834
  )
135189
135835
  ] });
135190
135836
  }
135837
+ function CourseSlidingScaleInput({
135838
+ pricing,
135839
+ value,
135840
+ onChange
135841
+ }) {
135842
+ const slidingScale = pricing.slidingScale;
135843
+ if (!slidingScale) {
135844
+ return null;
135845
+ }
135846
+ const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
135847
+ const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
135848
+ const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
135849
+ return /* @__PURE__ */ jsxs("div", { className: "cr-form__field", children: [
135850
+ /* @__PURE__ */ jsx("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
135851
+ /* @__PURE__ */ jsx(
135852
+ "input",
135853
+ {
135854
+ id: "cr-sliding-amount",
135855
+ type: "number",
135856
+ min: slidingScale.minAmount / 100,
135857
+ max: slidingScale.maxAmount / 100,
135858
+ step: "0.01",
135859
+ inputMode: "decimal",
135860
+ className: "cr-form__input",
135861
+ value,
135862
+ onChange: (event) => onChange(event.target.value)
135863
+ }
135864
+ ),
135865
+ /* @__PURE__ */ jsxs("p", { className: "cr-text cr-text--muted", children: [
135866
+ "Choose between ",
135867
+ minLabel,
135868
+ " and ",
135869
+ maxLabel,
135870
+ suggestedLabel ? `; suggested ${suggestedLabel}` : "",
135871
+ "."
135872
+ ] })
135873
+ ] });
135874
+ }
135191
135875
  function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
135192
135876
  const nameErrorId = "cr-name-error";
135193
135877
  const emailErrorId = "cr-email-error";
@@ -135270,6 +135954,17 @@ function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading,
135270
135954
  ] })
135271
135955
  ] });
135272
135956
  }
135957
+ function parseCurrencyInputToCents2(value) {
135958
+ const trimmed = value.trim();
135959
+ if (!trimmed) return null;
135960
+ const amount = Number(trimmed);
135961
+ if (!Number.isFinite(amount) || amount < 0) return null;
135962
+ return Math.round(amount * 100);
135963
+ }
135964
+ function formatCentsAsCurrencyInput2(amount) {
135965
+ const major = amount / 100;
135966
+ return Number.isInteger(major) ? String(major) : major.toFixed(2);
135967
+ }
135273
135968
  function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
135274
135969
  if (!course || portalAuthState === "checking") return false;
135275
135970
  if (hasWaitlistClaimToken) return false;
@@ -135287,12 +135982,27 @@ function getSessionIdFromUrl() {
135287
135982
  }
135288
135983
  function getMissingCoursePricingSelectionMessage(pricing) {
135289
135984
  if (pricing?.requiresSelection && !pricing.selectedOption) {
135985
+ if (pricing.slidingScale) {
135986
+ return "Choose an amount to continue.";
135987
+ }
135290
135988
  return "Choose a pricing option to continue.";
135291
135989
  }
135990
+ if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
135991
+ return "Choose an amount within the sliding scale.";
135992
+ }
135993
+ if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
135994
+ return "Choose an amount within the sliding scale.";
135995
+ }
135292
135996
  return null;
135293
135997
  }
135294
135998
  function buildCoursePricingOptionPayload(pricing) {
135295
- return pricing?.selectedOption ? { pricingOptionId: pricing.selectedOption.id } : {};
135999
+ if (pricing?.selectedOption) {
136000
+ return { pricingOptionId: pricing.selectedOption.id };
136001
+ }
136002
+ if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
136003
+ return { selectedSlidingAmount: pricing.selectedSlidingAmount };
136004
+ }
136005
+ return {};
135296
136006
  }
135297
136007
  function resolveHasCoursePayment(pricing) {
135298
136008
  if (!pricing) {
@@ -135333,6 +136043,7 @@ function useCourseRegistrationWizard(props2) {
135333
136043
  scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
135334
136044
  );
135335
136045
  const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
136046
+ const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
135336
136047
  const [formData, setFormData] = useState({
135337
136048
  name: "",
135338
136049
  email: "",
@@ -135354,8 +136065,12 @@ function useCourseRegistrationWizard(props2) {
135354
136065
  const [bookingMode, setBookingMode] = useState(null);
135355
136066
  const waitlistClaim = useWaitlistClaim();
135356
136067
  const selectedCoursePricing = useMemo(
135357
- () => selectedCourse ? resolveCoursePricingState(selectedCourse, selectedPricingOptionId) : null,
135358
- [selectedCourse, selectedPricingOptionId]
136068
+ () => selectedCourse ? resolveCoursePricingState(
136069
+ selectedCourse,
136070
+ selectedPricingOptionId,
136071
+ parseCurrencyInputToCents2(selectedSlidingAmountInput)
136072
+ ) : null,
136073
+ [selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
135359
136074
  );
135360
136075
  const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
135361
136076
  selectedCoursePricing
@@ -135428,9 +136143,13 @@ function useCourseRegistrationWizard(props2) {
135428
136143
  useEffect(() => {
135429
136144
  if (!selectedCourse) {
135430
136145
  setSelectedPricingOptionId(null);
136146
+ setSelectedSlidingAmountInput("");
135431
136147
  return;
135432
136148
  }
135433
136149
  const defaultPricing = resolveCoursePricingState(selectedCourse, null);
136150
+ setSelectedSlidingAmountInput(
136151
+ defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
136152
+ );
135434
136153
  setSelectedPricingOptionId((previous) => {
135435
136154
  if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
135436
136155
  return previous;
@@ -135805,6 +136524,8 @@ function useCourseRegistrationWizard(props2) {
135805
136524
  selectedCourse,
135806
136525
  selectedPricingOptionId,
135807
136526
  setSelectedPricingOptionId,
136527
+ selectedSlidingAmountInput,
136528
+ setSelectedSlidingAmountInput,
135808
136529
  selectedCoursePricing,
135809
136530
  setSelectedCourse,
135810
136531
  formData,
@@ -135852,6 +136573,19 @@ function useCourseRegistrationWizard(props2) {
135852
136573
  handleBookingModeChange
135853
136574
  };
135854
136575
  }
136576
+ function getCourseSlidingScaleMessage(pricing) {
136577
+ if (!pricing.slidingScale) {
136578
+ return null;
136579
+ }
136580
+ const selectedAmount = pricing.selectedSlidingAmount;
136581
+ if (selectedAmount === null) {
136582
+ return "Choose an amount to continue.";
136583
+ }
136584
+ if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
136585
+ return "Choose an amount within the sliding scale.";
136586
+ }
136587
+ return null;
136588
+ }
135855
136589
  function CourseRegistrationWizard(props2) {
135856
136590
  const {
135857
136591
  showSessions = true,
@@ -135873,6 +136607,8 @@ function CourseRegistrationWizard(props2) {
135873
136607
  selectedCourse,
135874
136608
  selectedPricingOptionId,
135875
136609
  setSelectedPricingOptionId,
136610
+ selectedSlidingAmountInput,
136611
+ setSelectedSlidingAmountInput,
135876
136612
  selectedCoursePricing,
135877
136613
  formData,
135878
136614
  setFormData,
@@ -135943,7 +136679,8 @@ function CourseRegistrationWizard(props2) {
135943
136679
  const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
135944
136680
  const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
135945
136681
  const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
135946
- const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
136682
+ const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
136683
+ const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
135947
136684
  const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
135948
136685
  const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
135949
136686
  course: selectedCourse,
@@ -136036,6 +136773,14 @@ function CourseRegistrationWizard(props2) {
136036
136773
  onSelect: setSelectedPricingOptionId
136037
136774
  }
136038
136775
  ),
136776
+ /* @__PURE__ */ jsx(
136777
+ CourseSlidingScaleInput,
136778
+ {
136779
+ pricing: selectedCourseWithPricing.pricing,
136780
+ value: selectedSlidingAmountInput,
136781
+ onChange: setSelectedSlidingAmountInput
136782
+ }
136783
+ ),
136039
136784
  showSpamProtection && /* @__PURE__ */ jsx("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx(
136040
136785
  AltchaWidget,
136041
136786
  {
@@ -136073,7 +136818,7 @@ function CourseRegistrationWizard(props2) {
136073
136818
  {
136074
136819
  type: "submit",
136075
136820
  className: buttonClass,
136076
- disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
136821
+ disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
136077
136822
  children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
136078
136823
  }
136079
136824
  )
@@ -136083,6 +136828,7 @@ function CourseRegistrationWizard(props2) {
136083
136828
  ),
136084
136829
  courseSoldOut && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "This course is fully booked and there is no waitlist available right now." }),
136085
136830
  pricingSelectionMissing && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
136831
+ slidingScaleMessage && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
136086
136832
  pricingUnavailable && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
136087
136833
  eligibilityError && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--error", children: eligibilityError })
136088
136834
  ] })
@@ -137782,12 +138528,13 @@ var CarouselNodeClient = ({
137782
138528
  ]
137783
138529
  );
137784
138530
  const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
138531
+ const canAutoplay = normalized.autoplay && slides.length > 1;
137785
138532
  const cssVars = React61__default.useMemo(
137786
138533
  () => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
137787
138534
  [normalized.slidesToShow]
137788
138535
  );
137789
138536
  const plugins = React61__default.useMemo(() => {
137790
- if (!normalized.autoplay) return void 0;
138537
+ if (!canAutoplay) return void 0;
137791
138538
  return [
137792
138539
  Autoplay({
137793
138540
  delay: normalized.autoplayDelay,
@@ -137797,7 +138544,7 @@ var CarouselNodeClient = ({
137797
138544
  // Continue after manual navigation
137798
138545
  })
137799
138546
  ];
137800
- }, [normalized.autoplay, normalized.autoplayDelay]);
138547
+ }, [canAutoplay, normalized.autoplayDelay]);
137801
138548
  const [viewportRef, api] = useEmblaCarousel(
137802
138549
  {
137803
138550
  align: "start",
@@ -137836,7 +138583,7 @@ var CarouselNodeClient = ({
137836
138583
  };
137837
138584
  }, [api]);
137838
138585
  React61__default.useEffect(() => {
137839
- if (!api || !normalized.autoplay) return;
138586
+ if (!api || !canAutoplay) return;
137840
138587
  const autoplayPlugin = api.plugins()?.autoplay;
137841
138588
  if (!autoplayPlugin) return;
137842
138589
  const handleVisibility = () => {
@@ -137845,7 +138592,7 @@ var CarouselNodeClient = ({
137845
138592
  };
137846
138593
  document.addEventListener("visibilitychange", handleVisibility);
137847
138594
  return () => document.removeEventListener("visibilitychange", handleVisibility);
137848
- }, [api, normalized.autoplay]);
138595
+ }, [api, canAutoplay]);
137849
138596
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
137850
138597
  /* @__PURE__ */ jsx("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx(
137851
138598
  "div",
@@ -137896,7 +138643,7 @@ var CarouselNodeClient = ({
137896
138643
  "data-show-controls": normalized.showControls ? "true" : "false",
137897
138644
  "data-show-dots": normalized.showDots ? "true" : "false",
137898
138645
  "data-arrow-visibility": normalized.arrowVisibility,
137899
- "data-autoplay": normalized.autoplay ? "true" : "false",
138646
+ "data-autoplay": canAutoplay ? "true" : "false",
137900
138647
  "data-loop": normalized.loop ? "true" : "false",
137901
138648
  children: inner
137902
138649
  }
@@ -150158,6 +150905,14 @@ var MediaUploaderError = class extends Error {
150158
150905
  this.cause = options.cause;
150159
150906
  }
150160
150907
  };
150908
+ var SignedUrlUploadError = class extends Error {
150909
+ constructor(status) {
150910
+ super("Signed URL upload failed");
150911
+ this.name = "SignedUrlUploadError";
150912
+ this.status = status;
150913
+ }
150914
+ };
150915
+ var DEFAULT_UPLOAD_ERROR_MESSAGE = "Upload failed. Please try again.";
150161
150916
  var useApiMediaUploader = ({
150162
150917
  siteId,
150163
150918
  apiClient,
@@ -150166,6 +150921,7 @@ var useApiMediaUploader = ({
150166
150921
  videoPrepIntent,
150167
150922
  loadVideoPrep,
150168
150923
  onClassification,
150924
+ onUploadError,
150169
150925
  logger: providedLogger
150170
150926
  }) => {
150171
150927
  const loggerRef = useRef(providedLogger ?? createConsoleLogger());
@@ -150239,7 +150995,8 @@ var useApiMediaUploader = ({
150239
150995
  });
150240
150996
  }
150241
150997
  } catch (error) {
150242
- const message2 = extractUploadError(error);
150998
+ const uploaderError = mediaUploaderErrorFromCaught(error);
150999
+ const { message: message2 } = uploaderError;
150243
151000
  if (error instanceof ApiRequestError) {
150244
151001
  uploadLogger.error("media upload failed", { status: error.status, message: message2 });
150245
151002
  } else {
@@ -150248,7 +151005,8 @@ var useApiMediaUploader = ({
150248
151005
  error: error instanceof Error ? error.message : String(error)
150249
151006
  });
150250
151007
  }
150251
- throw mediaUploaderErrorFromCaught(error, message2);
151008
+ onUploadError?.(uploaderError, file);
151009
+ throw uploaderError;
150252
151010
  }
150253
151011
  onProgress?.(file.size, file.size, "uploading");
150254
151012
  if (autoClassify) {
@@ -150262,7 +151020,7 @@ var useApiMediaUploader = ({
150262
151020
  }
150263
151021
  return asset;
150264
151022
  },
150265
- [siteId, autoClassify, onClassification, uploadIntent, videoPrepIntent, loadVideoPrep]
151023
+ [siteId, autoClassify, onClassification, uploadIntent, videoPrepIntent, loadVideoPrep, onUploadError]
150266
151024
  );
150267
151025
  };
150268
151026
  async function maybePrepareVideoFile(input) {
@@ -150420,7 +151178,7 @@ var putBlobToSignedUrl = ({
150420
151178
  headers: { "Content-Type": contentType },
150421
151179
  body: blob
150422
151180
  }).then((response) => {
150423
- if (!response.ok) throw new Error(`Upload failed with status ${response.status}`);
151181
+ if (!response.ok) throw new SignedUrlUploadError(response.status);
150424
151182
  });
150425
151183
  }
150426
151184
  return new Promise((resolve, reject) => {
@@ -150434,7 +151192,7 @@ var putBlobToSignedUrl = ({
150434
151192
  if (xhr.status >= 200 && xhr.status < 300) {
150435
151193
  resolve();
150436
151194
  } else {
150437
- reject(new Error(`Upload failed with status ${xhr.status}`));
151195
+ reject(new SignedUrlUploadError(xhr.status));
150438
151196
  }
150439
151197
  });
150440
151198
  xhr.addEventListener("error", () => reject(new Error("Upload failed")));
@@ -150444,27 +151202,28 @@ var putBlobToSignedUrl = ({
150444
151202
  xhr.send(blob);
150445
151203
  });
150446
151204
  };
150447
- var extractUploadError = (error) => {
151205
+ var uploadMessageFromUnknownError = (error) => {
150448
151206
  if (error instanceof ApiEnvelopeError) {
150449
- return error.message.trim() ? error.message : "Upload failed";
151207
+ return error.message.trim() ? error.message : DEFAULT_UPLOAD_ERROR_MESSAGE;
150450
151208
  }
150451
151209
  if (error instanceof ApiRequestError) {
150452
- const payload = error.body;
150453
- for (const value of [payload?.error, payload?.message]) {
150454
- if (typeof value === "string" && value.trim()) {
150455
- return value;
150456
- }
151210
+ const envelope = extractApiEnvelopeErrorDetails(error.body);
151211
+ if (envelope.message) {
151212
+ return envelope.message;
150457
151213
  }
150458
- return `Upload failed with status ${error.status}`;
151214
+ return DEFAULT_UPLOAD_ERROR_MESSAGE;
151215
+ }
151216
+ if (error instanceof SignedUrlUploadError) {
151217
+ return DEFAULT_UPLOAD_ERROR_MESSAGE;
150459
151218
  }
150460
151219
  if (error instanceof Error && error.message.trim()) {
150461
151220
  return error.message;
150462
151221
  }
150463
- return "Upload failed";
151222
+ return DEFAULT_UPLOAD_ERROR_MESSAGE;
150464
151223
  };
150465
- function mediaUploaderErrorFromCaught(error, message2) {
151224
+ function mediaUploaderErrorFromCaught(error) {
150466
151225
  if (error instanceof ApiEnvelopeError) {
150467
- return new MediaUploaderError(message2, {
151226
+ return new MediaUploaderError(uploadMessageFromUnknownError(error), {
150468
151227
  code: error.code,
150469
151228
  status: error.status,
150470
151229
  fieldErrors: error.fieldErrors,
@@ -150472,12 +151231,21 @@ function mediaUploaderErrorFromCaught(error, message2) {
150472
151231
  });
150473
151232
  }
150474
151233
  if (error instanceof ApiRequestError) {
150475
- return new MediaUploaderError(message2, {
151234
+ const envelope = extractApiEnvelopeErrorDetails(error.body);
151235
+ return new MediaUploaderError(envelope.message ?? DEFAULT_UPLOAD_ERROR_MESSAGE, {
151236
+ code: envelope.code ?? error.errorCode,
151237
+ status: envelope.status ?? error.status,
151238
+ fieldErrors: envelope.fieldErrors ?? void 0,
151239
+ cause: error
151240
+ });
151241
+ }
151242
+ if (error instanceof SignedUrlUploadError) {
151243
+ return new MediaUploaderError(DEFAULT_UPLOAD_ERROR_MESSAGE, {
150476
151244
  status: error.status,
150477
151245
  cause: error
150478
151246
  });
150479
151247
  }
150480
- return new MediaUploaderError(message2, { cause: error });
151248
+ return new MediaUploaderError(uploadMessageFromUnknownError(error), { cause: error });
150481
151249
  }
150482
151250
  var findIndex2 = (arr, id) => arr.findIndex((asset) => asset.id === id);
150483
151251
  var MediaLibrary = ({
@@ -156935,7 +157703,8 @@ var MediaPickerDialog = ({
156935
157703
  className: isError ? "h-full bg-destructive" : isSuccess ? "h-full bg-green-500" : "h-full bg-primary",
156936
157704
  style: { width: `${progress}%` }
156937
157705
  }
156938
- ) })
157706
+ ) }),
157707
+ isError && item.error?.message ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-destructive", children: item.error.message }) : null
156939
157708
  ] }, item.id);
156940
157709
  }) }) : null
156941
157710
  ] })
@@ -181838,7 +182607,7 @@ function TabButton({ active, label, onClick }) {
181838
182607
  {
181839
182608
  type: "button",
181840
182609
  className: cn(
181841
- "flex-1 rounded-sm px-3 py-2 text-sm font-medium transition",
182610
+ "min-w-0 flex-1 truncate rounded-sm px-3 py-2 text-sm font-medium transition",
181842
182611
  active ? "bg-background shadow" : "hover:bg-background/50",
181843
182612
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
181844
182613
  ),
@@ -181858,18 +182627,19 @@ function InternalTabPanel(props2) {
181858
182627
  onSearchChange,
181859
182628
  onSelectRouteId
181860
182629
  } = props2;
181861
- return /* @__PURE__ */ jsxs("div", { className: "space-y-3 pt-1", children: [
182630
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-3 pt-1", children: [
181862
182631
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Select any published or draft page, post, or routed entry for this site." }),
181863
182632
  /* @__PURE__ */ jsx(
181864
182633
  Input,
181865
182634
  {
182635
+ className: "min-w-0",
181866
182636
  placeholder: loadingItems ? "Loading\u2026" : "Search content...",
181867
182637
  value: searchQuery,
181868
182638
  onChange: (event) => onSearchChange(event.target.value),
181869
182639
  disabled: loadingItems
181870
182640
  }
181871
182641
  ),
181872
- /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto rounded-md border border-input", children: filteredItems.length > 0 ? filteredItems.map((item) => {
182642
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 max-w-full overflow-hidden rounded-md border border-input", children: /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto", children: filteredItems.length > 0 ? filteredItems.map((item) => {
181873
182643
  const isSelected = selectedRouteId === item.routeId;
181874
182644
  const title = getDisplayTitle(item);
181875
182645
  return /* @__PURE__ */ jsxs(
@@ -181877,12 +182647,12 @@ function InternalTabPanel(props2) {
181877
182647
  {
181878
182648
  type: "button",
181879
182649
  className: cn(
181880
- "flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition-colors hover:bg-muted",
182650
+ "flex min-w-0 w-full items-center gap-2 px-3 py-2 text-left text-sm transition-colors hover:bg-muted",
181881
182651
  isSelected && "bg-muted"
181882
182652
  ),
181883
182653
  onClick: () => onSelectRouteId(item.routeId),
181884
182654
  children: [
181885
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
182655
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 overflow-hidden", children: [
181886
182656
  /* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: title }),
181887
182657
  /* @__PURE__ */ jsx(
181888
182658
  "span",
@@ -181901,12 +182671,12 @@ function InternalTabPanel(props2) {
181901
182671
  },
181902
182672
  item.routeId
181903
182673
  );
181904
- }) : /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: loadingItems ? "Loading\u2026" : errorMessage ?? "No routable content yet" }) }),
181905
- selectedItem ? /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-muted/30 px-3 py-2 text-sm", children: [
181906
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
181907
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
181908
- /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: getDisplayTitle(selectedItem) }),
181909
- /* @__PURE__ */ jsx(Badge2, { variant: "secondary", className: "ml-2 shrink-0", children: selectedItem.typeLabel })
182674
+ }) : /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: loadingItems ? "Loading\u2026" : errorMessage ?? "No routable content yet" }) }) }),
182675
+ selectedItem ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 overflow-hidden rounded-md border border-border bg-muted/30 px-3 py-2 text-sm", children: [
182676
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
182677
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
182678
+ /* @__PURE__ */ jsx("span", { className: "block min-w-0 truncate font-medium", children: getDisplayTitle(selectedItem) }),
182679
+ /* @__PURE__ */ jsx(Badge2, { variant: "secondary", className: "shrink-0", children: selectedItem.typeLabel })
181910
182680
  ] }),
181911
182681
  /* @__PURE__ */ jsx(
181912
182682
  Button,
@@ -181914,7 +182684,7 @@ function InternalTabPanel(props2) {
181914
182684
  type: "button",
181915
182685
  variant: "ghost",
181916
182686
  size: "sm",
181917
- className: "h-7 px-2 text-xs",
182687
+ className: "h-7 shrink-0 px-2 text-xs",
181918
182688
  onClick: () => onSelectRouteId(null),
181919
182689
  children: "Clear"
181920
182690
  }
@@ -182049,13 +182819,13 @@ function LinkPopover({ editor, tone = "dark", initialItems, loadItems }) {
182049
182819
  children: /* @__PURE__ */ jsx(Link, { className: "size-4", "aria-hidden": "true" })
182050
182820
  }
182051
182821
  ),
182052
- /* @__PURE__ */ jsx(Dialog2, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent2, { className: "max-h-[85vh] max-w-2xl overflow-y-auto", children: [
182822
+ /* @__PURE__ */ jsx(Dialog2, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent2, { className: "max-h-[85vh] w-[calc(100vw-2rem)] max-w-2xl overflow-hidden overflow-y-auto", children: [
182053
182823
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
182054
182824
  /* @__PURE__ */ jsx(DialogTitle2, { children: "Choose link" }),
182055
182825
  /* @__PURE__ */ jsx(DialogDescription2, { children: "Select an internal page, an external URL, or a custom path." })
182056
182826
  ] }),
182057
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
182058
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 rounded-md bg-muted/40 p-1", children: [
182827
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-3", children: [
182828
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 gap-2 rounded-md bg-muted/40 p-1", children: [
182059
182829
  /* @__PURE__ */ jsx(TabButton, { active: tab === "internal", label: "Internal", onClick: () => setTab("internal") }),
182060
182830
  /* @__PURE__ */ jsx(TabButton, { active: tab === "external", label: "External URL", onClick: () => setTab("external") }),
182061
182831
  /* @__PURE__ */ jsx(TabButton, { active: tab === "custom", label: "Custom Path", onClick: () => setTab("custom") })
@@ -188533,4 +189303,4 @@ lucide-react/dist/esm/lucide-react.mjs:
188533
189303
  *)
188534
189304
  */
188535
189305
 
188536
- export { AMBIENT_BACKGROUND_ROLES2 as AMBIENT_BACKGROUND_ROLES, ArrowDown, ArrowUp, BackgroundColorField, BackgroundGradientField, Badge2 as Badge, BlockApiProvider, Box, Button, CSS2 as CSS, Callout, CalloutDescription, CalloutTitle, Card, CardContent, CardHeader, CardTitle, Check, ChevronDown, ChevronLeft, ChevronRight, Collapsible2 as Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, CommandMultiSelect, Content, ContentFieldsForm, ContentSpinner, Copy, DEFAULT_LAUNCH_READINESS_INPUT, Dialog2 as Dialog, DialogClose2 as DialogClose, DialogContent2 as DialogContent, DialogDescription2 as DialogDescription, DialogFooter, DialogHeader, DialogTitle2 as DialogTitle, DndContext, DropdownMenu2 as DropdownMenu, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuTrigger2 as DropdownMenuTrigger, EDITABLE_SURFACE_FORWARDING_PROP, EMPTY_DOC, EditableBlockProvider, EditorChrome, EditorProvider, EllipsisVertical, EmptyState2 as EmptyState, EntryControllerProvider, EyeOff, FieldFrame, FixedBottomSurface, FormRenderer, GRADIENT_PRESETS, GripVertical, Image, ImagePlus, Input, KeyboardCode, LINKED_CONTENT_ENTRY_META_KEY, Label4 as Label, List2 as List, LoaderCircle, ManifestForm, Maximize2, MediaEditor, MediaEditorProvider, MediaPickerDialog, MediaPickerMini, Monitor, PAGE_DESIGN_EDITOR_STATE_FETCH_ERROR_MESSAGE, PUBLIC_FILE_FIELD_KINDS, PageRenderer, Palette, PaletteProvider, Pencil, Plus, PointerSensor, PreviewDesignCoordinatorProvider, PreviewDesignHistoryOrderProvider, PreviewRichTextEditor, PreviewTextEditor, PreviewThemeOverlayProvider, ResizableSplitPane, ResponsiveScope, RichText2 as RichText, RichTextEditorSurface, Root2, RotateCcw, SECTION_BACKGROUND_MIN_SOURCE_HEIGHT, SECTION_BACKGROUND_MIN_SOURCE_WIDTH, SITE_CHROME_CLASS_NAMES, SITE_CHROME_VISIBLE_HEADER_SELECTOR, SUBROUTE_KINDS, ScrollableDialogContent, SdkConfigProvider, Search, Select2 as Select, SelectContent2 as SelectContent, SelectItem2 as SelectItem, SelectTrigger2 as SelectTrigger, SelectValue2 as SelectValue, Separator2 as Separator, Settings, SiteChromeCustomizeProvider, SiteDocumentLayout, Smartphone, Sparkles, Surface, Tablet, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Text2 as Text, Textarea, ThemeScope, Trash2, TriangleAlert, Trigger, Upload, X, applyBackgroundOverrideContentPatch, applyCompiledRuntimeFieldsToContent, applyFeatureCardIconSuggestions, applyPageDesignEditorAction, applyResolvedSelections, asDesignBlockId, asRecord, assertNever, assertNever5 as assertNever2, attachRenderableMediaAssetFields, augmentManifestWithStyleGroups, backgroundColorTokens, backgroundOverrideEquals, beginAutosaveBatch, buildApplySiteStyleSelectionBody, buildEditorModelRuntimeFieldsByBlockId, buildSiteChromeLookModels, buildThemeRuntime, buttonPersonalities, canCycleBackgroundOverrideValue, canRedoHistory, canUndoHistory, cancelPreview, classifyHistoryShortcut, classifyKnownMimeType, clearTypographyFontOverrides, clientComponentRegistry, closestCenter, cn, confirmAutosaveBatch, createBlock, createCustomBlockRegistry, createEditorInsertBlockCommand, createEditorRemoveBlockCommand, createEditorReorderBlocksCommand, createEntrySlotBlock, createFeatureCardIconKey, createHistoryState, createManifestFormAdapter, createManifestValidation, createMicrobatcher, createOptimisticActionRunner, createRoutingHelpers, createSnapshotFromPageRecord, createStoreBackend, createStyleConfiguratorState, curatedSiteStyles, cycleSiteChromeLookId, cycleableSiteChromeOptions, decodePublicProductCategorySelectorQuery, defaultBackgroundOverrideForMode, defaultSectionTransitionVariantForFamily, deleteBlock, deleteEntrySlotBlock, deriveLaunchReadiness, deriveRouteMetadataPresentation, deriveStyleConfiguratorCapabilities, deriveTransactionCapabilities, designRuntimeRulesForTheme, dismissNotices, dismissWarnings, emitMediaCropDebug, enabledBackgroundModes, enqueueTransaction, evaluateTypographyFontSlot, evaluateVisibility, expectParsedBrandedId, findButtonPersonality, findFooterLook, findPaletteVariant, findTypographyPreset, foldSubroute, formatSiteChromeBackgroundTokenLabel, getBlockDefinition, getBlockIconSemanticFallbackId, getClientRect, getCuratedSiteStyle, getDirectImageUrlForMediaAsset, getFeatureCardIconCompletion, getFieldIntent, getFooterLayout, getGeneratedBlockIconStyleState, getHeaderLayout, getHeaderStyle, getIconComponent, getIconPickerOptionsForPreset, getLinkedContentEntryMeta, getModalConfig, getPageDesignEditorState, getRichTextImagePositionFromTarget, gradientToCss, idleEditorTransactionQueueState, imagePoolForOverride, inferLegacyOfferingsPreviewGroupOrder, insertOrReplaceRichTextImage, isHeaderField, isIconPickerPreset, isInternalResolvedLinkValue, isKeyboardEvent, isKnownIconName, isNonEmptyValue, isObjectRecord2 as isObjectRecord, isOfferingsPreviewSourceKey, isPreviewingChange, isSupportedLoaderEndpoint, isSvgMimeType, isThemeV2NormalEditorRawStyleFieldName, isThemeV2NormalEditorRawStylePath, listBlockDescriptors, listContentTypes, listEntryPageContentSlots, lucide_react_exports, markApplyFailed, markApplySaved, markApplySaving, mergeBlockDescriptorsWithRegistry, mergeManifestWithSdkOptions, mutateBlockContent, normalEditorCuratedPromotedFieldPaths, normalizeOfferingsPreviewGroupOrder, normalizePickerSearchThreshold, normalizePublicApiLoaderParams, openRow, paletteOverridesSchema, paletteVariants, parseAspectRatioValue, parseBackgroundOverrideFromContent, parseBlockIconValue, parseMediaAssetId, parseSiteIconStyleGuideVersionId, parseSiteId, planBackgroundOverride, planBackgroundTransition, planPageDesignLayoutLookCompatibility, planSiteChromeFooterLayoutSelection, planSiteChromeLookSelection, planSiteDocument, planSiteStylePreviewChange, prefetchBlockData, previewAssistantEnabled, previewButtonPersonality, previewDesignHistoryDomainForCommand, previewFooterLook, previewHeaderLayout, previewHeaderStyle, previewPaletteVariant, previewSiteStyle, previewTypographyPreset, pushHistoryEntry, rankBackgroundImagePoolItems, recoveryConflictCopy, redoHistory, rejectAutosaveBatch, renderBlock, reorderBlocks, reorderEntrySlotBlocks, requireEntriesForCuratedChoices, resolveBackgroundCapability, resolveBlockTitle, resolveContentTitle, resolveIconPickerPreset, resolveImageUrlWithContext, resolveMediaSlotContract, resolveOfferingsPreviewGroupOrderEntries, resolvePageRouteSlug, resolvePickerSelectionLabel, resolvePreviewSidebarTab, resolveStyleConfiguratorInitialSnapshot, resolveVideoSelectionIntentForMediaField, resolveVisiblePromotedFieldPathsForEditorBlock, sectionTransitionFamilies, sectionTransitionFamilyForBoundaryOptionId, sectionTransitionVariantForBoundaryOptionId, selectPreviewDesignHistoryDomain, selectionSnapshotFromApplySiteStyleSelectionResponse, setPaletteOverrides, setTypographyBodyFontOverride, setTypographyHeadingFontOverride, shouldShowPickerSearch, siteFooterManifest, siteHeaderManifest, siteOptionSources, stableSerialize, styleConfiguratorHistoryEntryForPersistedSelection, suggestFeatureCardSemanticIcons, suggestSemanticIconForFeatureCard, surfaceResolutionContextFromTheme, syncStyleConfiguratorState, systemCustomizeFacetAppliesToLayoutVariant, systemCustomizeFacetApplyContentPatch, systemCustomizeFacetCurrentValue, systemCustomizeFacetDefinitionForBlock, systemCustomizeFacetDefinitionsForBlock, systemCustomizeFacetLabelForValue, systemCustomizeFacetNextValue, systemCustomizeFacetRollbackContentPatch, toFeatureCardIconSuggestionInputs, toRoutableLinkPayload, toggleRow, typographyPresets, undoHistory, unfinishedBlockCopy, unsafeAsEditorBlockId, unsafeAsEditorBlockValues, unsafeAsLinkedContentEntryId, unwrapResponse, useAsyncPickerOptions, useBackendWatch, useBlockContext, useCombinedRefs, useDebouncedLatestSave, useDndContext, useDraggable, useDroppable, useEditor, useEditorUiStore, useEditorUiStoreInstance, useEntryController, useEntryEditorController, useField, useIsomorphicLayoutEffect3 as useIsomorphicLayoutEffect, useMediaEditor, useMediaEditorOptional, useMultiAutosave, useOptionalEditorUiStoreInstance, usePreviewDesignCoordinator, usePreviewDesignHistoryOrder, usePreviewThemeOverlay, useRichTextEditor, useSdkConfig, useSensor, useSensors, useSiteChromeCustomizeOptional, useUISelector, useUniqueId, validateBlockManifestIssues, visibleHeaderClearancePx };
189306
+ export { AMBIENT_BACKGROUND_ROLES2 as AMBIENT_BACKGROUND_ROLES, ArrowDown, ArrowUp, BackgroundColorField, BackgroundGradientField, Badge2 as Badge, BlockApiProvider, Box, Button, CSS2 as CSS, Callout, CalloutDescription, CalloutTitle, Card, CardContent, CardHeader, CardTitle, Check, ChevronDown, ChevronLeft, ChevronRight, Collapsible2 as Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, CommandMultiSelect, Content, ContentFieldsForm, ContentSpinner, Copy, DEFAULT_LAUNCH_READINESS_INPUT, Dialog2 as Dialog, DialogClose2 as DialogClose, DialogContent2 as DialogContent, DialogDescription2 as DialogDescription, DialogFooter, DialogHeader, DialogTitle2 as DialogTitle, DndContext, DropdownMenu2 as DropdownMenu, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuTrigger2 as DropdownMenuTrigger, EDITABLE_SURFACE_FORWARDING_PROP, EMPTY_DOC, EditableBlockProvider, EditorChrome, EditorProvider, EllipsisVertical, EmptyState2 as EmptyState, EntryControllerProvider, EyeOff, FieldFrame, FixedBottomSurface, FormRenderer, GRADIENT_PRESETS, GripVertical, Image, ImagePlus, Input, KeyboardCode, LINKED_CONTENT_ENTRY_META_KEY, Label4 as Label, List2 as List, LoaderCircle, ManifestForm, Maximize2, MediaEditor, MediaEditorProvider, MediaPickerDialog, MediaPickerMini, Monitor, PAGE_DESIGN_EDITOR_STATE_FETCH_ERROR_MESSAGE, PUBLIC_FILE_FIELD_KINDS, PageRenderer, Palette, PaletteProvider, Pencil, Plus, PointerSensor, PreviewDesignCoordinatorProvider, PreviewDesignHistoryOrderProvider, PreviewRichTextEditor, PreviewTextEditor, PreviewThemeOverlayProvider, ResizableSplitPane, ResponsiveScope, RichText2 as RichText, RichTextEditorSurface, Root2, RotateCcw, SECTION_BACKGROUND_MIN_SOURCE_HEIGHT, SECTION_BACKGROUND_MIN_SOURCE_WIDTH, SITE_CHROME_CLASS_NAMES, SITE_CHROME_VISIBLE_HEADER_SELECTOR, SUBROUTE_KINDS, ScrollableDialogContent, SdkConfigProvider, Search, Select2 as Select, SelectContent2 as SelectContent, SelectItem2 as SelectItem, SelectTrigger2 as SelectTrigger, SelectValue2 as SelectValue, Separator2 as Separator, Settings, SiteChromeCustomizeProvider, SiteDocumentLayout, Smartphone, Sparkles, Surface, Tablet, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Text2 as Text, Textarea, ThemeScope, Trash2, TriangleAlert, Trigger, Upload, X, applyBackgroundOverrideContentPatch, applyCompiledRuntimeFieldsToContent, applyFeatureCardIconSuggestions, applyPageDesignEditorAction, applyResolvedSelections, asDesignBlockId, asRecord, assertNever, assertNever5 as assertNever2, attachRenderableMediaAssetFields, augmentManifestWithStyleGroups, backgroundColorTokens, backgroundOverrideEquals, beginAutosaveBatch, buildApplySiteStyleSelectionBody, buildEditorModelRuntimeFieldsByBlockId, buildSiteChromeLookModels, buildThemeRuntime, buttonPersonalities, canCycleBackgroundOverrideValue, canRedoHistory, canUndoHistory, cancelPreview, classifyHistoryShortcut, classifyKnownMimeType, clearTypographyFontOverrides, clientComponentRegistry, closestCenter, cn, confirmAutosaveBatch, createBlock, createCustomBlockRegistry, createEditorInsertBlockCommand, createEditorRemoveBlockCommand, createEditorReorderBlocksCommand, createEntrySlotBlock, createFeatureCardIconKey, createHistoryState, createManifestFormAdapter, createManifestValidation, createMicrobatcher, createOptimisticActionRunner, createRoutingHelpers, createSnapshotFromPageRecord, createStoreBackend, createStyleConfiguratorState, curatedSiteStyles, cycleSiteChromeLookId, cycleableSiteChromeOptions, decodePublicProductCategorySelectorQuery, defaultBackgroundOverrideForMode, defaultSectionTransitionVariantForFamily, deleteBlock, deleteEntrySlotBlock, deriveLaunchReadiness, deriveRouteMetadataPresentation, deriveStyleConfiguratorCapabilities, deriveTransactionCapabilities, designRuntimeRulesForTheme, dismissNotices, dismissWarnings, emitMediaCropDebug, enabledBackgroundModes, enqueueTransaction, evaluateTypographyFontSlot, evaluateVisibility, expectParsedBrandedId, findButtonPersonality, findFooterLook, findPaletteVariant, findTypographyPreset, foldSubroute, formatSiteChromeBackgroundTokenLabel, getBlockDefinition, getBlockIconSemanticFallbackId, getClientRect, getCuratedSiteStyle, getDirectImageUrlForMediaAsset, getFeatureCardIconCompletion, getFieldIntent, getFooterLayout, getGeneratedBlockIconStyleState, getHeaderLayout, getHeaderStyle, getIconComponent, getIconPickerOptionsForPreset, getLinkedContentEntryMeta, getModalConfig, getPageDesignEditorState, getRichTextImagePositionFromTarget, gradientToCss, idleEditorTransactionQueueState, imagePoolForOverride, inferLegacyOfferingsPreviewGroupOrder, insertOrReplaceRichTextImage, isHeaderField, isIconPickerPreset, isInternalResolvedLinkValue, isKeyboardEvent, isKnownIconName, isNonEmptyValue, isObjectRecord2 as isObjectRecord, isOfferingsPreviewSourceKey, isPreviewingChange, isSupportedLoaderEndpoint, isSvgMimeType, isThemeV2NormalEditorRawStyleFieldName, isThemeV2NormalEditorRawStylePath, listBlockDescriptors, listContentTypes, listEntryPageContentSlots, lucide_react_exports, markApplyFailed, markApplySaved, markApplySaving, mergeBlockDescriptorsWithRegistry, mergeManifestWithSdkOptions, mutateBlockContent, normalEditorCuratedPromotedFieldPaths, normalizeOfferingsPreviewGroupOrder, normalizePickerSearchThreshold, normalizePublicApiLoaderParams, openRow, paletteOverridesSchema, paletteVariants, parseAspectRatioValue, parseBackgroundOverrideFromContent, parseBlockIconValue, parseMediaAssetId, parseSiteIconStyleGuideVersionId, parseSiteId, planBackgroundOverride, planBackgroundTransition, planPageDesignLayoutLookCompatibility, planSiteChromeFooterLayoutSelection, planSiteChromeLookSelection, planSiteDocument, planSiteStylePreviewChange, prefetchBlockData, previewAssistantEnabled, previewButtonPersonality, previewDesignHistoryDomainForCommand, previewFooterLook, previewHeaderLayout, previewHeaderStyle, previewPaletteVariant, previewSiteStyle, previewTypographyPreset, pushHistoryEntry, rankBackgroundImagePoolItems, recoveryConflictCopy, redoHistory, rejectAutosaveBatch, renderBlock, reorderBlocks, reorderEntrySlotBlocks, requireEntriesForCuratedChoices, resolveBackgroundCapability, resolveBlockTitle, resolveContentTitle, resolveIconPickerPreset, resolveImageUrlWithContext, resolveMediaSlotContract, resolveOfferingsPreviewGroupOrderEntries, resolvePageRouteSlug, resolvePickerSelectionLabel, resolvePreviewSidebarTab, resolveStyleConfiguratorInitialSnapshot, resolveVideoSelectionIntentForMediaField, resolveVisiblePromotedFieldPathsForEditorBlock, sectionTransitionFamilies, sectionTransitionFamilyForBoundaryOptionId, sectionTransitionVariantForBoundaryOptionId, selectPreviewDesignHistoryDomain, selectionSnapshotFromApplySiteStyleSelectionResponse, setPaletteOverrides, setTypographyBodyFontOverride, setTypographyHeadingFontOverride, shouldShowPickerSearch, siteFooterManifest, siteHeaderManifest, siteOptionSources, stableSerialize, styleConfiguratorHistoryEntryForPersistedSelection, suggestFeatureCardSemanticIcons, suggestSemanticIconForFeatureCard, surfaceResolutionContextFromTheme, syncStyleConfiguratorState, systemCustomizeFacetAppliesToLayoutVariant, systemCustomizeFacetApplyContentPatch, systemCustomizeFacetCurrentValue, systemCustomizeFacetDefinitionForBlock, systemCustomizeFacetDefinitionsForBlock, systemCustomizeFacetLabelForValue, systemCustomizeFacetNextValue, systemCustomizeFacetRollbackContentPatch, toFeatureCardIconSuggestionInputs, toRoutableLinkPayload, toggleRow, typographyPresets, undoHistory, unfinishedBlockCopy, unsafeAsEditorBlockId, unsafeAsEditorBlockValues, unsafeAsLinkedContentEntryId, useAsyncPickerOptions, useBackendWatch, useBlockContext, useCombinedRefs, useDebouncedLatestSave, useDndContext, useDraggable, useDroppable, useEditor, useEditorUiStore, useEditorUiStoreInstance, useEntryController, useEntryEditorController, useField, useIsomorphicLayoutEffect3 as useIsomorphicLayoutEffect, useMediaEditor, useMediaEditorOptional, useMultiAutosave, useOptionalEditorUiStoreInstance, usePreviewDesignCoordinator, usePreviewDesignHistoryOrder, usePreviewThemeOverlay, useRichTextEditor, useSdkConfig, useSensor, useSensors, useSiteChromeCustomizeOptional, useUISelector, useUniqueId, validateBlockManifestIssues, visibleHeaderClearancePx };