@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
@@ -1995,6 +1995,144 @@ function resolveVariantKey(manifest, content) {
1995
1995
  return null;
1996
1996
  }
1997
1997
 
1998
+ // ../theme-core/src/palette/utils/colorConversion.ts
1999
+ var clamp01 = (x) => Math.max(0, Math.min(1, x));
2000
+ var mod = (a, n) => (a % n + n) % n;
2001
+ var deg = (x) => mod(x, 360);
2002
+ function hexToRgb(hex) {
2003
+ const h = hex.replace(/^#/, "");
2004
+ const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
2005
+ if (m.length !== 6) throw new Error("Bad hex");
2006
+ const int = parseInt(m, 16);
2007
+ return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
2008
+ }
2009
+ function rgbToHex(r2, g, b) {
2010
+ const to = (n) => Math.round(n).toString(16).padStart(2, "0");
2011
+ return `#${to(r2)}${to(g)}${to(b)}`;
2012
+ }
2013
+ function srgbToLinear(u) {
2014
+ const x = u / 255;
2015
+ return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
2016
+ }
2017
+ function linearToSrgb(x) {
2018
+ const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
2019
+ return clamp01(y) * 255;
2020
+ }
2021
+ function rgbToHsl(r2, g, b) {
2022
+ const R = r2 / 255, G = g / 255, B = b / 255;
2023
+ const max = Math.max(R, G, B), min = Math.min(R, G, B);
2024
+ const d = max - min;
2025
+ let h = 0;
2026
+ if (d !== 0) {
2027
+ switch (max) {
2028
+ case R:
2029
+ h = (G - B) / d + (G < B ? 6 : 0);
2030
+ break;
2031
+ case G:
2032
+ h = (B - R) / d + 2;
2033
+ break;
2034
+ case B:
2035
+ h = (R - G) / d + 4;
2036
+ break;
2037
+ }
2038
+ h *= 60;
2039
+ }
2040
+ const l = (max + min) / 2;
2041
+ const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
2042
+ return { h, s, l };
2043
+ }
2044
+ function srgbToOklab(r2, g, b) {
2045
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
2046
+ const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
2047
+ const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
2048
+ const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
2049
+ const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
2050
+ const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
2051
+ const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
2052
+ const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
2053
+ return { L, a, b: b2 };
2054
+ }
2055
+ function oklabToSrgb(L, a, b) {
2056
+ const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
2057
+ const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
2058
+ const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
2059
+ const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
2060
+ const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
2061
+ const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
2062
+ return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
2063
+ }
2064
+ function oklabToOklch(L, a, b) {
2065
+ const C = Math.sqrt(a * a + b * b);
2066
+ const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
2067
+ return { L, C, h };
2068
+ }
2069
+ function oklchToOklab(L, C, h) {
2070
+ const hr = h * Math.PI / 180;
2071
+ const a = C * Math.cos(hr);
2072
+ const b = C * Math.sin(hr);
2073
+ return { L, a, b };
2074
+ }
2075
+ function inSRGB(r2, g, b) {
2076
+ return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
2077
+ }
2078
+ function oklchToHexGamut(L, C, h) {
2079
+ let lo = 0, hi = C, best = 0;
2080
+ for (let i = 0; i < 18; i++) {
2081
+ const mid = (lo + hi) / 2;
2082
+ const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
2083
+ const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
2084
+ if (inSRGB(r3, g2, bb2)) {
2085
+ best = mid;
2086
+ lo = mid;
2087
+ } else {
2088
+ hi = mid;
2089
+ }
2090
+ }
2091
+ const { a, b } = oklchToOklab(L, best, h);
2092
+ const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
2093
+ return rgbToHex(r2, g, bb);
2094
+ }
2095
+ function featuresFromHex(hex) {
2096
+ const { r: r2, g, b } = hexToRgb(hex);
2097
+ const { h, s, l } = rgbToHsl(r2, g, b);
2098
+ const { L, a, b: b2 } = srgbToOklab(r2, g, b);
2099
+ const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
2100
+ const max = Math.max(r2, g, b);
2101
+ const v = max / 255;
2102
+ const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
2103
+ const chroma = s;
2104
+ return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
2105
+ }
2106
+
2107
+ // ../theme-core/src/palette/utils/contrast.ts
2108
+ function relativeLuminance(r2, g, b) {
2109
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
2110
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
2111
+ }
2112
+
2113
+ // ../theme-core/src/palette/utils/onColor.ts
2114
+ var BACKGROUND_ROLE_NAMES = /* @__PURE__ */ new Set([
2115
+ "primary",
2116
+ "secondary",
2117
+ "accent",
2118
+ "success",
2119
+ "warning",
2120
+ "destructive",
2121
+ "info",
2122
+ "background",
2123
+ "surface",
2124
+ "surfaceAlt",
2125
+ "muted",
2126
+ "neutral"
2127
+ ]);
2128
+ function onColorTokenName(backgroundToken) {
2129
+ return `on${backgroundToken.split("-").filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`;
2130
+ }
2131
+ function isOnColorBackgroundCandidateToken(token) {
2132
+ const role = token.match(/^(.*?)(?:-\d{2,3})?$/)?.[1] ?? token;
2133
+ return BACKGROUND_ROLE_NAMES.has(role);
2134
+ }
2135
+
1998
2136
  // ../theme-core/src/site-styles/appearancePresetResolution.ts
1999
2137
  function assertValidOptionGroups(preset2) {
2000
2138
  preset2.optionGroups?.forEach((group) => {
@@ -7616,6 +7754,9 @@ var curatedSiteStyleIdValues = [
7616
7754
  "site-style:bright-community",
7617
7755
  "site-style:quiet-luxury",
7618
7756
  "site-style:practical-services",
7757
+ "site-style:quiet-practice",
7758
+ "site-style:personal-retreat-journal",
7759
+ "site-style:tactile-workshop",
7619
7760
  "site-style:modern-wellness",
7620
7761
  "site-style:bold-launch",
7621
7762
  "site-style:south-west-twerk-school"
@@ -7698,7 +7839,8 @@ function defineCuratedSiteStyle(input) {
7698
7839
  name: input.name,
7699
7840
  description: input.description,
7700
7841
  generationBrief: input.generationBrief,
7701
- selectionKeywords: input.selectionKeywords ?? [],
7842
+ selectionKeywordRules: input.selectionKeywordRules ?? [],
7843
+ siteCreatorSelection: input.siteCreatorSelection ?? { kind: "explicit_only" },
7702
7844
  template: {
7703
7845
  id: asDesignSystemTemplateId(`template:${input.id.replace("site-style:", "")}`),
7704
7846
  name: input.name,
@@ -7842,12 +7984,13 @@ var curatedSiteStyles = [
7842
7984
  name: "Quiet Luxury",
7843
7985
  description: "Minimal, confident, and refined for premium experiences and private services.",
7844
7986
  generationBrief: "Use fewer claims, more specificity, and restrained sensory detail. Favor elegant media and low repetition over dense panels.",
7845
- selectionKeywords: [
7846
- "luxury",
7847
- "premium",
7848
- "boutique",
7849
- "bespoke",
7850
- "exclusive"
7987
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 20 },
7988
+ selectionKeywordRules: [
7989
+ { kind: "word", value: "luxury" },
7990
+ { kind: "word", value: "premium" },
7991
+ { kind: "word", value: "boutique" },
7992
+ { kind: "word", value: "bespoke" },
7993
+ { kind: "word", value: "exclusive" }
7851
7994
  ],
7852
7995
  tokenRecipes: {
7853
7996
  palette: "high-contrast",
@@ -7876,13 +8019,14 @@ var curatedSiteStyles = [
7876
8019
  name: "Practical Services",
7877
8020
  description: "Efficient, plainspoken, and conversion-focused for trades and everyday services.",
7878
8021
  generationBrief: "Make services, location, trust signals, and contact paths obvious. Keep copy brief and avoid ornate visual treatments.",
7879
- selectionKeywords: [
7880
- "repair",
7881
- "plumb",
7882
- "electric",
7883
- "cleaning",
7884
- "landscap",
7885
- "contractor"
8022
+ siteCreatorSelection: { kind: "primary_goal_support" },
8023
+ selectionKeywordRules: [
8024
+ { kind: "word", value: "repair" },
8025
+ { kind: "substring", value: "plumb" },
8026
+ { kind: "substring", value: "electric" },
8027
+ { kind: "word", value: "cleaning" },
8028
+ { kind: "substring", value: "landscap" },
8029
+ { kind: "substring", value: "contractor" }
7886
8030
  ],
7887
8031
  tokenRecipes: {
7888
8032
  palette: "brand-led",
@@ -7933,18 +8077,134 @@ var curatedSiteStyles = [
7933
8077
  paletteChoice("warm-neutral-forest")
7934
8078
  ]
7935
8079
  }),
8080
+ defineCuratedSiteStyle({
8081
+ id: "site-style:quiet-practice",
8082
+ name: "Quiet Practice",
8083
+ description: "Grounded, calm, and practical for small appointment-first practices.",
8084
+ 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.",
8085
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 30 },
8086
+ selectionKeywordRules: [
8087
+ { kind: "substring", value: "massage" },
8088
+ { kind: "word", value: "bodywork" },
8089
+ { kind: "phrase", value: "appointment practice" },
8090
+ { kind: "phrase", value: "appointment-first" },
8091
+ { kind: "substring", value: "practitioner" },
8092
+ { kind: "substring", value: "therap" },
8093
+ { kind: "substring", value: "clinic" },
8094
+ { kind: "phrase", value: "wellness practice" }
8095
+ ],
8096
+ tokenRecipes: {
8097
+ palette: "soft-natural",
8098
+ contrast: "standard",
8099
+ radius: "soft",
8100
+ shadow: "subtle",
8101
+ typography: "clean-sans",
8102
+ spacing: "regular",
8103
+ motion: "subtle"
8104
+ },
8105
+ compositionBudget: quietBudget,
8106
+ recommendedHeaderLookIds: ["practical-utility", "clean-base", "centered-calm"],
8107
+ buttonPersonalityChoices: [
8108
+ buttonChoice("pebble"),
8109
+ buttonChoice("soft-pill"),
8110
+ buttonChoice("editorial-link")
8111
+ ],
8112
+ paletteVariantChoices: [
8113
+ paletteChoice("soft-natural-stone"),
8114
+ paletteChoice("soft-natural-sage"),
8115
+ paletteChoice("warm-neutral-clay")
8116
+ ]
8117
+ }),
8118
+ defineCuratedSiteStyle({
8119
+ id: "site-style:personal-retreat-journal",
8120
+ name: "Personal Retreat Journal",
8121
+ description: "Warm, story-led, and readable for solo practitioners with mixed offers.",
8122
+ 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.",
8123
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 40 },
8124
+ selectionKeywordRules: [
8125
+ { kind: "substring", value: "retreat" },
8126
+ { kind: "phrase", value: "solo practitioner" },
8127
+ { kind: "phrase", value: "personal brand" },
8128
+ { kind: "substring", value: "teacher" },
8129
+ { kind: "substring", value: "coach" },
8130
+ { kind: "phrase", value: "retreat resources" },
8131
+ { kind: "substring", value: "journal" }
8132
+ ],
8133
+ tokenRecipes: {
8134
+ palette: "warm-neutral",
8135
+ contrast: "standard",
8136
+ radius: "soft",
8137
+ shadow: "subtle",
8138
+ typography: "serif-editorial",
8139
+ spacing: "airy",
8140
+ motion: "subtle"
8141
+ },
8142
+ compositionBudget: balancedBudget,
8143
+ recommendedHeaderLookIds: ["editorial-line", "centered-calm", "minimal-transparent"],
8144
+ buttonPersonalityChoices: [
8145
+ buttonChoice("editorial-link"),
8146
+ buttonChoice("soft-pill"),
8147
+ buttonChoice("brushed-wash")
8148
+ ],
8149
+ paletteVariantChoices: [
8150
+ paletteChoice("warm-neutral-forest"),
8151
+ paletteChoice("warm-neutral-clay"),
8152
+ paletteChoice("soft-natural-stone")
8153
+ ]
8154
+ }),
8155
+ defineCuratedSiteStyle({
8156
+ id: "site-style:tactile-workshop",
8157
+ name: "Tactile Workshop",
8158
+ description: "Bright, hands-on, and image-led for maker studios, workshops, and creative classes.",
8159
+ 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.",
8160
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 50 },
8161
+ selectionKeywordRules: [
8162
+ { kind: "substring", value: "ceramic" },
8163
+ { kind: "word", value: "pottery" },
8164
+ { kind: "phrase", value: "maker studio" },
8165
+ { kind: "phrase", value: "craft class" },
8166
+ { kind: "phrase", value: "craft workshop" },
8167
+ { kind: "word", value: "clay" },
8168
+ { kind: "word", value: "kiln" }
8169
+ ],
8170
+ tokenRecipes: {
8171
+ palette: "brand-led",
8172
+ contrast: "standard",
8173
+ radius: "soft",
8174
+ shadow: "subtle",
8175
+ typography: "friendly-sans",
8176
+ spacing: "regular",
8177
+ motion: "subtle"
8178
+ },
8179
+ compositionBudget: balancedBudget,
8180
+ recommendedHeaderLookIds: ["brand-solid", "practical-utility", "clean-base"],
8181
+ recommendedFooterLookIds: ["site-footer-brand-two-band", "footer-muted-grounding"],
8182
+ buttonPersonalityChoices: [
8183
+ buttonChoice("pebble"),
8184
+ buttonChoice("confident-chip"),
8185
+ buttonChoice("ink-stamp"),
8186
+ buttonChoice("editorial-link")
8187
+ ],
8188
+ paletteVariantChoices: [
8189
+ paletteChoice("brand-led-warm"),
8190
+ paletteChoice("brand-led-cool"),
8191
+ paletteChoice("soft-natural-watercolor"),
8192
+ paletteChoice("warm-neutral-clay")
8193
+ ]
8194
+ }),
7936
8195
  defineCuratedSiteStyle({
7937
8196
  id: "site-style:bold-launch",
7938
8197
  name: "Bold Launch",
7939
8198
  description: "High-energy and punchy for launches, campaigns, and creative offers.",
7940
8199
  generationBrief: "Use crisp positioning, bold hero structure, strong calls to action, and confident visual rhythm. Keep it precise, not shouty.",
7941
- selectionKeywords: [
7942
- "launch",
7943
- "campaign",
7944
- "preorder",
7945
- "pre-order",
7946
- "waitlist",
7947
- "drop"
8200
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 10 },
8201
+ selectionKeywordRules: [
8202
+ { kind: "substring", value: "launch" },
8203
+ { kind: "substring", value: "campaign" },
8204
+ { kind: "word", value: "preorder" },
8205
+ { kind: "phrase", value: "pre-order" },
8206
+ { kind: "substring", value: "waitlist" },
8207
+ { kind: "word", value: "drop" }
7948
8208
  ],
7949
8209
  tokenRecipes: {
7950
8210
  palette: "high-contrast",
@@ -7975,15 +8235,6 @@ var curatedSiteStyles = [
7975
8235
  name: "South West Twerk School",
7976
8236
  description: "Energetic, editorial, and high-contrast for a branded dance school presence.",
7977
8237
  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.",
7978
- selectionKeywords: [
7979
- "dance",
7980
- "classes",
7981
- "workshop",
7982
- "school",
7983
- "movement",
7984
- "performance",
7985
- "community"
7986
- ],
7987
8238
  tokenRecipes: {
7988
8239
  palette: "brand-led",
7989
8240
  contrast: "maximum",
@@ -8226,6 +8477,148 @@ var modernMinimalTheme = {
8226
8477
  }
8227
8478
  };
8228
8479
 
8480
+ // ../theme-core/src/palette/generateShades.ts
8481
+ function generateShades(hexColor, name) {
8482
+ const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
8483
+ const base = featuresFromHex(hexColor);
8484
+ const hue = base.okH;
8485
+ const baseChroma = base.okC;
8486
+ const toneMap = {
8487
+ 50: 0.975,
8488
+ 100: 0.945,
8489
+ 200: 0.89,
8490
+ 300: 0.82,
8491
+ 400: 0.74,
8492
+ 500: 0.66,
8493
+ 600: 0.58,
8494
+ 700: 0.49,
8495
+ 800: 0.4,
8496
+ 900: 0.28,
8497
+ 950: 0.16
8498
+ };
8499
+ const shadeDefs = shadeSteps.map((step, idx) => {
8500
+ const t = idx / (shadeSteps.length - 1);
8501
+ const L = toneMap[step];
8502
+ const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
8503
+ const C = baseChroma * chromaFactor;
8504
+ return {
8505
+ name: `${name}-${step}`,
8506
+ hex: oklchToHexGamut(L, C, hue)
8507
+ };
8508
+ });
8509
+ shadeDefs.push({ name, hex: hexColor });
8510
+ return shadeDefs;
8511
+ }
8512
+
8513
+ // ../theme-core/src/palette/neutralScale.ts
8514
+ function generateNeutralScale({
8515
+ background,
8516
+ steps = 11,
8517
+ warm = false
8518
+ }) {
8519
+ const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
8520
+ const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
8521
+ const count = Math.min(steps, shadeNames.length);
8522
+ const scale = [];
8523
+ for (let i = 0; i < count; i++) {
8524
+ const t = i / (count - 1);
8525
+ const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
8526
+ const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
8527
+ const name = `neutral-${shadeNames[i]}`;
8528
+ scale.push({ name, hex });
8529
+ }
8530
+ return scale;
8531
+ }
8532
+ function mix(a, b, t) {
8533
+ return a + (b - a) * Math.max(0, Math.min(1, t));
8534
+ }
8535
+
8536
+ // ../theme-core/src/palette/utils/textColor.ts
8537
+ function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
8538
+ const { r: r2, g, b } = parseColorToRgb(background);
8539
+ const luminance = relativeLuminance(r2, g, b);
8540
+ const blackContrast = (luminance + 0.05) / 0.05;
8541
+ const whiteContrast = 1.05 / (luminance + 0.05);
8542
+ if (blackContrast >= minContrast && whiteContrast < minContrast) {
8543
+ return "#000000";
8544
+ }
8545
+ if (whiteContrast >= minContrast && blackContrast < minContrast) {
8546
+ return "#FFFFFF";
8547
+ }
8548
+ return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
8549
+ }
8550
+ function getTextColorForBackground(background) {
8551
+ return pickBlackOrWhiteTextColor(background);
8552
+ }
8553
+ function parseColorToRgb(input) {
8554
+ const trimmed = input.trim();
8555
+ if (trimmed.startsWith("#")) {
8556
+ return hexToRgb(trimmed);
8557
+ }
8558
+ const rgbMatch = trimmed.match(
8559
+ /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
8560
+ );
8561
+ if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
8562
+ return {
8563
+ r: clamp255(Number(rgbMatch[1])),
8564
+ g: clamp255(Number(rgbMatch[2])),
8565
+ b: clamp255(Number(rgbMatch[3]))
8566
+ };
8567
+ }
8568
+ throw new Error("Unsupported color format");
8569
+ }
8570
+ function clamp255(value) {
8571
+ if (Number.isNaN(value)) return 0;
8572
+ return Math.max(0, Math.min(255, value));
8573
+ }
8574
+
8575
+ // ../theme-core/src/palette/expandPalette.ts
8576
+ function colorsToMap(palette) {
8577
+ const map = {};
8578
+ for (const c of palette.colors) {
8579
+ map[c.name] = c.hex;
8580
+ }
8581
+ return map;
8582
+ }
8583
+ function isBackgroundDark(hex) {
8584
+ try {
8585
+ return featuresFromHex(hex).Y < 0.5;
8586
+ } catch {
8587
+ return false;
8588
+ }
8589
+ }
8590
+ function expandPalette(palette) {
8591
+ const base = colorsToMap(palette);
8592
+ const expanded = { ...base };
8593
+ const background = base.background || base.surface || "#ffffff";
8594
+ const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
8595
+ neutral2.forEach((n) => {
8596
+ expanded[n.name] = n.hex;
8597
+ });
8598
+ for (const [name, hex] of Object.entries(base)) {
8599
+ if (hex) {
8600
+ const shades = generateShades(hex, name);
8601
+ shades.forEach((shade) => {
8602
+ expanded[shade.name] = shade.hex;
8603
+ });
8604
+ }
8605
+ }
8606
+ if (base.text) expanded.body = base.text;
8607
+ if (base.danger && !base.destructive) {
8608
+ expanded.destructive = base.danger;
8609
+ }
8610
+ const isDark = base.background ? isBackgroundDark(base.background) : false;
8611
+ const isDarkMode = palette.meta?.mode === "dark" || isDark;
8612
+ expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
8613
+ for (const [token, hex] of Object.entries({ ...expanded })) {
8614
+ if (!hex || !isOnColorBackgroundCandidateToken(token)) continue;
8615
+ const onToken = onColorTokenName(token);
8616
+ if (expanded[onToken]) continue;
8617
+ expanded[onToken] = getTextColorForBackground(hex);
8618
+ }
8619
+ return expanded;
8620
+ }
8621
+
8229
8622
  // ../theme-core/src/site-styles/designState.ts
8230
8623
  import { z as z24 } from "zod";
8231
8624
 
@@ -8394,25 +8787,19 @@ var defaultDesignRuntimeRules = defineDesignRuntimeRules({
8394
8787
  "muted-band": {
8395
8788
  background: {
8396
8789
  type: "color",
8397
- color: "muted",
8398
- textColor: "text",
8399
- headingColor: "text"
8790
+ color: "muted"
8400
8791
  }
8401
8792
  },
8402
8793
  "accent-band": {
8403
8794
  background: {
8404
8795
  type: "color",
8405
- color: "primary",
8406
- textColor: "primaryForeground",
8407
- headingColor: "primaryForeground"
8796
+ color: "primary"
8408
8797
  }
8409
8798
  },
8410
8799
  "brand-depth-band": {
8411
8800
  background: {
8412
8801
  type: "color",
8413
- color: "primary-800",
8414
- textColor: "primaryForeground",
8415
- headingColor: "primaryForeground"
8802
+ color: "primary-800"
8416
8803
  }
8417
8804
  },
8418
8805
  "hero-image": {
@@ -14634,6 +15021,16 @@ var jsonArrayTransform = {
14634
15021
  return "";
14635
15022
  }
14636
15023
  };
15024
+ var csvTransform = {
15025
+ id: "value.csv",
15026
+ kind: "formatter",
15027
+ summary: "Normalize a string or array of strings into a comma-separated list",
15028
+ run: (value) => {
15029
+ const rawValues = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
15030
+ const normalized = rawValues.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
15031
+ return normalized.length > 0 ? Array.from(new Set(normalized)).join(",") : "";
15032
+ }
15033
+ };
14637
15034
  var marqueeLoopOptionsSchema = z33.object({
14638
15035
  minItems: z33.number().int().min(1).default(10)
14639
15036
  });
@@ -14659,6 +15056,7 @@ var formattingTransforms = [
14659
15056
  dateFormatShort,
14660
15057
  arrayLengthTransform,
14661
15058
  jsonArrayTransform,
15059
+ csvTransform,
14662
15060
  marqueeLoopTransform
14663
15061
  ];
14664
15062
 
@@ -15142,117 +15540,6 @@ var uiTransforms = [
15142
15540
 
15143
15541
  // ../blocks/src/system/transforms/registry/layout.ts
15144
15542
  import { z as z35 } from "zod";
15145
-
15146
- // ../theme-core/src/palette/utils/colorConversion.ts
15147
- var clamp01 = (x) => Math.max(0, Math.min(1, x));
15148
- var mod = (a, n) => (a % n + n) % n;
15149
- var deg = (x) => mod(x, 360);
15150
- function hexToRgb(hex) {
15151
- const h = hex.replace(/^#/, "");
15152
- const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
15153
- if (m.length !== 6) throw new Error("Bad hex");
15154
- const int = parseInt(m, 16);
15155
- return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
15156
- }
15157
- function rgbToHex(r2, g, b) {
15158
- const to = (n) => Math.round(n).toString(16).padStart(2, "0");
15159
- return `#${to(r2)}${to(g)}${to(b)}`;
15160
- }
15161
- function srgbToLinear(u) {
15162
- const x = u / 255;
15163
- return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
15164
- }
15165
- function linearToSrgb(x) {
15166
- const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
15167
- return clamp01(y) * 255;
15168
- }
15169
- function rgbToHsl(r2, g, b) {
15170
- const R = r2 / 255, G = g / 255, B = b / 255;
15171
- const max = Math.max(R, G, B), min = Math.min(R, G, B);
15172
- const d = max - min;
15173
- let h = 0;
15174
- if (d !== 0) {
15175
- switch (max) {
15176
- case R:
15177
- h = (G - B) / d + (G < B ? 6 : 0);
15178
- break;
15179
- case G:
15180
- h = (B - R) / d + 2;
15181
- break;
15182
- case B:
15183
- h = (R - G) / d + 4;
15184
- break;
15185
- }
15186
- h *= 60;
15187
- }
15188
- const l = (max + min) / 2;
15189
- const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
15190
- return { h, s, l };
15191
- }
15192
- function srgbToOklab(r2, g, b) {
15193
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
15194
- const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
15195
- const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
15196
- const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
15197
- const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
15198
- const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
15199
- const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
15200
- const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
15201
- return { L, a, b: b2 };
15202
- }
15203
- function oklabToSrgb(L, a, b) {
15204
- const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
15205
- const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
15206
- const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
15207
- const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
15208
- const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
15209
- const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
15210
- return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
15211
- }
15212
- function oklabToOklch(L, a, b) {
15213
- const C = Math.sqrt(a * a + b * b);
15214
- const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
15215
- return { L, C, h };
15216
- }
15217
- function oklchToOklab(L, C, h) {
15218
- const hr = h * Math.PI / 180;
15219
- const a = C * Math.cos(hr);
15220
- const b = C * Math.sin(hr);
15221
- return { L, a, b };
15222
- }
15223
- function inSRGB(r2, g, b) {
15224
- return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
15225
- }
15226
- function oklchToHexGamut(L, C, h) {
15227
- let lo = 0, hi = C, best = 0;
15228
- for (let i = 0; i < 18; i++) {
15229
- const mid = (lo + hi) / 2;
15230
- const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
15231
- const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
15232
- if (inSRGB(r3, g2, bb2)) {
15233
- best = mid;
15234
- lo = mid;
15235
- } else {
15236
- hi = mid;
15237
- }
15238
- }
15239
- const { a, b } = oklchToOklab(L, best, h);
15240
- const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
15241
- return rgbToHex(r2, g, bb);
15242
- }
15243
- function featuresFromHex(hex) {
15244
- const { r: r2, g, b } = hexToRgb(hex);
15245
- const { h, s, l } = rgbToHsl(r2, g, b);
15246
- const { L, a, b: b2 } = srgbToOklab(r2, g, b);
15247
- const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
15248
- const max = Math.max(r2, g, b);
15249
- const v = max / 255;
15250
- const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
15251
- const chroma = s;
15252
- return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
15253
- }
15254
-
15255
- // ../blocks/src/system/transforms/registry/layout.ts
15256
15543
  var joinClasses4 = (parts) => parts.filter(
15257
15544
  (part) => typeof part === "string" && part.trim().length > 0
15258
15545
  ).join(" ").replace(/\s+/g, " ").trim();
@@ -20201,51 +20488,6 @@ function resolveEventCta(event, buttonText) {
20201
20488
  return { label, href: event.path, hidden: false };
20202
20489
  }
20203
20490
 
20204
- // ../theme-core/src/palette/utils/contrast.ts
20205
- function relativeLuminance(r2, g, b) {
20206
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
20207
- return 0.2126 * R + 0.7152 * G + 0.0722 * B;
20208
- }
20209
-
20210
- // ../theme-core/src/palette/utils/textColor.ts
20211
- function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
20212
- const { r: r2, g, b } = parseColorToRgb(background);
20213
- const luminance = relativeLuminance(r2, g, b);
20214
- const blackContrast = (luminance + 0.05) / 0.05;
20215
- const whiteContrast = 1.05 / (luminance + 0.05);
20216
- if (blackContrast >= minContrast && whiteContrast < minContrast) {
20217
- return "#000000";
20218
- }
20219
- if (whiteContrast >= minContrast && blackContrast < minContrast) {
20220
- return "#FFFFFF";
20221
- }
20222
- return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
20223
- }
20224
- function getTextColorForBackground(background) {
20225
- return pickBlackOrWhiteTextColor(background);
20226
- }
20227
- function parseColorToRgb(input) {
20228
- const trimmed = input.trim();
20229
- if (trimmed.startsWith("#")) {
20230
- return hexToRgb(trimmed);
20231
- }
20232
- const rgbMatch = trimmed.match(
20233
- /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
20234
- );
20235
- if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
20236
- return {
20237
- r: clamp255(Number(rgbMatch[1])),
20238
- g: clamp255(Number(rgbMatch[2])),
20239
- b: clamp255(Number(rgbMatch[3]))
20240
- };
20241
- }
20242
- throw new Error("Unsupported color format");
20243
- }
20244
- function clamp255(value) {
20245
- if (Number.isNaN(value)) return 0;
20246
- return Math.max(0, Math.min(255, value));
20247
- }
20248
-
20249
20491
  // ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
20250
20492
  function r(e) {
20251
20493
  var t, f, n = "";
@@ -22175,7 +22417,12 @@ var eventListingBlockDefinition = {
22175
22417
  detailLevel: "listing",
22176
22418
  kind: { $bind: { from: "content.kind" } },
22177
22419
  eventSurface: { $bind: { from: "content.eventSurface" } },
22178
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
22420
+ eventPresets: {
22421
+ $bind: {
22422
+ from: "content.filterEventPresets",
22423
+ transforms: [{ id: "value.csv" }]
22424
+ }
22425
+ },
22179
22426
  scheduleScope: { $bind: { from: "content.scheduleScope" } }
22180
22427
  },
22181
22428
  mode: "server"
@@ -22960,7 +23207,12 @@ var eventCalendarBlockDefinition = {
22960
23207
  // Pass filter params if configured
22961
23208
  kind: { $bind: { from: "content.kind" } },
22962
23209
  eventSurface: { $bind: { from: "content.eventSurface" } },
22963
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
23210
+ eventPresets: {
23211
+ $bind: {
23212
+ from: "content.filterEventPresets",
23213
+ transforms: [{ id: "value.csv" }]
23214
+ }
23215
+ },
22964
23216
  scheduleScope: { $bind: { from: "content.scheduleScope" } },
22965
23217
  categoryIds: { $bind: { from: "content.filterCategoryIds" } },
22966
23218
  staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
@@ -33422,119 +33674,6 @@ function renderBlock(manifest, content, options = {}) {
33422
33674
  );
33423
33675
  }
33424
33676
 
33425
- // ../theme-core/src/palette/generateShades.ts
33426
- function generateShades(hexColor, name) {
33427
- const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
33428
- const base = featuresFromHex(hexColor);
33429
- const hue = base.okH;
33430
- const baseChroma = base.okC;
33431
- const toneMap = {
33432
- 50: 0.975,
33433
- 100: 0.945,
33434
- 200: 0.89,
33435
- 300: 0.82,
33436
- 400: 0.74,
33437
- 500: 0.66,
33438
- 600: 0.58,
33439
- 700: 0.49,
33440
- 800: 0.4,
33441
- 900: 0.28,
33442
- 950: 0.16
33443
- };
33444
- const shadeDefs = shadeSteps.map((step, idx) => {
33445
- const t = idx / (shadeSteps.length - 1);
33446
- const L = toneMap[step];
33447
- const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
33448
- const C = baseChroma * chromaFactor;
33449
- return {
33450
- name: `${name}-${step}`,
33451
- hex: oklchToHexGamut(L, C, hue)
33452
- };
33453
- });
33454
- shadeDefs.push({ name, hex: hexColor });
33455
- return shadeDefs;
33456
- }
33457
-
33458
- // ../theme-core/src/palette/neutralScale.ts
33459
- function generateNeutralScale({
33460
- background,
33461
- steps = 11,
33462
- warm = false
33463
- }) {
33464
- const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
33465
- const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
33466
- const count = Math.min(steps, shadeNames.length);
33467
- const scale = [];
33468
- for (let i = 0; i < count; i++) {
33469
- const t = i / (count - 1);
33470
- const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
33471
- const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
33472
- const name = `neutral-${shadeNames[i]}`;
33473
- scale.push({ name, hex });
33474
- }
33475
- return scale;
33476
- }
33477
- function mix(a, b, t) {
33478
- return a + (b - a) * Math.max(0, Math.min(1, t));
33479
- }
33480
-
33481
- // ../theme-core/src/palette/expandPalette.ts
33482
- function colorsToMap(palette) {
33483
- const map = {};
33484
- for (const c of palette.colors) {
33485
- map[c.name] = c.hex;
33486
- }
33487
- return map;
33488
- }
33489
- function isBackgroundDark(hex) {
33490
- try {
33491
- return featuresFromHex(hex).Y < 0.5;
33492
- } catch {
33493
- return false;
33494
- }
33495
- }
33496
- function expandPalette(palette) {
33497
- const base = colorsToMap(palette);
33498
- const expanded = { ...base };
33499
- const background = base.background || base.surface || "#ffffff";
33500
- const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
33501
- neutral2.forEach((n) => {
33502
- expanded[n.name] = n.hex;
33503
- });
33504
- for (const [name, hex] of Object.entries(base)) {
33505
- if (hex) {
33506
- const shades = generateShades(hex, name);
33507
- shades.forEach((shade) => {
33508
- expanded[shade.name] = shade.hex;
33509
- });
33510
- }
33511
- }
33512
- if (base.text) expanded.body = base.text;
33513
- if (base.danger && !base.destructive) {
33514
- expanded.destructive = base.danger;
33515
- }
33516
- const isDark = base.background ? isBackgroundDark(base.background) : false;
33517
- const isDarkMode = palette.meta?.mode === "dark" || isDark;
33518
- expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
33519
- const onRoles = [
33520
- { role: "primary", on: "onPrimary" },
33521
- { role: "secondary", on: "onSecondary" },
33522
- { role: "accent", on: "onAccent" },
33523
- { role: "success", on: "onSuccess" },
33524
- { role: "warning", on: "onWarning" },
33525
- { role: "destructive", on: "onDestructive" },
33526
- { role: "info", on: "onInfo" },
33527
- { role: "surface", on: "onSurface" }
33528
- ];
33529
- for (const { role, on } of onRoles) {
33530
- const bg = base[role];
33531
- if (!bg) continue;
33532
- if (expanded[on]) continue;
33533
- expanded[on] = getTextColorForBackground(bg);
33534
- }
33535
- return expanded;
33536
- }
33537
-
33538
33677
  // ../theme-core/src/runtime/fontFamily.ts
33539
33678
  var GENERIC_CSS_FAMILIES = [
33540
33679
  "serif",
@@ -48682,6 +48821,17 @@ var SUPPORTED_LOADER_ENDPOINTS = [
48682
48821
  // ../blocks/src/primitives/content/primitives.tsx
48683
48822
  var RichText2 = RichText;
48684
48823
 
48824
+ // ../api/src/apiEndpointTypes.ts
48825
+ function blockedDemoMutationPolicy(classification, publicMessage) {
48826
+ if (publicMessage.trim() === "") {
48827
+ throw new Error(`Demo mutation policy ${classification} requires publicMessage.`);
48828
+ }
48829
+ return {
48830
+ classification,
48831
+ publicMessage
48832
+ };
48833
+ }
48834
+
48685
48835
  // ../api/src/cache-tags.ts
48686
48836
  var TAG_TEMPLATES = {
48687
48837
  siteCollection: "riverbank:site",
@@ -48712,6 +48862,18 @@ var TAG_TEMPLATES = {
48712
48862
  };
48713
48863
 
48714
48864
  // ../api/src/endpoints.ts
48865
+ var DEMO_MUTATION_BLOCKED_HIDDEN = blockedDemoMutationPolicy(
48866
+ "blocked-hidden",
48867
+ "This action is not available in demo sites."
48868
+ );
48869
+ var DEMO_MUTATION_BLOCKED_DISABLED = blockedDemoMutationPolicy(
48870
+ "blocked-disabled",
48871
+ "This setting is disabled in demo sites."
48872
+ );
48873
+ var DEMO_MUTATION_INTERNAL_ONLY = blockedDemoMutationPolicy(
48874
+ "internal-only",
48875
+ "This internal operation is not available in demo sites."
48876
+ );
48715
48877
  var ENDPOINT_DEFINITIONS = {
48716
48878
  // AI endpoints - no cache due to dynamic nature
48717
48879
  aiContentUpdateChat: {
@@ -48828,7 +48990,8 @@ var ENDPOINT_DEFINITIONS = {
48828
48990
  path: "/sites/{siteId}/ai/generate",
48829
48991
  method: "POST",
48830
48992
  auth: "user",
48831
- responseKind: "json"
48993
+ responseKind: "json",
48994
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
48832
48995
  },
48833
48996
  getOnboardingPreviewStatus: {
48834
48997
  path: "/public/sites/{siteId}/onboarding/preview-status",
@@ -48849,7 +49012,8 @@ var ENDPOINT_DEFINITIONS = {
48849
49012
  method: "POST",
48850
49013
  auth: "user",
48851
49014
  errors: [],
48852
- responseKind: "json"
49015
+ responseKind: "json",
49016
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED
48853
49017
  },
48854
49018
  goLiveSite: {
48855
49019
  path: "/sites/{siteId}/launch/go-live",
@@ -48918,20 +49082,23 @@ var ENDPOINT_DEFINITIONS = {
48918
49082
  path: "/sites/{siteId}/ai/site-wizard/goals",
48919
49083
  method: "POST",
48920
49084
  auth: "user",
48921
- responseKind: "json"
49085
+ responseKind: "json",
49086
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
48922
49087
  },
48923
49088
  aiSiteWizardIntakeTriage: {
48924
49089
  path: "/sites/{siteId}/ai/site-wizard/intake-triage",
48925
49090
  method: "POST",
48926
49091
  auth: "user",
48927
- responseKind: "json"
49092
+ responseKind: "json",
49093
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
48928
49094
  },
48929
49095
  aiSiteWizardTelemetry: {
48930
49096
  path: "/sites/{siteId}/ai/site-wizard/telemetry",
48931
49097
  method: "POST",
48932
49098
  auth: "user",
48933
49099
  errors: [],
48934
- responseKind: "json"
49100
+ responseKind: "json",
49101
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
48935
49102
  },
48936
49103
  // Admin SEO
48937
49104
  listGscPropertiesAdmin: {
@@ -49138,7 +49305,7 @@ var ENDPOINT_DEFINITIONS = {
49138
49305
  responseKind: "json",
49139
49306
  errors: ["resource:not_found", "server:internal_error"]
49140
49307
  },
49141
- // Ops (event hosts/admins)
49308
+ // Ops (staff event operators/admins)
49142
49309
  opsListUpcomingEventOccurrences: {
49143
49310
  path: "/ops/sites/{siteId}/events",
49144
49311
  method: "GET",
@@ -49156,6 +49323,7 @@ var ENDPOINT_DEFINITIONS = {
49156
49323
  method: "POST",
49157
49324
  auth: "user",
49158
49325
  responseKind: "json",
49326
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49159
49327
  errors: [
49160
49328
  "validation:invalid_input",
49161
49329
  "auth:forbidden",
@@ -49168,6 +49336,7 @@ var ENDPOINT_DEFINITIONS = {
49168
49336
  method: "POST",
49169
49337
  auth: "user",
49170
49338
  responseKind: "json",
49339
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49171
49340
  errors: [
49172
49341
  "validation:invalid_input",
49173
49342
  "auth:forbidden",
@@ -49186,6 +49355,7 @@ var ENDPOINT_DEFINITIONS = {
49186
49355
  method: "POST",
49187
49356
  auth: "user",
49188
49357
  responseKind: "json",
49358
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49189
49359
  errors: [
49190
49360
  "validation:invalid_input",
49191
49361
  "auth:forbidden",
@@ -49219,6 +49389,7 @@ var ENDPOINT_DEFINITIONS = {
49219
49389
  method: "POST",
49220
49390
  auth: "user",
49221
49391
  responseKind: "json",
49392
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49222
49393
  errors: [
49223
49394
  "validation:invalid_input",
49224
49395
  "auth:forbidden",
@@ -49247,7 +49418,8 @@ var ENDPOINT_DEFINITIONS = {
49247
49418
  method: "POST",
49248
49419
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings],
49249
49420
  auth: "user",
49250
- responseKind: "json"
49421
+ responseKind: "json",
49422
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49251
49423
  },
49252
49424
  previewEmailTemplate: {
49253
49425
  path: "/sites/{siteId}/settings/emails/preview",
@@ -49298,14 +49470,16 @@ var ENDPOINT_DEFINITIONS = {
49298
49470
  method: "POST",
49299
49471
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49300
49472
  auth: "user",
49301
- responseKind: "json"
49473
+ responseKind: "json",
49474
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49302
49475
  },
49303
49476
  createNewsletterSubscribersImportUploadUrl: {
49304
49477
  path: "/sites/{siteId}/newsletter/subscribers/import-url",
49305
49478
  method: "POST",
49306
49479
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49307
49480
  auth: "user",
49308
- responseKind: "json"
49481
+ responseKind: "json",
49482
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49309
49483
  },
49310
49484
  exportNewsletterSubscribersCsv: {
49311
49485
  path: "/sites/{siteId}/newsletter/subscribers/export.csv",
@@ -49502,14 +49676,16 @@ var ENDPOINT_DEFINITIONS = {
49502
49676
  method: "POST",
49503
49677
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49504
49678
  auth: "user",
49505
- responseKind: "json"
49679
+ responseKind: "json",
49680
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49506
49681
  },
49507
49682
  testSendNewsletterCampaign: {
49508
49683
  path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/test-send",
49509
49684
  method: "POST",
49510
49685
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49511
49686
  auth: "user",
49512
- responseKind: "json"
49687
+ responseKind: "json",
49688
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49513
49689
  },
49514
49690
  listNewsletterSendJobs: {
49515
49691
  path: "/sites/{siteId}/newsletter/jobs",
@@ -50197,7 +50373,8 @@ var ENDPOINT_DEFINITIONS = {
50197
50373
  method: "DELETE",
50198
50374
  tags: ["site", "site-{siteId}"],
50199
50375
  auth: "user",
50200
- responseKind: "json"
50376
+ responseKind: "json",
50377
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
50201
50378
  },
50202
50379
  listSiteMembers: {
50203
50380
  path: "/sites/{siteId}/members",
@@ -50653,7 +50830,8 @@ var ENDPOINT_DEFINITIONS = {
50653
50830
  method: "POST",
50654
50831
  tags: ["site-{siteId}", "content-{siteId}-{type}"],
50655
50832
  auth: "user",
50656
- responseKind: "json"
50833
+ responseKind: "json",
50834
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
50657
50835
  },
50658
50836
  updateSiteGeneralSettings: {
50659
50837
  path: "/sites/{siteId}/settings/general",
@@ -52892,6 +53070,7 @@ var ENDPOINT_DEFINITIONS = {
52892
53070
  method: "POST",
52893
53071
  tags: ["site-{siteId}"],
52894
53072
  auth: "user",
53073
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
52895
53074
  errors: [
52896
53075
  "validation:invalid_input",
52897
53076
  "auth:forbidden",
@@ -52906,6 +53085,7 @@ var ENDPOINT_DEFINITIONS = {
52906
53085
  method: "POST",
52907
53086
  tags: ["site-{siteId}"],
52908
53087
  auth: "user",
53088
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
52909
53089
  errors: [
52910
53090
  "validation:invalid_input",
52911
53091
  "auth:forbidden",
@@ -53215,6 +53395,7 @@ var ENDPOINT_DEFINITIONS = {
53215
53395
  tags: ["site-{siteId}", "passes-{siteId}"],
53216
53396
  auth: "user",
53217
53397
  responseKind: "json",
53398
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53218
53399
  errors: ["validation:invalid_input", "server:internal_error"]
53219
53400
  },
53220
53401
  getBookingPass: {
@@ -53230,6 +53411,7 @@ var ENDPOINT_DEFINITIONS = {
53230
53411
  tags: ["site-{siteId}", "passes-{siteId}"],
53231
53412
  auth: "user",
53232
53413
  responseKind: "json",
53414
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53233
53415
  errors: [
53234
53416
  "validation:invalid_input",
53235
53417
  "resource:not_found",
@@ -53242,6 +53424,7 @@ var ENDPOINT_DEFINITIONS = {
53242
53424
  tags: ["site-{siteId}", "passes-{siteId}"],
53243
53425
  auth: "user",
53244
53426
  responseKind: "json",
53427
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53245
53428
  errors: [
53246
53429
  "validation:invalid_input",
53247
53430
  "resource:not_found",
@@ -53297,6 +53480,7 @@ var ENDPOINT_DEFINITIONS = {
53297
53480
  tags: ["site-{siteId}", "memberships-{siteId}"],
53298
53481
  auth: "user",
53299
53482
  responseKind: "json",
53483
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53300
53484
  errors: ["validation:invalid_input", "server:internal_error"]
53301
53485
  },
53302
53486
  getBookingMembership: {
@@ -53312,6 +53496,7 @@ var ENDPOINT_DEFINITIONS = {
53312
53496
  tags: ["site-{siteId}", "memberships-{siteId}"],
53313
53497
  auth: "user",
53314
53498
  responseKind: "json",
53499
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53315
53500
  errors: [
53316
53501
  "validation:invalid_input",
53317
53502
  "resource:not_found",
@@ -53324,6 +53509,7 @@ var ENDPOINT_DEFINITIONS = {
53324
53509
  tags: ["site-{siteId}", "memberships-{siteId}"],
53325
53510
  auth: "user",
53326
53511
  responseKind: "json",
53512
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53327
53513
  errors: [
53328
53514
  "validation:invalid_input",
53329
53515
  "resource:not_found",
@@ -53540,6 +53726,7 @@ var ENDPOINT_DEFINITIONS = {
53540
53726
  tags: ["site-{siteId}", "customers-{siteId}"],
53541
53727
  auth: "user",
53542
53728
  responseKind: "json",
53729
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53543
53730
  errors: [
53544
53731
  "validation:invalid_input",
53545
53732
  "auth:forbidden",
@@ -54917,8 +55104,7 @@ var dashboardNavVisibilityBaseSchema = z66.object({
54917
55104
  var dashboardNavVisibilityRolesSchema = z66.object({
54918
55105
  administrator: dashboardNavVisibilityBaseSchema.optional(),
54919
55106
  editor: dashboardNavVisibilityBaseSchema.optional(),
54920
- team_member: dashboardNavVisibilityBaseSchema.optional(),
54921
- event_host: dashboardNavVisibilityBaseSchema.optional()
55107
+ team_member: dashboardNavVisibilityBaseSchema.optional()
54922
55108
  }).strip().optional();
54923
55109
  var dashboardNavVisibilitySchema = dashboardNavVisibilityBaseSchema.extend({
54924
55110
  roles: dashboardNavVisibilityRolesSchema
@@ -55439,6 +55625,21 @@ var appointmentSetupServiceDraftSchema = z68.object({
55439
55625
  timezone: z68.string().trim().min(1).nullable(),
55440
55626
  payment: appointmentSetupPaymentDraftSchema,
55441
55627
  assignment: appointmentSetupServiceAssignmentDraftSchema
55628
+ }).superRefine((service, ctx) => {
55629
+ if (service.payment.priceType === "paid" && (service.priceAmount === null || service.priceAmount <= 0)) {
55630
+ ctx.addIssue({
55631
+ code: "custom",
55632
+ path: ["priceAmount"],
55633
+ message: "Paid appointment services need a positive price."
55634
+ });
55635
+ }
55636
+ if (service.payment.priceType === "free" && service.priceAmount !== null && service.priceAmount > 0) {
55637
+ ctx.addIssue({
55638
+ code: "custom",
55639
+ path: ["priceAmount"],
55640
+ message: "Free appointment services cannot carry a positive price."
55641
+ });
55642
+ }
55442
55643
  });
55443
55644
  var appointmentSetupPractitionerDraftSchema = z68.object({
55444
55645
  ref: appointmentSetupRefSchema,