@riverbankcms/sdk 0.64.0 → 0.67.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 (78) hide show
  1. package/dist/_dts/api/src/aiPlayground.d.ts +18 -11
  2. package/dist/_dts/api/src/apiEndpointTypes.d.ts +12 -0
  3. package/dist/_dts/api/src/bookingOperations.d.ts +1 -1
  4. package/dist/_dts/api/src/endpoints.d.ts +25 -0
  5. package/dist/_dts/api/src/sdkConfig/contracts.d.ts +0 -40
  6. package/dist/_dts/api/src/sdkContracts.d.ts +1 -1
  7. package/dist/_dts/api/src/siteMembers.d.ts +1 -1
  8. package/dist/_dts/api/src/siteOperations.d.ts +1 -1
  9. package/dist/_dts/billing/src/plans/types.d.ts +1 -1
  10. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -1
  11. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  12. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +1 -0
  13. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +2 -1
  14. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +81 -0
  15. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +7 -3
  16. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  17. package/dist/_dts/sdk/src/cli/commands/push/execute/footer.d.ts +33 -0
  18. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +2 -1
  19. package/dist/_dts/sdk/src/cli/env.d.ts +2 -1
  20. package/dist/_dts/sdk/src/cli/merge-remote/entryMergePush.d.ts +2 -1
  21. package/dist/_dts/sdk/src/cli/site-commands/commandKeys.d.ts +13 -0
  22. package/dist/_dts/sdk/src/cli/site-commands/commandRuntime.d.ts +114 -0
  23. package/dist/_dts/sdk/src/cli/site-commands/entryCommands.d.ts +26 -48
  24. package/dist/_dts/sdk/src/cli/site-commands/footerCommands.d.ts +50 -0
  25. package/dist/_dts/sdk/src/cli/site-commands/formCommands.d.ts +57 -0
  26. package/dist/_dts/sdk/src/cli/site-commands/index.d.ts +5 -0
  27. package/dist/_dts/sdk/src/cli/site-commands/navigationCommands.d.ts +57 -0
  28. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +83 -0
  29. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +67 -14
  30. package/dist/_dts/sdk/src/cli/sync/executor.d.ts +10 -28
  31. package/dist/_dts/sdk/src/cli/sync/index.d.ts +1 -1
  32. package/dist/_dts/sdk/src/config/dashboard-validation.d.ts +0 -48
  33. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  34. package/dist/_dts/sdk/src/version.d.ts +1 -1
  35. package/dist/_dts/site-commands/src/adapter.d.ts +2 -2
  36. package/dist/_dts/site-commands/src/commands.d.ts +410 -13
  37. package/dist/_dts/site-commands/src/domain.d.ts +3 -3
  38. package/dist/_dts/site-commands/src/exposure.d.ts +41 -0
  39. package/dist/_dts/site-commands/src/index.d.ts +1 -0
  40. package/dist/_dts/site-commands/src/metadata.d.ts +93 -2
  41. package/dist/_dts/site-commands/src/planner.d.ts +13 -6
  42. package/dist/_dts/site-commands/src/refs.d.ts +13 -1
  43. package/dist/_dts/theme-core/src/palette/utils/index.d.ts +1 -0
  44. package/dist/_dts/theme-core/src/palette/utils/onColor.d.ts +2 -0
  45. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +83 -0
  46. package/dist/_dts/theme-core/src/site-styles/contentTemplateRuntimeCompiler.d.ts +2 -1
  47. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +89 -12
  48. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +8 -2
  49. package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
  50. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +3 -2
  51. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +9 -6
  52. package/dist/_dts/ui/src/callout.d.ts +1 -1
  53. package/dist/cli/index.mjs +4290 -2513
  54. package/dist/client/client.mjs +598 -372
  55. package/dist/client/hooks.mjs +311 -123
  56. package/dist/client/rendering/client.mjs +209 -68
  57. package/dist/client/rendering/islands.mjs +281 -150
  58. package/dist/client/rendering.mjs +416 -190
  59. package/dist/preview-next/before-render.mjs +61 -13
  60. package/dist/preview-next/client/runtime.mjs +930 -376
  61. package/dist/preview-next/middleware.mjs +61 -13
  62. package/dist/server/components.mjs +526 -325
  63. package/dist/server/config-validation.mjs +313 -125
  64. package/dist/server/config.mjs +313 -125
  65. package/dist/server/data.mjs +311 -123
  66. package/dist/server/index.mjs +78 -16
  67. package/dist/server/next.mjs +527 -326
  68. package/dist/server/page-converter.mjs +159 -41
  69. package/dist/server/prebuild.mjs +1 -1
  70. package/dist/server/rendering/server.mjs +526 -325
  71. package/dist/server/rendering.mjs +526 -325
  72. package/dist/server/routing.mjs +392 -131
  73. package/dist/server/server.mjs +312 -124
  74. package/dist/server/theme-bridge.mjs +155 -48
  75. package/package.json +1 -1
  76. package/dist/_dts/path-utils/src/index.d.ts +0 -8
  77. package/dist/_dts/path-utils/src/redirectPaths.d.ts +0 -26
  78. package/dist/_dts/path-utils/src/safeAppPath.d.ts +0 -26
@@ -31,6 +31,17 @@ function getPortalToken(cookieStore) {
31
31
  // src/next/catch-all.tsx
32
32
  import { BlocksIslandsHydrator } from "#sdk-rendering-client";
33
33
 
34
+ // ../api/src/apiEndpointTypes.ts
35
+ function blockedDemoMutationPolicy(classification, publicMessage) {
36
+ if (publicMessage.trim() === "") {
37
+ throw new Error(`Demo mutation policy ${classification} requires publicMessage.`);
38
+ }
39
+ return {
40
+ classification,
41
+ publicMessage
42
+ };
43
+ }
44
+
34
45
  // ../api/src/cache-tags.ts
35
46
  var TAG_TEMPLATES = {
36
47
  siteCollection: "riverbank:site",
@@ -61,6 +72,18 @@ var TAG_TEMPLATES = {
61
72
  };
62
73
 
63
74
  // ../api/src/endpoints.ts
75
+ var DEMO_MUTATION_BLOCKED_HIDDEN = blockedDemoMutationPolicy(
76
+ "blocked-hidden",
77
+ "This action is not available in demo sites."
78
+ );
79
+ var DEMO_MUTATION_BLOCKED_DISABLED = blockedDemoMutationPolicy(
80
+ "blocked-disabled",
81
+ "This setting is disabled in demo sites."
82
+ );
83
+ var DEMO_MUTATION_INTERNAL_ONLY = blockedDemoMutationPolicy(
84
+ "internal-only",
85
+ "This internal operation is not available in demo sites."
86
+ );
64
87
  var ENDPOINT_DEFINITIONS = {
65
88
  // AI endpoints - no cache due to dynamic nature
66
89
  aiContentUpdateChat: {
@@ -177,7 +200,8 @@ var ENDPOINT_DEFINITIONS = {
177
200
  path: "/sites/{siteId}/ai/generate",
178
201
  method: "POST",
179
202
  auth: "user",
180
- responseKind: "json"
203
+ responseKind: "json",
204
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
181
205
  },
182
206
  getOnboardingPreviewStatus: {
183
207
  path: "/public/sites/{siteId}/onboarding/preview-status",
@@ -198,7 +222,8 @@ var ENDPOINT_DEFINITIONS = {
198
222
  method: "POST",
199
223
  auth: "user",
200
224
  errors: [],
201
- responseKind: "json"
225
+ responseKind: "json",
226
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED
202
227
  },
203
228
  goLiveSite: {
204
229
  path: "/sites/{siteId}/launch/go-live",
@@ -267,20 +292,23 @@ var ENDPOINT_DEFINITIONS = {
267
292
  path: "/sites/{siteId}/ai/site-wizard/goals",
268
293
  method: "POST",
269
294
  auth: "user",
270
- responseKind: "json"
295
+ responseKind: "json",
296
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
271
297
  },
272
298
  aiSiteWizardIntakeTriage: {
273
299
  path: "/sites/{siteId}/ai/site-wizard/intake-triage",
274
300
  method: "POST",
275
301
  auth: "user",
276
- responseKind: "json"
302
+ responseKind: "json",
303
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
277
304
  },
278
305
  aiSiteWizardTelemetry: {
279
306
  path: "/sites/{siteId}/ai/site-wizard/telemetry",
280
307
  method: "POST",
281
308
  auth: "user",
282
309
  errors: [],
283
- responseKind: "json"
310
+ responseKind: "json",
311
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
284
312
  },
285
313
  // Admin SEO
286
314
  listGscPropertiesAdmin: {
@@ -487,7 +515,7 @@ var ENDPOINT_DEFINITIONS = {
487
515
  responseKind: "json",
488
516
  errors: ["resource:not_found", "server:internal_error"]
489
517
  },
490
- // Ops (event hosts/admins)
518
+ // Ops (staff event operators/admins)
491
519
  opsListUpcomingEventOccurrences: {
492
520
  path: "/ops/sites/{siteId}/events",
493
521
  method: "GET",
@@ -505,6 +533,7 @@ var ENDPOINT_DEFINITIONS = {
505
533
  method: "POST",
506
534
  auth: "user",
507
535
  responseKind: "json",
536
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
508
537
  errors: [
509
538
  "validation:invalid_input",
510
539
  "auth:forbidden",
@@ -517,6 +546,7 @@ var ENDPOINT_DEFINITIONS = {
517
546
  method: "POST",
518
547
  auth: "user",
519
548
  responseKind: "json",
549
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
520
550
  errors: [
521
551
  "validation:invalid_input",
522
552
  "auth:forbidden",
@@ -535,6 +565,7 @@ var ENDPOINT_DEFINITIONS = {
535
565
  method: "POST",
536
566
  auth: "user",
537
567
  responseKind: "json",
568
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
538
569
  errors: [
539
570
  "validation:invalid_input",
540
571
  "auth:forbidden",
@@ -568,6 +599,7 @@ var ENDPOINT_DEFINITIONS = {
568
599
  method: "POST",
569
600
  auth: "user",
570
601
  responseKind: "json",
602
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
571
603
  errors: [
572
604
  "validation:invalid_input",
573
605
  "auth:forbidden",
@@ -596,7 +628,8 @@ var ENDPOINT_DEFINITIONS = {
596
628
  method: "POST",
597
629
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings],
598
630
  auth: "user",
599
- responseKind: "json"
631
+ responseKind: "json",
632
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
600
633
  },
601
634
  previewEmailTemplate: {
602
635
  path: "/sites/{siteId}/settings/emails/preview",
@@ -647,14 +680,16 @@ var ENDPOINT_DEFINITIONS = {
647
680
  method: "POST",
648
681
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
649
682
  auth: "user",
650
- responseKind: "json"
683
+ responseKind: "json",
684
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
651
685
  },
652
686
  createNewsletterSubscribersImportUploadUrl: {
653
687
  path: "/sites/{siteId}/newsletter/subscribers/import-url",
654
688
  method: "POST",
655
689
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
656
690
  auth: "user",
657
- responseKind: "json"
691
+ responseKind: "json",
692
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
658
693
  },
659
694
  exportNewsletterSubscribersCsv: {
660
695
  path: "/sites/{siteId}/newsletter/subscribers/export.csv",
@@ -851,14 +886,16 @@ var ENDPOINT_DEFINITIONS = {
851
886
  method: "POST",
852
887
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
853
888
  auth: "user",
854
- responseKind: "json"
889
+ responseKind: "json",
890
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
855
891
  },
856
892
  testSendNewsletterCampaign: {
857
893
  path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/test-send",
858
894
  method: "POST",
859
895
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
860
896
  auth: "user",
861
- responseKind: "json"
897
+ responseKind: "json",
898
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
862
899
  },
863
900
  listNewsletterSendJobs: {
864
901
  path: "/sites/{siteId}/newsletter/jobs",
@@ -1546,7 +1583,8 @@ var ENDPOINT_DEFINITIONS = {
1546
1583
  method: "DELETE",
1547
1584
  tags: ["site", "site-{siteId}"],
1548
1585
  auth: "user",
1549
- responseKind: "json"
1586
+ responseKind: "json",
1587
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
1550
1588
  },
1551
1589
  listSiteMembers: {
1552
1590
  path: "/sites/{siteId}/members",
@@ -2002,7 +2040,8 @@ var ENDPOINT_DEFINITIONS = {
2002
2040
  method: "POST",
2003
2041
  tags: ["site-{siteId}", "content-{siteId}-{type}"],
2004
2042
  auth: "user",
2005
- responseKind: "json"
2043
+ responseKind: "json",
2044
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
2006
2045
  },
2007
2046
  updateSiteGeneralSettings: {
2008
2047
  path: "/sites/{siteId}/settings/general",
@@ -4241,6 +4280,7 @@ var ENDPOINT_DEFINITIONS = {
4241
4280
  method: "POST",
4242
4281
  tags: ["site-{siteId}"],
4243
4282
  auth: "user",
4283
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
4244
4284
  errors: [
4245
4285
  "validation:invalid_input",
4246
4286
  "auth:forbidden",
@@ -4255,6 +4295,7 @@ var ENDPOINT_DEFINITIONS = {
4255
4295
  method: "POST",
4256
4296
  tags: ["site-{siteId}"],
4257
4297
  auth: "user",
4298
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
4258
4299
  errors: [
4259
4300
  "validation:invalid_input",
4260
4301
  "auth:forbidden",
@@ -4564,6 +4605,7 @@ var ENDPOINT_DEFINITIONS = {
4564
4605
  tags: ["site-{siteId}", "passes-{siteId}"],
4565
4606
  auth: "user",
4566
4607
  responseKind: "json",
4608
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4567
4609
  errors: ["validation:invalid_input", "server:internal_error"]
4568
4610
  },
4569
4611
  getBookingPass: {
@@ -4579,6 +4621,7 @@ var ENDPOINT_DEFINITIONS = {
4579
4621
  tags: ["site-{siteId}", "passes-{siteId}"],
4580
4622
  auth: "user",
4581
4623
  responseKind: "json",
4624
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4582
4625
  errors: [
4583
4626
  "validation:invalid_input",
4584
4627
  "resource:not_found",
@@ -4591,6 +4634,7 @@ var ENDPOINT_DEFINITIONS = {
4591
4634
  tags: ["site-{siteId}", "passes-{siteId}"],
4592
4635
  auth: "user",
4593
4636
  responseKind: "json",
4637
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4594
4638
  errors: [
4595
4639
  "validation:invalid_input",
4596
4640
  "resource:not_found",
@@ -4646,6 +4690,7 @@ var ENDPOINT_DEFINITIONS = {
4646
4690
  tags: ["site-{siteId}", "memberships-{siteId}"],
4647
4691
  auth: "user",
4648
4692
  responseKind: "json",
4693
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4649
4694
  errors: ["validation:invalid_input", "server:internal_error"]
4650
4695
  },
4651
4696
  getBookingMembership: {
@@ -4661,6 +4706,7 @@ var ENDPOINT_DEFINITIONS = {
4661
4706
  tags: ["site-{siteId}", "memberships-{siteId}"],
4662
4707
  auth: "user",
4663
4708
  responseKind: "json",
4709
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4664
4710
  errors: [
4665
4711
  "validation:invalid_input",
4666
4712
  "resource:not_found",
@@ -4673,6 +4719,7 @@ var ENDPOINT_DEFINITIONS = {
4673
4719
  tags: ["site-{siteId}", "memberships-{siteId}"],
4674
4720
  auth: "user",
4675
4721
  responseKind: "json",
4722
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4676
4723
  errors: [
4677
4724
  "validation:invalid_input",
4678
4725
  "resource:not_found",
@@ -4889,6 +4936,7 @@ var ENDPOINT_DEFINITIONS = {
4889
4936
  tags: ["site-{siteId}", "customers-{siteId}"],
4890
4937
  auth: "user",
4891
4938
  responseKind: "json",
4939
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
4892
4940
  errors: [
4893
4941
  "validation:invalid_input",
4894
4942
  "auth:forbidden",
@@ -7537,8 +7585,7 @@ var dashboardNavVisibilityBaseSchema = z5.object({
7537
7585
  var dashboardNavVisibilityRolesSchema = z5.object({
7538
7586
  administrator: dashboardNavVisibilityBaseSchema.optional(),
7539
7587
  editor: dashboardNavVisibilityBaseSchema.optional(),
7540
- team_member: dashboardNavVisibilityBaseSchema.optional(),
7541
- event_host: dashboardNavVisibilityBaseSchema.optional()
7588
+ team_member: dashboardNavVisibilityBaseSchema.optional()
7542
7589
  }).strip().optional();
7543
7590
  var dashboardNavVisibilitySchema = dashboardNavVisibilityBaseSchema.extend({
7544
7591
  roles: dashboardNavVisibilityRolesSchema
@@ -8483,6 +8530,21 @@ var appointmentSetupServiceDraftSchema = z7.object({
8483
8530
  timezone: z7.string().trim().min(1).nullable(),
8484
8531
  payment: appointmentSetupPaymentDraftSchema,
8485
8532
  assignment: appointmentSetupServiceAssignmentDraftSchema
8533
+ }).superRefine((service, ctx) => {
8534
+ if (service.payment.priceType === "paid" && (service.priceAmount === null || service.priceAmount <= 0)) {
8535
+ ctx.addIssue({
8536
+ code: "custom",
8537
+ path: ["priceAmount"],
8538
+ message: "Paid appointment services need a positive price."
8539
+ });
8540
+ }
8541
+ if (service.payment.priceType === "free" && service.priceAmount !== null && service.priceAmount > 0) {
8542
+ ctx.addIssue({
8543
+ code: "custom",
8544
+ path: ["priceAmount"],
8545
+ message: "Free appointment services cannot carry a positive price."
8546
+ });
8547
+ }
8486
8548
  });
8487
8549
  var appointmentSetupPractitionerDraftSchema = z7.object({
8488
8550
  ref: appointmentSetupRefSchema,
@@ -9556,6 +9618,144 @@ function resolveVariantKey(manifest, content) {
9556
9618
  return null;
9557
9619
  }
9558
9620
 
9621
+ // ../theme-core/src/palette/utils/colorConversion.ts
9622
+ var clamp01 = (x) => Math.max(0, Math.min(1, x));
9623
+ var mod = (a, n) => (a % n + n) % n;
9624
+ var deg = (x) => mod(x, 360);
9625
+ function hexToRgb(hex) {
9626
+ const h = hex.replace(/^#/, "");
9627
+ const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
9628
+ if (m.length !== 6) throw new Error("Bad hex");
9629
+ const int = parseInt(m, 16);
9630
+ return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
9631
+ }
9632
+ function rgbToHex(r2, g, b) {
9633
+ const to = (n) => Math.round(n).toString(16).padStart(2, "0");
9634
+ return `#${to(r2)}${to(g)}${to(b)}`;
9635
+ }
9636
+ function srgbToLinear(u) {
9637
+ const x = u / 255;
9638
+ return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
9639
+ }
9640
+ function linearToSrgb(x) {
9641
+ const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
9642
+ return clamp01(y) * 255;
9643
+ }
9644
+ function rgbToHsl(r2, g, b) {
9645
+ const R = r2 / 255, G = g / 255, B = b / 255;
9646
+ const max = Math.max(R, G, B), min = Math.min(R, G, B);
9647
+ const d = max - min;
9648
+ let h = 0;
9649
+ if (d !== 0) {
9650
+ switch (max) {
9651
+ case R:
9652
+ h = (G - B) / d + (G < B ? 6 : 0);
9653
+ break;
9654
+ case G:
9655
+ h = (B - R) / d + 2;
9656
+ break;
9657
+ case B:
9658
+ h = (R - G) / d + 4;
9659
+ break;
9660
+ }
9661
+ h *= 60;
9662
+ }
9663
+ const l = (max + min) / 2;
9664
+ const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
9665
+ return { h, s, l };
9666
+ }
9667
+ function srgbToOklab(r2, g, b) {
9668
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
9669
+ const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
9670
+ const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
9671
+ const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
9672
+ const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
9673
+ const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
9674
+ const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
9675
+ const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
9676
+ return { L, a, b: b2 };
9677
+ }
9678
+ function oklabToSrgb(L, a, b) {
9679
+ const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
9680
+ const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
9681
+ const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
9682
+ const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
9683
+ const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
9684
+ const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
9685
+ return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
9686
+ }
9687
+ function oklabToOklch(L, a, b) {
9688
+ const C = Math.sqrt(a * a + b * b);
9689
+ const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
9690
+ return { L, C, h };
9691
+ }
9692
+ function oklchToOklab(L, C, h) {
9693
+ const hr = h * Math.PI / 180;
9694
+ const a = C * Math.cos(hr);
9695
+ const b = C * Math.sin(hr);
9696
+ return { L, a, b };
9697
+ }
9698
+ function inSRGB(r2, g, b) {
9699
+ return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
9700
+ }
9701
+ function oklchToHexGamut(L, C, h) {
9702
+ let lo = 0, hi = C, best = 0;
9703
+ for (let i = 0; i < 18; i++) {
9704
+ const mid = (lo + hi) / 2;
9705
+ const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
9706
+ const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
9707
+ if (inSRGB(r3, g2, bb2)) {
9708
+ best = mid;
9709
+ lo = mid;
9710
+ } else {
9711
+ hi = mid;
9712
+ }
9713
+ }
9714
+ const { a, b } = oklchToOklab(L, best, h);
9715
+ const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
9716
+ return rgbToHex(r2, g, bb);
9717
+ }
9718
+ function featuresFromHex(hex) {
9719
+ const { r: r2, g, b } = hexToRgb(hex);
9720
+ const { h, s, l } = rgbToHsl(r2, g, b);
9721
+ const { L, a, b: b2 } = srgbToOklab(r2, g, b);
9722
+ const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
9723
+ const max = Math.max(r2, g, b);
9724
+ const v = max / 255;
9725
+ const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
9726
+ const chroma = s;
9727
+ return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
9728
+ }
9729
+
9730
+ // ../theme-core/src/palette/utils/contrast.ts
9731
+ function relativeLuminance(r2, g, b) {
9732
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
9733
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
9734
+ }
9735
+
9736
+ // ../theme-core/src/palette/utils/onColor.ts
9737
+ var BACKGROUND_ROLE_NAMES = /* @__PURE__ */ new Set([
9738
+ "primary",
9739
+ "secondary",
9740
+ "accent",
9741
+ "success",
9742
+ "warning",
9743
+ "destructive",
9744
+ "info",
9745
+ "background",
9746
+ "surface",
9747
+ "surfaceAlt",
9748
+ "muted",
9749
+ "neutral"
9750
+ ]);
9751
+ function onColorTokenName(backgroundToken) {
9752
+ return `on${backgroundToken.split("-").filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`;
9753
+ }
9754
+ function isOnColorBackgroundCandidateToken(token) {
9755
+ const role = token.match(/^(.*?)(?:-\d{2,3})?$/)?.[1] ?? token;
9756
+ return BACKGROUND_ROLE_NAMES.has(role);
9757
+ }
9758
+
9559
9759
  // ../theme-core/src/site-styles/appearancePresetResolution.ts
9560
9760
  function assertValidOptionGroups(preset2) {
9561
9761
  preset2.optionGroups?.forEach((group) => {
@@ -15177,6 +15377,9 @@ var curatedSiteStyleIdValues = [
15177
15377
  "site-style:bright-community",
15178
15378
  "site-style:quiet-luxury",
15179
15379
  "site-style:practical-services",
15380
+ "site-style:quiet-practice",
15381
+ "site-style:personal-retreat-journal",
15382
+ "site-style:tactile-workshop",
15180
15383
  "site-style:modern-wellness",
15181
15384
  "site-style:bold-launch",
15182
15385
  "site-style:south-west-twerk-school"
@@ -15259,7 +15462,8 @@ function defineCuratedSiteStyle(input) {
15259
15462
  name: input.name,
15260
15463
  description: input.description,
15261
15464
  generationBrief: input.generationBrief,
15262
- selectionKeywords: input.selectionKeywords ?? [],
15465
+ selectionKeywordRules: input.selectionKeywordRules ?? [],
15466
+ siteCreatorSelection: input.siteCreatorSelection ?? { kind: "explicit_only" },
15263
15467
  template: {
15264
15468
  id: asDesignSystemTemplateId(`template:${input.id.replace("site-style:", "")}`),
15265
15469
  name: input.name,
@@ -15403,12 +15607,13 @@ var curatedSiteStyles = [
15403
15607
  name: "Quiet Luxury",
15404
15608
  description: "Minimal, confident, and refined for premium experiences and private services.",
15405
15609
  generationBrief: "Use fewer claims, more specificity, and restrained sensory detail. Favor elegant media and low repetition over dense panels.",
15406
- selectionKeywords: [
15407
- "luxury",
15408
- "premium",
15409
- "boutique",
15410
- "bespoke",
15411
- "exclusive"
15610
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 20 },
15611
+ selectionKeywordRules: [
15612
+ { kind: "word", value: "luxury" },
15613
+ { kind: "word", value: "premium" },
15614
+ { kind: "word", value: "boutique" },
15615
+ { kind: "word", value: "bespoke" },
15616
+ { kind: "word", value: "exclusive" }
15412
15617
  ],
15413
15618
  tokenRecipes: {
15414
15619
  palette: "high-contrast",
@@ -15437,13 +15642,14 @@ var curatedSiteStyles = [
15437
15642
  name: "Practical Services",
15438
15643
  description: "Efficient, plainspoken, and conversion-focused for trades and everyday services.",
15439
15644
  generationBrief: "Make services, location, trust signals, and contact paths obvious. Keep copy brief and avoid ornate visual treatments.",
15440
- selectionKeywords: [
15441
- "repair",
15442
- "plumb",
15443
- "electric",
15444
- "cleaning",
15445
- "landscap",
15446
- "contractor"
15645
+ siteCreatorSelection: { kind: "primary_goal_support" },
15646
+ selectionKeywordRules: [
15647
+ { kind: "word", value: "repair" },
15648
+ { kind: "substring", value: "plumb" },
15649
+ { kind: "substring", value: "electric" },
15650
+ { kind: "word", value: "cleaning" },
15651
+ { kind: "substring", value: "landscap" },
15652
+ { kind: "substring", value: "contractor" }
15447
15653
  ],
15448
15654
  tokenRecipes: {
15449
15655
  palette: "brand-led",
@@ -15494,18 +15700,134 @@ var curatedSiteStyles = [
15494
15700
  paletteChoice("warm-neutral-forest")
15495
15701
  ]
15496
15702
  }),
15703
+ defineCuratedSiteStyle({
15704
+ id: "site-style:quiet-practice",
15705
+ name: "Quiet Practice",
15706
+ description: "Grounded, calm, and practical for small appointment-first practices.",
15707
+ generationBrief: "Make services, practitioner trust, preparation notes, and booking routes easy to scan. Keep the tone warm and specific, with quiet confidence rather than spa cliches or medical claims.",
15708
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 30 },
15709
+ selectionKeywordRules: [
15710
+ { kind: "substring", value: "massage" },
15711
+ { kind: "word", value: "bodywork" },
15712
+ { kind: "phrase", value: "appointment practice" },
15713
+ { kind: "phrase", value: "appointment-first" },
15714
+ { kind: "substring", value: "practitioner" },
15715
+ { kind: "substring", value: "therap" },
15716
+ { kind: "substring", value: "clinic" },
15717
+ { kind: "phrase", value: "wellness practice" }
15718
+ ],
15719
+ tokenRecipes: {
15720
+ palette: "soft-natural",
15721
+ contrast: "standard",
15722
+ radius: "soft",
15723
+ shadow: "subtle",
15724
+ typography: "clean-sans",
15725
+ spacing: "regular",
15726
+ motion: "subtle"
15727
+ },
15728
+ compositionBudget: quietBudget,
15729
+ recommendedHeaderLookIds: ["practical-utility", "clean-base", "centered-calm"],
15730
+ buttonPersonalityChoices: [
15731
+ buttonChoice("pebble"),
15732
+ buttonChoice("soft-pill"),
15733
+ buttonChoice("editorial-link")
15734
+ ],
15735
+ paletteVariantChoices: [
15736
+ paletteChoice("soft-natural-stone"),
15737
+ paletteChoice("soft-natural-sage"),
15738
+ paletteChoice("warm-neutral-clay")
15739
+ ]
15740
+ }),
15741
+ defineCuratedSiteStyle({
15742
+ id: "site-style:personal-retreat-journal",
15743
+ name: "Personal Retreat Journal",
15744
+ description: "Warm, story-led, and readable for solo practitioners with mixed offers.",
15745
+ generationBrief: "Center the practitioner as the guide, then make private sessions, classes, retreats, and resources feel like clear pathways. Keep retreat copy grounded and practical, with enough editorial warmth for longer reading.",
15746
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 40 },
15747
+ selectionKeywordRules: [
15748
+ { kind: "substring", value: "retreat" },
15749
+ { kind: "phrase", value: "solo practitioner" },
15750
+ { kind: "phrase", value: "personal brand" },
15751
+ { kind: "substring", value: "teacher" },
15752
+ { kind: "substring", value: "coach" },
15753
+ { kind: "phrase", value: "retreat resources" },
15754
+ { kind: "substring", value: "journal" }
15755
+ ],
15756
+ tokenRecipes: {
15757
+ palette: "warm-neutral",
15758
+ contrast: "standard",
15759
+ radius: "soft",
15760
+ shadow: "subtle",
15761
+ typography: "serif-editorial",
15762
+ spacing: "airy",
15763
+ motion: "subtle"
15764
+ },
15765
+ compositionBudget: balancedBudget,
15766
+ recommendedHeaderLookIds: ["editorial-line", "centered-calm", "minimal-transparent"],
15767
+ buttonPersonalityChoices: [
15768
+ buttonChoice("editorial-link"),
15769
+ buttonChoice("soft-pill"),
15770
+ buttonChoice("brushed-wash")
15771
+ ],
15772
+ paletteVariantChoices: [
15773
+ paletteChoice("warm-neutral-forest"),
15774
+ paletteChoice("warm-neutral-clay"),
15775
+ paletteChoice("soft-natural-stone")
15776
+ ]
15777
+ }),
15778
+ defineCuratedSiteStyle({
15779
+ id: "site-style:tactile-workshop",
15780
+ name: "Tactile Workshop",
15781
+ description: "Bright, hands-on, and image-led for maker studios, workshops, and creative classes.",
15782
+ generationBrief: "Lead with objects, materials, studio process, and practical booking detail. Keep the tone warm and direct, with useful mess, clear dates, and enough gallery rhythm to feel like a real creative studio.",
15783
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 50 },
15784
+ selectionKeywordRules: [
15785
+ { kind: "substring", value: "ceramic" },
15786
+ { kind: "word", value: "pottery" },
15787
+ { kind: "phrase", value: "maker studio" },
15788
+ { kind: "phrase", value: "craft class" },
15789
+ { kind: "phrase", value: "craft workshop" },
15790
+ { kind: "word", value: "clay" },
15791
+ { kind: "word", value: "kiln" }
15792
+ ],
15793
+ tokenRecipes: {
15794
+ palette: "brand-led",
15795
+ contrast: "standard",
15796
+ radius: "soft",
15797
+ shadow: "subtle",
15798
+ typography: "friendly-sans",
15799
+ spacing: "regular",
15800
+ motion: "subtle"
15801
+ },
15802
+ compositionBudget: balancedBudget,
15803
+ recommendedHeaderLookIds: ["brand-solid", "practical-utility", "clean-base"],
15804
+ recommendedFooterLookIds: ["site-footer-brand-two-band", "footer-muted-grounding"],
15805
+ buttonPersonalityChoices: [
15806
+ buttonChoice("pebble"),
15807
+ buttonChoice("confident-chip"),
15808
+ buttonChoice("ink-stamp"),
15809
+ buttonChoice("editorial-link")
15810
+ ],
15811
+ paletteVariantChoices: [
15812
+ paletteChoice("brand-led-warm"),
15813
+ paletteChoice("brand-led-cool"),
15814
+ paletteChoice("soft-natural-watercolor"),
15815
+ paletteChoice("warm-neutral-clay")
15816
+ ]
15817
+ }),
15497
15818
  defineCuratedSiteStyle({
15498
15819
  id: "site-style:bold-launch",
15499
15820
  name: "Bold Launch",
15500
15821
  description: "High-energy and punchy for launches, campaigns, and creative offers.",
15501
15822
  generationBrief: "Use crisp positioning, bold hero structure, strong calls to action, and confident visual rhythm. Keep it precise, not shouty.",
15502
- selectionKeywords: [
15503
- "launch",
15504
- "campaign",
15505
- "preorder",
15506
- "pre-order",
15507
- "waitlist",
15508
- "drop"
15823
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 10 },
15824
+ selectionKeywordRules: [
15825
+ { kind: "substring", value: "launch" },
15826
+ { kind: "substring", value: "campaign" },
15827
+ { kind: "word", value: "preorder" },
15828
+ { kind: "phrase", value: "pre-order" },
15829
+ { kind: "substring", value: "waitlist" },
15830
+ { kind: "word", value: "drop" }
15509
15831
  ],
15510
15832
  tokenRecipes: {
15511
15833
  palette: "high-contrast",
@@ -15536,15 +15858,6 @@ var curatedSiteStyles = [
15536
15858
  name: "South West Twerk School",
15537
15859
  description: "Energetic, editorial, and high-contrast for a branded dance school presence.",
15538
15860
  generationBrief: "Use confident rhythm, bold burgundy-and-gold accents, large editorial intro copy, strong booking routes, and dark feature sections where proof or forms need emphasis.",
15539
- selectionKeywords: [
15540
- "dance",
15541
- "classes",
15542
- "workshop",
15543
- "school",
15544
- "movement",
15545
- "performance",
15546
- "community"
15547
- ],
15548
15861
  tokenRecipes: {
15549
15862
  palette: "brand-led",
15550
15863
  contrast: "maximum",
@@ -15787,6 +16100,148 @@ var modernMinimalTheme = {
15787
16100
  }
15788
16101
  };
15789
16102
 
16103
+ // ../theme-core/src/palette/generateShades.ts
16104
+ function generateShades(hexColor, name) {
16105
+ const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
16106
+ const base = featuresFromHex(hexColor);
16107
+ const hue = base.okH;
16108
+ const baseChroma = base.okC;
16109
+ const toneMap = {
16110
+ 50: 0.975,
16111
+ 100: 0.945,
16112
+ 200: 0.89,
16113
+ 300: 0.82,
16114
+ 400: 0.74,
16115
+ 500: 0.66,
16116
+ 600: 0.58,
16117
+ 700: 0.49,
16118
+ 800: 0.4,
16119
+ 900: 0.28,
16120
+ 950: 0.16
16121
+ };
16122
+ const shadeDefs = shadeSteps.map((step, idx) => {
16123
+ const t = idx / (shadeSteps.length - 1);
16124
+ const L = toneMap[step];
16125
+ const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
16126
+ const C = baseChroma * chromaFactor;
16127
+ return {
16128
+ name: `${name}-${step}`,
16129
+ hex: oklchToHexGamut(L, C, hue)
16130
+ };
16131
+ });
16132
+ shadeDefs.push({ name, hex: hexColor });
16133
+ return shadeDefs;
16134
+ }
16135
+
16136
+ // ../theme-core/src/palette/neutralScale.ts
16137
+ function generateNeutralScale({
16138
+ background,
16139
+ steps = 11,
16140
+ warm = false
16141
+ }) {
16142
+ const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
16143
+ const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
16144
+ const count = Math.min(steps, shadeNames.length);
16145
+ const scale = [];
16146
+ for (let i = 0; i < count; i++) {
16147
+ const t = i / (count - 1);
16148
+ const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
16149
+ const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
16150
+ const name = `neutral-${shadeNames[i]}`;
16151
+ scale.push({ name, hex });
16152
+ }
16153
+ return scale;
16154
+ }
16155
+ function mix(a, b, t) {
16156
+ return a + (b - a) * Math.max(0, Math.min(1, t));
16157
+ }
16158
+
16159
+ // ../theme-core/src/palette/utils/textColor.ts
16160
+ function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
16161
+ const { r: r2, g, b } = parseColorToRgb(background);
16162
+ const luminance = relativeLuminance(r2, g, b);
16163
+ const blackContrast = (luminance + 0.05) / 0.05;
16164
+ const whiteContrast = 1.05 / (luminance + 0.05);
16165
+ if (blackContrast >= minContrast && whiteContrast < minContrast) {
16166
+ return "#000000";
16167
+ }
16168
+ if (whiteContrast >= minContrast && blackContrast < minContrast) {
16169
+ return "#FFFFFF";
16170
+ }
16171
+ return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
16172
+ }
16173
+ function getTextColorForBackground(background) {
16174
+ return pickBlackOrWhiteTextColor(background);
16175
+ }
16176
+ function parseColorToRgb(input) {
16177
+ const trimmed = input.trim();
16178
+ if (trimmed.startsWith("#")) {
16179
+ return hexToRgb(trimmed);
16180
+ }
16181
+ const rgbMatch = trimmed.match(
16182
+ /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
16183
+ );
16184
+ if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
16185
+ return {
16186
+ r: clamp255(Number(rgbMatch[1])),
16187
+ g: clamp255(Number(rgbMatch[2])),
16188
+ b: clamp255(Number(rgbMatch[3]))
16189
+ };
16190
+ }
16191
+ throw new Error("Unsupported color format");
16192
+ }
16193
+ function clamp255(value) {
16194
+ if (Number.isNaN(value)) return 0;
16195
+ return Math.max(0, Math.min(255, value));
16196
+ }
16197
+
16198
+ // ../theme-core/src/palette/expandPalette.ts
16199
+ function colorsToMap(palette) {
16200
+ const map = {};
16201
+ for (const c of palette.colors) {
16202
+ map[c.name] = c.hex;
16203
+ }
16204
+ return map;
16205
+ }
16206
+ function isBackgroundDark(hex) {
16207
+ try {
16208
+ return featuresFromHex(hex).Y < 0.5;
16209
+ } catch {
16210
+ return false;
16211
+ }
16212
+ }
16213
+ function expandPalette(palette) {
16214
+ const base = colorsToMap(palette);
16215
+ const expanded = { ...base };
16216
+ const background = base.background || base.surface || "#ffffff";
16217
+ const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
16218
+ neutral2.forEach((n) => {
16219
+ expanded[n.name] = n.hex;
16220
+ });
16221
+ for (const [name, hex] of Object.entries(base)) {
16222
+ if (hex) {
16223
+ const shades = generateShades(hex, name);
16224
+ shades.forEach((shade) => {
16225
+ expanded[shade.name] = shade.hex;
16226
+ });
16227
+ }
16228
+ }
16229
+ if (base.text) expanded.body = base.text;
16230
+ if (base.danger && !base.destructive) {
16231
+ expanded.destructive = base.danger;
16232
+ }
16233
+ const isDark = base.background ? isBackgroundDark(base.background) : false;
16234
+ const isDarkMode = palette.meta?.mode === "dark" || isDark;
16235
+ expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
16236
+ for (const [token, hex] of Object.entries({ ...expanded })) {
16237
+ if (!hex || !isOnColorBackgroundCandidateToken(token)) continue;
16238
+ const onToken = onColorTokenName(token);
16239
+ if (expanded[onToken]) continue;
16240
+ expanded[onToken] = getTextColorForBackground(hex);
16241
+ }
16242
+ return expanded;
16243
+ }
16244
+
15790
16245
  // ../theme-core/src/site-styles/designState.ts
15791
16246
  import { z as z30 } from "zod";
15792
16247
 
@@ -15955,25 +16410,19 @@ var defaultDesignRuntimeRules = defineDesignRuntimeRules({
15955
16410
  "muted-band": {
15956
16411
  background: {
15957
16412
  type: "color",
15958
- color: "muted",
15959
- textColor: "text",
15960
- headingColor: "text"
16413
+ color: "muted"
15961
16414
  }
15962
16415
  },
15963
16416
  "accent-band": {
15964
16417
  background: {
15965
16418
  type: "color",
15966
- color: "primary",
15967
- textColor: "primaryForeground",
15968
- headingColor: "primaryForeground"
16419
+ color: "primary"
15969
16420
  }
15970
16421
  },
15971
16422
  "brand-depth-band": {
15972
16423
  background: {
15973
16424
  type: "color",
15974
- color: "primary-800",
15975
- textColor: "primaryForeground",
15976
- headingColor: "primaryForeground"
16425
+ color: "primary-800"
15977
16426
  }
15978
16427
  },
15979
16428
  "hero-image": {
@@ -22195,6 +22644,16 @@ var jsonArrayTransform = {
22195
22644
  return "";
22196
22645
  }
22197
22646
  };
22647
+ var csvTransform = {
22648
+ id: "value.csv",
22649
+ kind: "formatter",
22650
+ summary: "Normalize a string or array of strings into a comma-separated list",
22651
+ run: (value) => {
22652
+ const rawValues = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
22653
+ const normalized = rawValues.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
22654
+ return normalized.length > 0 ? Array.from(new Set(normalized)).join(",") : "";
22655
+ }
22656
+ };
22198
22657
  var marqueeLoopOptionsSchema = z39.object({
22199
22658
  minItems: z39.number().int().min(1).default(10)
22200
22659
  });
@@ -22220,6 +22679,7 @@ var formattingTransforms = [
22220
22679
  dateFormatShort,
22221
22680
  arrayLengthTransform,
22222
22681
  jsonArrayTransform,
22682
+ csvTransform,
22223
22683
  marqueeLoopTransform
22224
22684
  ];
22225
22685
 
@@ -22703,117 +23163,6 @@ var uiTransforms = [
22703
23163
 
22704
23164
  // ../blocks/src/system/transforms/registry/layout.ts
22705
23165
  import { z as z41 } from "zod";
22706
-
22707
- // ../theme-core/src/palette/utils/colorConversion.ts
22708
- var clamp01 = (x) => Math.max(0, Math.min(1, x));
22709
- var mod = (a, n) => (a % n + n) % n;
22710
- var deg = (x) => mod(x, 360);
22711
- function hexToRgb(hex) {
22712
- const h = hex.replace(/^#/, "");
22713
- const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
22714
- if (m.length !== 6) throw new Error("Bad hex");
22715
- const int = parseInt(m, 16);
22716
- return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
22717
- }
22718
- function rgbToHex(r2, g, b) {
22719
- const to = (n) => Math.round(n).toString(16).padStart(2, "0");
22720
- return `#${to(r2)}${to(g)}${to(b)}`;
22721
- }
22722
- function srgbToLinear(u) {
22723
- const x = u / 255;
22724
- return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
22725
- }
22726
- function linearToSrgb(x) {
22727
- const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
22728
- return clamp01(y) * 255;
22729
- }
22730
- function rgbToHsl(r2, g, b) {
22731
- const R = r2 / 255, G = g / 255, B = b / 255;
22732
- const max = Math.max(R, G, B), min = Math.min(R, G, B);
22733
- const d = max - min;
22734
- let h = 0;
22735
- if (d !== 0) {
22736
- switch (max) {
22737
- case R:
22738
- h = (G - B) / d + (G < B ? 6 : 0);
22739
- break;
22740
- case G:
22741
- h = (B - R) / d + 2;
22742
- break;
22743
- case B:
22744
- h = (R - G) / d + 4;
22745
- break;
22746
- }
22747
- h *= 60;
22748
- }
22749
- const l = (max + min) / 2;
22750
- const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
22751
- return { h, s, l };
22752
- }
22753
- function srgbToOklab(r2, g, b) {
22754
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
22755
- const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
22756
- const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
22757
- const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
22758
- const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
22759
- const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
22760
- const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
22761
- const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
22762
- return { L, a, b: b2 };
22763
- }
22764
- function oklabToSrgb(L, a, b) {
22765
- const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
22766
- const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
22767
- const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
22768
- const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
22769
- const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
22770
- const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
22771
- return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
22772
- }
22773
- function oklabToOklch(L, a, b) {
22774
- const C = Math.sqrt(a * a + b * b);
22775
- const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
22776
- return { L, C, h };
22777
- }
22778
- function oklchToOklab(L, C, h) {
22779
- const hr = h * Math.PI / 180;
22780
- const a = C * Math.cos(hr);
22781
- const b = C * Math.sin(hr);
22782
- return { L, a, b };
22783
- }
22784
- function inSRGB(r2, g, b) {
22785
- return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
22786
- }
22787
- function oklchToHexGamut(L, C, h) {
22788
- let lo = 0, hi = C, best = 0;
22789
- for (let i = 0; i < 18; i++) {
22790
- const mid = (lo + hi) / 2;
22791
- const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
22792
- const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
22793
- if (inSRGB(r3, g2, bb2)) {
22794
- best = mid;
22795
- lo = mid;
22796
- } else {
22797
- hi = mid;
22798
- }
22799
- }
22800
- const { a, b } = oklchToOklab(L, best, h);
22801
- const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
22802
- return rgbToHex(r2, g, bb);
22803
- }
22804
- function featuresFromHex(hex) {
22805
- const { r: r2, g, b } = hexToRgb(hex);
22806
- const { h, s, l } = rgbToHsl(r2, g, b);
22807
- const { L, a, b: b2 } = srgbToOklab(r2, g, b);
22808
- const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
22809
- const max = Math.max(r2, g, b);
22810
- const v = max / 255;
22811
- const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
22812
- const chroma = s;
22813
- return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
22814
- }
22815
-
22816
- // ../blocks/src/system/transforms/registry/layout.ts
22817
23166
  var joinClasses4 = (parts) => parts.filter(
22818
23167
  (part) => typeof part === "string" && part.trim().length > 0
22819
23168
  ).join(" ").replace(/\s+/g, " ").trim();
@@ -27762,51 +28111,6 @@ function resolveEventCta(event, buttonText) {
27762
28111
  return { label, href: event.path, hidden: false };
27763
28112
  }
27764
28113
 
27765
- // ../theme-core/src/palette/utils/contrast.ts
27766
- function relativeLuminance(r2, g, b) {
27767
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
27768
- return 0.2126 * R + 0.7152 * G + 0.0722 * B;
27769
- }
27770
-
27771
- // ../theme-core/src/palette/utils/textColor.ts
27772
- function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
27773
- const { r: r2, g, b } = parseColorToRgb(background);
27774
- const luminance = relativeLuminance(r2, g, b);
27775
- const blackContrast = (luminance + 0.05) / 0.05;
27776
- const whiteContrast = 1.05 / (luminance + 0.05);
27777
- if (blackContrast >= minContrast && whiteContrast < minContrast) {
27778
- return "#000000";
27779
- }
27780
- if (whiteContrast >= minContrast && blackContrast < minContrast) {
27781
- return "#FFFFFF";
27782
- }
27783
- return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
27784
- }
27785
- function getTextColorForBackground(background) {
27786
- return pickBlackOrWhiteTextColor(background);
27787
- }
27788
- function parseColorToRgb(input) {
27789
- const trimmed = input.trim();
27790
- if (trimmed.startsWith("#")) {
27791
- return hexToRgb(trimmed);
27792
- }
27793
- const rgbMatch = trimmed.match(
27794
- /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
27795
- );
27796
- if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
27797
- return {
27798
- r: clamp255(Number(rgbMatch[1])),
27799
- g: clamp255(Number(rgbMatch[2])),
27800
- b: clamp255(Number(rgbMatch[3]))
27801
- };
27802
- }
27803
- throw new Error("Unsupported color format");
27804
- }
27805
- function clamp255(value) {
27806
- if (Number.isNaN(value)) return 0;
27807
- return Math.max(0, Math.min(255, value));
27808
- }
27809
-
27810
28114
  // ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
27811
28115
  function r(e) {
27812
28116
  var t, f, n = "";
@@ -29733,7 +30037,12 @@ var eventListingBlockDefinition = {
29733
30037
  detailLevel: "listing",
29734
30038
  kind: { $bind: { from: "content.kind" } },
29735
30039
  eventSurface: { $bind: { from: "content.eventSurface" } },
29736
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
30040
+ eventPresets: {
30041
+ $bind: {
30042
+ from: "content.filterEventPresets",
30043
+ transforms: [{ id: "value.csv" }]
30044
+ }
30045
+ },
29737
30046
  scheduleScope: { $bind: { from: "content.scheduleScope" } }
29738
30047
  },
29739
30048
  mode: "server"
@@ -30518,7 +30827,12 @@ var eventCalendarBlockDefinition = {
30518
30827
  // Pass filter params if configured
30519
30828
  kind: { $bind: { from: "content.kind" } },
30520
30829
  eventSurface: { $bind: { from: "content.eventSurface" } },
30521
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
30830
+ eventPresets: {
30831
+ $bind: {
30832
+ from: "content.filterEventPresets",
30833
+ transforms: [{ id: "value.csv" }]
30834
+ }
30835
+ },
30522
30836
  scheduleScope: { $bind: { from: "content.scheduleScope" } },
30523
30837
  categoryIds: { $bind: { from: "content.filterCategoryIds" } },
30524
30838
  staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
@@ -40936,119 +41250,6 @@ function makeDefaultBlockComponent(args) {
40936
41250
  };
40937
41251
  }
40938
41252
 
40939
- // ../theme-core/src/palette/generateShades.ts
40940
- function generateShades(hexColor, name) {
40941
- const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
40942
- const base = featuresFromHex(hexColor);
40943
- const hue = base.okH;
40944
- const baseChroma = base.okC;
40945
- const toneMap = {
40946
- 50: 0.975,
40947
- 100: 0.945,
40948
- 200: 0.89,
40949
- 300: 0.82,
40950
- 400: 0.74,
40951
- 500: 0.66,
40952
- 600: 0.58,
40953
- 700: 0.49,
40954
- 800: 0.4,
40955
- 900: 0.28,
40956
- 950: 0.16
40957
- };
40958
- const shadeDefs = shadeSteps.map((step, idx) => {
40959
- const t = idx / (shadeSteps.length - 1);
40960
- const L = toneMap[step];
40961
- const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
40962
- const C = baseChroma * chromaFactor;
40963
- return {
40964
- name: `${name}-${step}`,
40965
- hex: oklchToHexGamut(L, C, hue)
40966
- };
40967
- });
40968
- shadeDefs.push({ name, hex: hexColor });
40969
- return shadeDefs;
40970
- }
40971
-
40972
- // ../theme-core/src/palette/neutralScale.ts
40973
- function generateNeutralScale({
40974
- background,
40975
- steps = 11,
40976
- warm = false
40977
- }) {
40978
- const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
40979
- const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
40980
- const count = Math.min(steps, shadeNames.length);
40981
- const scale = [];
40982
- for (let i = 0; i < count; i++) {
40983
- const t = i / (count - 1);
40984
- const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
40985
- const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
40986
- const name = `neutral-${shadeNames[i]}`;
40987
- scale.push({ name, hex });
40988
- }
40989
- return scale;
40990
- }
40991
- function mix(a, b, t) {
40992
- return a + (b - a) * Math.max(0, Math.min(1, t));
40993
- }
40994
-
40995
- // ../theme-core/src/palette/expandPalette.ts
40996
- function colorsToMap(palette) {
40997
- const map = {};
40998
- for (const c of palette.colors) {
40999
- map[c.name] = c.hex;
41000
- }
41001
- return map;
41002
- }
41003
- function isBackgroundDark(hex) {
41004
- try {
41005
- return featuresFromHex(hex).Y < 0.5;
41006
- } catch {
41007
- return false;
41008
- }
41009
- }
41010
- function expandPalette(palette) {
41011
- const base = colorsToMap(palette);
41012
- const expanded = { ...base };
41013
- const background = base.background || base.surface || "#ffffff";
41014
- const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
41015
- neutral2.forEach((n) => {
41016
- expanded[n.name] = n.hex;
41017
- });
41018
- for (const [name, hex] of Object.entries(base)) {
41019
- if (hex) {
41020
- const shades = generateShades(hex, name);
41021
- shades.forEach((shade) => {
41022
- expanded[shade.name] = shade.hex;
41023
- });
41024
- }
41025
- }
41026
- if (base.text) expanded.body = base.text;
41027
- if (base.danger && !base.destructive) {
41028
- expanded.destructive = base.danger;
41029
- }
41030
- const isDark = base.background ? isBackgroundDark(base.background) : false;
41031
- const isDarkMode = palette.meta?.mode === "dark" || isDark;
41032
- expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
41033
- const onRoles = [
41034
- { role: "primary", on: "onPrimary" },
41035
- { role: "secondary", on: "onSecondary" },
41036
- { role: "accent", on: "onAccent" },
41037
- { role: "success", on: "onSuccess" },
41038
- { role: "warning", on: "onWarning" },
41039
- { role: "destructive", on: "onDestructive" },
41040
- { role: "info", on: "onInfo" },
41041
- { role: "surface", on: "onSurface" }
41042
- ];
41043
- for (const { role, on } of onRoles) {
41044
- const bg = base[role];
41045
- if (!bg) continue;
41046
- if (expanded[on]) continue;
41047
- expanded[on] = getTextColorForBackground(bg);
41048
- }
41049
- return expanded;
41050
- }
41051
-
41052
41253
  // ../theme-core/src/runtime/fontFamily.ts
41053
41254
  var GENERIC_CSS_FAMILIES = [
41054
41255
  "serif",
@@ -56439,7 +56640,7 @@ var SimpleCache = class {
56439
56640
  };
56440
56641
 
56441
56642
  // src/version.ts
56442
- var SDK_VERSION = "0.64.0";
56643
+ var SDK_VERSION = "0.67.0";
56443
56644
 
56444
56645
  // src/client/error.ts
56445
56646
  var RiverbankApiError = class _RiverbankApiError extends Error {