@riverbankcms/sdk 0.101.0 → 0.102.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 (54) hide show
  1. package/dist/{PreviewEditorSidebar-DBpy0KTh.mjs → PreviewEditorSidebar-BKkhhkJk.mjs} +358 -68
  2. package/dist/{PreviewEditorUI-Fg6I2R2T.mjs → PreviewEditorUI-DIvTqcqI.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-BICQLAUF.mjs → PreviewQueryProvider-ZF6TXq5Q.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-DFQP-Q53.mjs → SdkPreviewModeRuntime-CA2k7Z_T.mjs} +200 -122
  5. package/dist/{SiteChromeCustomizeContext-GwZc89KN.mjs → SiteChromeCustomizeContext-Bh9-DtMQ.mjs} +203 -34
  6. package/dist/_dts/ai/src/designer/rfc6902.d.ts +57 -1
  7. package/dist/_dts/ai/src/designer/themePatch.d.ts +16 -6
  8. package/dist/_dts/api/src/bookingVerticals.d.ts +53 -1
  9. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +1 -0
  10. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -1
  11. package/dist/_dts/blocks/src/system/runtime/nodes/layout.d.ts +1 -0
  12. package/dist/_dts/content-editor/src/index.d.ts +1 -0
  13. package/dist/_dts/core/src/branded.d.ts +4 -0
  14. package/dist/_dts/core/src/person-records.d.ts +6 -1
  15. package/dist/_dts/media-core/src/identifiers.d.ts +14 -1
  16. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +1 -1
  17. package/dist/_dts/preview-next/src/client/blocks/previewProjection/applyPreviewProjections.d.ts +3 -1
  18. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  19. package/dist/_dts/preview-next/src/client/preview/PreviewChromeLayer.d.ts +2 -1
  20. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +43 -7
  21. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +4 -4
  22. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -1
  23. package/dist/_dts/preview-next/src/client/preview/typographySelectionInput.d.ts +4 -2
  24. package/dist/_dts/sdk/src/version.d.ts +1 -1
  25. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +4 -2
  26. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +4 -4
  27. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +6 -1
  28. package/dist/_dts/theme-core/src/site-styles/rawStyleFields.d.ts +3 -3
  29. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +24 -1
  30. package/dist/cli/index.mjs +31 -15
  31. package/dist/client/client.mjs +44 -16
  32. package/dist/client/hooks.mjs +14 -5
  33. package/dist/client/rendering/client.mjs +21 -13
  34. package/dist/client/rendering.mjs +43 -15
  35. package/dist/preview-next/before-render.mjs +1 -1
  36. package/dist/preview-next/client/runtime.mjs +4 -4
  37. package/dist/{previewAuthStore-Da74OL0X.mjs → previewAuthStore-ByPPZqmp.mjs} +1 -0
  38. package/dist/{sdk-runtime-CP6Kwalv.mjs → sdk-runtime-K8Oqj97H.mjs} +2 -2
  39. package/dist/{separator-BVk7GvGN.mjs → separator-CRoP34pT.mjs} +1 -1
  40. package/dist/server/components.mjs +37 -13
  41. package/dist/server/config-validation.mjs +14 -5
  42. package/dist/server/config.mjs +14 -5
  43. package/dist/server/data.mjs +14 -5
  44. package/dist/server/index.mjs +2 -2
  45. package/dist/server/next.mjs +38 -14
  46. package/dist/server/page-converter.mjs +7 -4
  47. package/dist/server/prebuild.mjs +1 -1
  48. package/dist/server/rendering/server.mjs +37 -13
  49. package/dist/server/rendering.mjs +37 -13
  50. package/dist/server/routing.mjs +16 -6
  51. package/dist/server/server.mjs +15 -6
  52. package/dist/server/theme-bridge.mjs +5 -4
  53. package/dist/server/theme.mjs +1 -0
  54. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { $l as DropdownMenuLabel, $t as listEntryPageContentSlots, A as markApplySaving, Ai as requireEntriesForCuratedChoices, B as setTypographyBodyFontOverride, Bl as CollapsibleTrigger, C as createStyleConfiguratorState, Ci as curatedSiteStyles, Cl as TabsContent, D as isPreviewingChange, Dd as LoaderCircle, Di as evaluateTypographyFontSlot, E as dismissWarnings, Ed as Maximize2, F as previewHeaderStyle, Gi as findPaletteVariant, Gu as assertNever$1, H as styleConfiguratorHistoryEntryForPersistedSelection, Ht as FormRenderer, I as previewPaletteVariant, Ki as paletteVariants, L as previewSiteStyle, M as previewButtonPersonality, Mc as findButtonPersonality, Mi as getFooterLayout, Mt as resolvePageRouteSlug, N as previewFooterLook, Ni as getHeaderLayout, Nt as resolveContentTitle, O as markApplyFailed, Oi as findTypographyPreset, P as previewHeaderLayout, Pi as getHeaderStyle, Q as resolvePreviewSidebarTab, Ql as DropdownMenuItem, R as previewTypographyPreset, Rl as Collapsible, S as clearTypographyFontOverrides, Sl as Tabs, T as dismissNotices, Ti as getCuratedSiteStyle, Tl as TabsTrigger, Tu as unsafeAsEditorBlockId, U as syncStyleConfiguratorState, V as setTypographyHeadingFontOverride, Vt as createManifestValidation, W as toggleRow, Wt as createStoreBackend, Xd as ChevronRight, Xl as DropdownMenu, Yl as Surface, Z as createOptimisticActionRunner, Zd as ChevronLeft, Zl as DropdownMenuContent, _ as usePreviewDesignCoordinator, _t as useEditorUiStore, _u as Button, b as applyResolvedSelections, bl as PopoverTrigger, bu as cn, c as selectionSnapshotFromApplySiteStyleSelectionResponse, d as buildSiteChromeLookModels, dl as Select, dt as useUISelector, eu as DropdownMenuSeparator, f as cycleSiteChromeLookId, fd as Tablet, fl as SelectContent, h as planSiteChromeLookSelection, hd as Smartphone, hl as SelectValue, j as openRow, jc as buttonPersonalities, ji as findFooterLook, jt as deriveRouteMetadataPresentation, k as markApplySaved, ki as typographyPresets, l as planSiteStylePreviewChange, m as planSiteChromeFooterLayoutSelection, ml as SelectTrigger, mt as useEntryController, n as useSiteChromeCustomizeOptional, od as X$1, p as cycleableSiteChromeOptions, pl as SelectItem, qi as paletteOverridesSchema, s as buildApplySiteStyleSelectionBody, tu as DropdownMenuTrigger, u as resolveStyleConfiguratorInitialSnapshot, ut as ContentFieldsForm, vl as Popover, vt as useEditorUiStoreInstance, w as deriveStyleConfiguratorCapabilities, wd as Monitor, wl as TabsList, x as cancelPreview, xl as Input, yl as PopoverContent, z as setPaletteOverrides, zl as CollapsibleContent, zt as ManifestForm } from "./SiteChromeCustomizeContext-GwZc89KN.mjs";
3
- import { d as unwrapResponse, f as getDashboardUrl, r as usePreviewAuth } from "./previewAuthStore-Da74OL0X.mjs";
4
- import { S as isAdapterReferenceKind, T as CalloutDescription, _ as usePreviewBlockCustomizeSelectionOptional, b as previewWidgetOverrides, d as buildPreviewDashboardSetupUrl, f as resolvePreviewDashboardSetupHandoff, g as canInspectSiteStyle, h as canApplySiteStyle, m as resolvePreviewSidebarChromeModel, p as resolvePreviewEditorGuidanceModel, v as useBlockCustomizeControls, w as Callout, x as BlockEditor, y as PreviewFormProvider } from "./SdkPreviewModeRuntime-DFQP-Q53.mjs";
5
- import { t as Separator } from "./separator-BVk7GvGN.mjs";
2
+ import { $d as ChevronLeft, $l as DropdownMenuContent, A as markApplySaving, Ai as findTypographyPreset, B as setPaletteOverrides, Bl as Collapsible, Bt as ManifestForm, C as createStyleConfiguratorState, Cl as Input, D as isPreviewingChange, Di as getCuratedSiteStyle, Dl as TabsTrigger, Du as unsafeAsEditorBlockId, E as dismissWarnings, Ed as Monitor, El as TabsList, F as previewHeaderStyle, Fi as getHeaderLayout, Gt as createStoreBackend, H as syncStyleConfiguratorState, Hl as CollapsibleTrigger, Ht as createManifestValidation, I as previewPaletteVariant, Ii as getHeaderStyle, Ji as paletteVariants, L as previewSiteStyle, M as previewButtonPersonality, Mi as requireEntriesForCuratedChoices, Mt as deriveRouteMetadataPresentation, N as previewFooterLook, Nc as buttonPersonalities, Ni as findFooterLook, Nt as resolvePageRouteSlug, O as markApplyFailed, Od as Maximize2, P as previewHeaderLayout, Pc as findButtonPersonality, Pi as getFooterLayout, Pt as resolveContentTitle, Q as resolvePreviewSidebarTab, Qd as ChevronRight, Ql as DropdownMenu, R as previewTypographyPreset, S as cancelPreview, Sl as PopoverTrigger, Su as cn, T as dismissNotices, Ti as curatedSiteStyles, Tl as TabsContent, U as toggleRow, Ut as FormRenderer, V as styleConfiguratorHistoryEntryForPersistedSelection, Vl as CollapsibleContent, W as typographySelectionSnapshotFromFlat, Yi as paletteOverridesSchema, Z as createOptimisticActionRunner, Zl as Surface, _ as usePreviewDesignCoordinator, _d as Smartphone, _l as SelectValue, _t as useEditorUiStore, b as applyResolvedSelections, bl as Popover, c as selectionSnapshotFromApplySiteStyleSelectionResponse, cd as X$1, d as buildSiteChromeLookModels, dt as useUISelector, en as listEntryPageContentSlots, eu as DropdownMenuItem, f as cycleSiteChromeLookId, gl as SelectTrigger, h as planSiteChromeLookSelection, hl as SelectItem, j as openRow, ji as typographyPresets, k as markApplySaved, kd as LoaderCircle, ki as evaluateTypographyFontSlot, l as planSiteStylePreviewChange, m as planSiteChromeFooterLayoutSelection, md as Tablet, ml as SelectContent, mt as useEntryController, n as useSiteChromeCustomizeOptional, nu as DropdownMenuSeparator, p as cycleableSiteChromeOptions, pl as Select, qi as findPaletteVariant, qu as assertNever$1, ru as DropdownMenuTrigger, s as buildApplySiteStyleSelectionBody, tu as DropdownMenuLabel, u as resolveStyleConfiguratorInitialSnapshot, ut as ContentFieldsForm, vt as useEditorUiStoreInstance, w as deriveStyleConfiguratorCapabilities, wl as Tabs, x as applyTypographyDraftPatch, xl as PopoverContent, yu as Button, z as resetTypographyToSaved } from "./SiteChromeCustomizeContext-Bh9-DtMQ.mjs";
3
+ import { d as unwrapResponse, f as getDashboardUrl, r as usePreviewAuth } from "./previewAuthStore-ByPPZqmp.mjs";
4
+ import { S as isAdapterReferenceKind, T as CalloutDescription, _ as usePreviewBlockCustomizeSelectionOptional, b as previewWidgetOverrides, d as buildPreviewDashboardSetupUrl, f as resolvePreviewDashboardSetupHandoff, g as canInspectSiteStyle, h as canApplySiteStyle, m as resolvePreviewSidebarChromeModel, p as resolvePreviewEditorGuidanceModel, v as useBlockCustomizeControls, w as Callout, x as BlockEditor, y as PreviewFormProvider } from "./SdkPreviewModeRuntime-CA2k7Z_T.mjs";
5
+ import { t as Separator } from "./separator-CRoP34pT.mjs";
6
6
  import React, { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, useTransition } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useQuery, useQueryClient } from "@tanstack/react-query";
@@ -2212,6 +2212,10 @@ function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVer
2212
2212
  });
2213
2213
  return applyResolvedSelections(next, {
2214
2214
  resolved: result.resolvedSelections,
2215
+ ...result.resolvedSelections.typographySelection.kind === "custom" ? { typographySelection: {
2216
+ kind: "custom",
2217
+ typography: result.themeOverlay.typography
2218
+ } } : {},
2215
2219
  warnings: result.warnings
2216
2220
  });
2217
2221
  });
@@ -2264,14 +2268,44 @@ function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVer
2264
2268
  const handlePreviewTypographyPreset = useCallback((id) => {
2265
2269
  setState((current) => current ? previewTypographyPreset(current, id) : current);
2266
2270
  }, []);
2267
- const handleBodyFontOverride = useCallback((fontFamily) => {
2268
- setState((current) => current ? setTypographyBodyFontOverride(current, fontFamily) : current);
2269
- }, []);
2270
- const handleHeadingFontOverride = useCallback((fontFamily) => {
2271
- setState((current) => current ? setTypographyHeadingFontOverride(current, fontFamily) : current);
2272
- }, []);
2273
- const handleClearTypographyOverrides = useCallback(() => {
2274
- setState((current) => current ? clearTypographyFontOverrides(current) : current);
2271
+ const patchTypography = useCallback((patch) => {
2272
+ setState((current) => {
2273
+ if (!current) return current;
2274
+ const siteStyle = getCuratedSiteStyle(current.previewed.siteStyleId);
2275
+ if (!siteStyle) return current;
2276
+ return applyTypographyDraftPatch(current, planSiteStylePreviewChange({
2277
+ siteStyle,
2278
+ selection: current.previewed,
2279
+ baseTheme: theme,
2280
+ headerSelectionContext,
2281
+ footerSelectionContext
2282
+ }).themeOverlay.typography, patch);
2283
+ });
2284
+ }, [
2285
+ footerSelectionContext,
2286
+ headerSelectionContext,
2287
+ theme
2288
+ ]);
2289
+ const handleHeadingTypographyChange = useCallback((patch) => {
2290
+ patchTypography({
2291
+ kind: "heading",
2292
+ patch
2293
+ });
2294
+ }, [patchTypography]);
2295
+ const handleBodyTypographyChange = useCallback((patch) => {
2296
+ patchTypography({
2297
+ kind: "body",
2298
+ patch
2299
+ });
2300
+ }, [patchTypography]);
2301
+ const handleTypographyScaleChange = useCallback((scale) => {
2302
+ patchTypography({
2303
+ kind: "scale",
2304
+ scale
2305
+ });
2306
+ }, [patchTypography]);
2307
+ const handleResetTypography = useCallback(() => {
2308
+ setState((current) => current ? resetTypographyToSaved(current) : current);
2275
2309
  }, []);
2276
2310
  const handleTokenOverride = useCallback((role, hex) => {
2277
2311
  setState((current) => {
@@ -2323,9 +2357,10 @@ function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVer
2323
2357
  headerLayoutId: compiled.resolvedSelections.headerLayoutId,
2324
2358
  headerStyleId: compiled.resolvedSelections.headerStyleId,
2325
2359
  headerLookId: compiled.resolvedSelections.headerLookId,
2326
- typographyPresetId: compiled.resolvedSelections.typographyPresetId,
2327
- typographyBodyFontOverride: compiled.resolvedSelections.typographyBodyFontOverride,
2328
- typographyHeadingFontOverride: compiled.resolvedSelections.typographyHeadingFontOverride
2360
+ typographySelection: compiled.resolvedSelections.typographySelection.kind === "custom" ? {
2361
+ kind: "custom",
2362
+ typography: compiled.themeOverlay.typography
2363
+ } : typographySelectionSnapshotFromFlat(compiled.resolvedSelections)
2329
2364
  },
2330
2365
  selectionId
2331
2366
  });
@@ -2390,7 +2425,14 @@ function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVer
2390
2425
  });
2391
2426
  const currentPersonality = findButtonPersonality(state.previewed.buttonPersonalityId);
2392
2427
  const currentPaletteVariant = findPaletteVariant(state.previewed.paletteVariantId);
2393
- const currentTypographyPreset = state.previewed.typographyPresetId ? findTypographyPreset(state.previewed.typographyPresetId) : null;
2428
+ const currentTypographyPreset = state.previewed.typographySelection.kind === "preset" && state.previewed.typographySelection.presetId ? findTypographyPreset(state.previewed.typographySelection.presetId) : null;
2429
+ const currentTypography = planSiteStylePreviewChange({
2430
+ siteStyle: currentSiteStyle,
2431
+ selection: state.previewed,
2432
+ baseTheme: theme,
2433
+ headerSelectionContext,
2434
+ footerSelectionContext
2435
+ }).themeOverlay.typography;
2394
2436
  const chromeLookModels = buildSiteChromeLookModels({
2395
2437
  state,
2396
2438
  siteStyle: currentSiteStyle,
@@ -2505,14 +2547,14 @@ function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVer
2505
2547
  onToggle: () => handleToggleRow("typography"),
2506
2548
  apiClient,
2507
2549
  siteStyle: currentSiteStyle,
2508
- currentPresetId: state.previewed.typographyPresetId,
2550
+ typography: currentTypography,
2551
+ currentPresetId: state.previewed.typographySelection.kind === "preset" ? state.previewed.typographySelection.presetId : null,
2509
2552
  currentLabel: currentTypographyPreset?.name ?? "Custom typography",
2510
- bodyFontOverride: state.previewed.typographyBodyFontOverride,
2511
- headingFontOverride: state.previewed.typographyHeadingFontOverride,
2512
2553
  onPreviewPreset: handlePreviewTypographyPreset,
2513
- onBodyFontOverride: handleBodyFontOverride,
2514
- onHeadingFontOverride: handleHeadingFontOverride,
2515
- onClearOverrides: handleClearTypographyOverrides,
2554
+ onHeadingChange: handleHeadingTypographyChange,
2555
+ onBodyChange: handleBodyTypographyChange,
2556
+ onScaleChange: handleTypographyScaleChange,
2557
+ onReset: handleResetTypography,
2516
2558
  disabled: saving
2517
2559
  }),
2518
2560
  /* @__PURE__ */ jsx(PaletteRow, {
@@ -2643,21 +2685,25 @@ function PersonalityRow({ expanded, onToggle, siteStyle, currentId, currentLabel
2643
2685
  })
2644
2686
  });
2645
2687
  }
2646
- function TypographyRow({ expanded, onToggle, apiClient, siteStyle, currentPresetId, currentLabel, bodyFontOverride, headingFontOverride, onPreviewPreset, onBodyFontOverride, onHeadingFontOverride, onClearOverrides, disabled }) {
2688
+ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, typography, currentPresetId, currentLabel, onPreviewPreset, onHeadingChange, onBodyChange, onScaleChange, onReset, disabled }) {
2689
+ const [headingOpen, setHeadingOpen] = useState(true);
2690
+ const [bodyOpen, setBodyOpen] = useState(false);
2647
2691
  const options = useMemo(() => requireEntriesForCuratedChoices(typographyPresets, siteStyle.typographyPresetChoices), [siteStyle.typographyPresetChoices]);
2648
2692
  const fontCatalog = useFontCatalog(apiClient, expanded);
2649
- const selectedPreset = currentPresetId ? findTypographyPreset(currentPresetId) : null;
2693
+ const fontPolicyPreset = (currentPresetId ? findTypographyPreset(currentPresetId) : null) ?? options[0] ?? typographyPresets[0];
2694
+ if (!fontPolicyPreset) return null;
2650
2695
  return /* @__PURE__ */ jsxs(StyleRowFrame, {
2651
2696
  label: "Typography",
2652
2697
  currentLabel,
2653
2698
  expanded,
2654
2699
  onToggle,
2655
- children: [
2656
- currentPresetId === null ? /* @__PURE__ */ jsx("div", {
2657
- className: "mb-3 rounded-md border border-muted-foreground/20 bg-muted/30 px-3 py-2 text-xs text-muted-foreground",
2658
- children: "Current custom setup"
2659
- }) : null,
2660
- /* @__PURE__ */ jsx("ul", {
2700
+ children: [/* @__PURE__ */ jsxs("section", {
2701
+ "aria-label": "Start from preset",
2702
+ className: "space-y-2",
2703
+ children: [/* @__PURE__ */ jsx("div", {
2704
+ className: "text-xs font-medium text-muted-foreground",
2705
+ children: "Start from preset"
2706
+ }), /* @__PURE__ */ jsx("ul", {
2661
2707
  role: "radiogroup",
2662
2708
  "aria-label": "Typography preset",
2663
2709
  className: "space-y-1",
@@ -2667,40 +2713,262 @@ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, currentPreset
2667
2713
  onSelect: () => onPreviewPreset(preset.id),
2668
2714
  disabled
2669
2715
  }, preset.id))
2670
- }),
2671
- /* @__PURE__ */ jsxs("div", {
2672
- className: "mt-3 space-y-3 border-t pt-3",
2673
- children: [selectedPreset ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(TypographyFontSlotPicker, {
2674
- label: "Body font",
2675
- slot: "body",
2676
- preset: selectedPreset,
2677
- catalog: fontCatalog,
2678
- value: bodyFontOverride,
2679
- onChange: onBodyFontOverride,
2680
- disabled
2681
- }), /* @__PURE__ */ jsx(TypographyFontSlotPicker, {
2682
- label: "Heading font",
2683
- slot: "heading",
2684
- preset: selectedPreset,
2685
- catalog: fontCatalog,
2686
- value: headingFontOverride,
2687
- onChange: onHeadingFontOverride,
2688
- disabled
2689
- })] }) : /* @__PURE__ */ jsx("p", {
2690
- className: "text-xs text-muted-foreground",
2691
- children: "Choose a typography preset to use curated font overrides."
2692
- }), /* @__PURE__ */ jsx(Button, {
2716
+ })]
2717
+ }), /* @__PURE__ */ jsxs("div", {
2718
+ className: "mt-3 space-y-2 border-t pt-3",
2719
+ children: [
2720
+ /* @__PURE__ */ jsxs(TypographyDisclosure, {
2721
+ label: "Heading",
2722
+ open: headingOpen,
2723
+ onOpenChange: setHeadingOpen,
2724
+ children: [
2725
+ /* @__PURE__ */ jsx(TypographyFontSlotPicker, {
2726
+ label: "Heading font",
2727
+ slot: "heading",
2728
+ preset: fontPolicyPreset,
2729
+ catalog: fontCatalog,
2730
+ value: typography.headings.default.family,
2731
+ onChange: (family) => onHeadingChange({ family }),
2732
+ disabled
2733
+ }),
2734
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2735
+ label: "Weight",
2736
+ value: typography.headings.default.weight,
2737
+ options: typographyWeightOptions,
2738
+ onChange: (weight) => onHeadingChange({ weight }),
2739
+ disabled
2740
+ }),
2741
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2742
+ label: "Line height",
2743
+ value: typography.headings.default.lineHeight,
2744
+ options: typographyLineHeightOptions,
2745
+ onChange: (lineHeight) => onHeadingChange({ lineHeight }),
2746
+ disabled
2747
+ }),
2748
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2749
+ label: "Scale",
2750
+ value: normalizeTypographyScaleForControl(typography.scale),
2751
+ options: typographyScaleOptions,
2752
+ onChange: onScaleChange,
2753
+ disabled
2754
+ }),
2755
+ /* @__PURE__ */ jsx(TypographyColorTokenControl, {
2756
+ value: typography.headings.default.colorToken ?? "text",
2757
+ onChange: (colorToken) => onHeadingChange({ colorToken: colorToken === "text" ? null : colorToken }),
2758
+ disabled
2759
+ })
2760
+ ]
2761
+ }),
2762
+ /* @__PURE__ */ jsxs(TypographyDisclosure, {
2763
+ label: "Body",
2764
+ open: bodyOpen,
2765
+ onOpenChange: setBodyOpen,
2766
+ children: [
2767
+ /* @__PURE__ */ jsx(TypographyFontSlotPicker, {
2768
+ label: "Body font",
2769
+ slot: "body",
2770
+ preset: fontPolicyPreset,
2771
+ catalog: fontCatalog,
2772
+ value: typography.body.family,
2773
+ onChange: (family) => onBodyChange({ family }),
2774
+ disabled
2775
+ }),
2776
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2777
+ label: "Size",
2778
+ value: typography.body.size,
2779
+ options: bodySizeOptions,
2780
+ onChange: (size) => onBodyChange({ size }),
2781
+ disabled
2782
+ }),
2783
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2784
+ label: "Weight",
2785
+ value: typography.body.weight,
2786
+ options: typographyWeightOptions,
2787
+ onChange: (weight) => onBodyChange({ weight }),
2788
+ disabled
2789
+ }),
2790
+ /* @__PURE__ */ jsx(TypographySelectControl, {
2791
+ label: "Line height",
2792
+ value: typography.body.lineHeight,
2793
+ options: typographyLineHeightOptions,
2794
+ onChange: (lineHeight) => onBodyChange({ lineHeight }),
2795
+ disabled
2796
+ })
2797
+ ]
2798
+ }),
2799
+ /* @__PURE__ */ jsx(Button, {
2693
2800
  type: "button",
2694
2801
  size: "sm",
2695
2802
  variant: "outline",
2696
- onClick: onClearOverrides,
2697
- disabled: disabled || !bodyFontOverride && !headingFontOverride,
2698
- children: "Use preset fonts"
2699
- })]
2700
- })
2701
- ]
2803
+ onClick: onReset,
2804
+ disabled,
2805
+ children: "Reset typography"
2806
+ })
2807
+ ]
2808
+ })]
2809
+ });
2810
+ }
2811
+ const typographyWeightOptions = [
2812
+ {
2813
+ value: "light",
2814
+ label: "Light"
2815
+ },
2816
+ {
2817
+ value: "regular",
2818
+ label: "Regular"
2819
+ },
2820
+ {
2821
+ value: "medium",
2822
+ label: "Medium"
2823
+ },
2824
+ {
2825
+ value: "semibold",
2826
+ label: "Semibold"
2827
+ },
2828
+ {
2829
+ value: "bold",
2830
+ label: "Bold"
2831
+ }
2832
+ ];
2833
+ const typographyLineHeightOptions = [
2834
+ {
2835
+ value: "normal",
2836
+ label: "Normal"
2837
+ },
2838
+ {
2839
+ value: "relaxed",
2840
+ label: "Relaxed"
2841
+ },
2842
+ {
2843
+ value: "loose",
2844
+ label: "Loose"
2845
+ }
2846
+ ];
2847
+ const bodySizeOptions = [
2848
+ {
2849
+ value: "md",
2850
+ label: "Medium"
2851
+ },
2852
+ {
2853
+ value: "lg",
2854
+ label: "Large"
2855
+ },
2856
+ {
2857
+ value: "xl",
2858
+ label: "Extra large"
2859
+ }
2860
+ ];
2861
+ const typographyScaleOptions = [
2862
+ {
2863
+ value: "compact",
2864
+ label: "Compact"
2865
+ },
2866
+ {
2867
+ value: "balanced",
2868
+ label: "Balanced"
2869
+ },
2870
+ {
2871
+ value: "spacious",
2872
+ label: "Spacious"
2873
+ }
2874
+ ];
2875
+ const headingColorTokenOptions = [
2876
+ {
2877
+ value: "text",
2878
+ label: "Text"
2879
+ },
2880
+ {
2881
+ value: "primary",
2882
+ label: "Primary"
2883
+ },
2884
+ {
2885
+ value: "secondary",
2886
+ label: "Secondary"
2887
+ },
2888
+ {
2889
+ value: "accent",
2890
+ label: "Accent"
2891
+ }
2892
+ ];
2893
+ function TypographyDisclosure({ label, open, onOpenChange, children }) {
2894
+ return /* @__PURE__ */ jsx(Collapsible, {
2895
+ open,
2896
+ onOpenChange,
2897
+ children: /* @__PURE__ */ jsxs("div", {
2898
+ className: "rounded-md border bg-muted/10",
2899
+ children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
2900
+ asChild: true,
2901
+ children: /* @__PURE__ */ jsxs("button", {
2902
+ type: "button",
2903
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm font-medium hover:bg-accent/30",
2904
+ "aria-expanded": open,
2905
+ children: [/* @__PURE__ */ jsx(ChevronRight, {
2906
+ className: cn("h-4 w-4 transition", open && "rotate-90"),
2907
+ "aria-hidden": "true"
2908
+ }), /* @__PURE__ */ jsx("span", { children: label })]
2909
+ })
2910
+ }), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", {
2911
+ className: "space-y-3 border-t px-3 py-3",
2912
+ children
2913
+ }) })]
2914
+ })
2702
2915
  });
2703
2916
  }
2917
+ function TypographySelectControl({ label, value, options, onChange, disabled }) {
2918
+ return /* @__PURE__ */ jsxs("label", {
2919
+ className: "block space-y-1",
2920
+ children: [/* @__PURE__ */ jsx("span", {
2921
+ className: "text-xs font-medium text-muted-foreground",
2922
+ children: label
2923
+ }), /* @__PURE__ */ jsx("select", {
2924
+ value,
2925
+ onChange: (event) => onChange(event.currentTarget.value),
2926
+ disabled,
2927
+ className: "h-8 w-full rounded-md border bg-background px-2 text-sm outline-none focus:border-primary disabled:cursor-not-allowed disabled:opacity-50",
2928
+ children: options.map((option) => /* @__PURE__ */ jsx("option", {
2929
+ value: option.value,
2930
+ children: option.label
2931
+ }, option.value))
2932
+ })]
2933
+ });
2934
+ }
2935
+ function TypographyColorTokenControl({ value, onChange, disabled }) {
2936
+ return /* @__PURE__ */ jsxs("section", {
2937
+ className: "space-y-2",
2938
+ "aria-label": "Default heading color",
2939
+ children: [/* @__PURE__ */ jsxs("div", {
2940
+ className: "flex items-center justify-between gap-2",
2941
+ children: [/* @__PURE__ */ jsx("span", {
2942
+ className: "text-xs font-medium text-muted-foreground",
2943
+ children: "Default heading color"
2944
+ }), /* @__PURE__ */ jsx("span", {
2945
+ className: "text-[11px] text-muted-foreground",
2946
+ children: "Sections may override"
2947
+ })]
2948
+ }), /* @__PURE__ */ jsx("div", {
2949
+ className: "grid grid-cols-2 gap-1",
2950
+ children: headingColorTokenOptions.map((option) => /* @__PURE__ */ jsx("button", {
2951
+ type: "button",
2952
+ className: cn("rounded-md border px-2 py-1.5 text-left text-xs transition disabled:cursor-not-allowed disabled:opacity-50", value === option.value ? "border-primary bg-primary/10" : "border-border hover:bg-muted/60"),
2953
+ "aria-pressed": value === option.value,
2954
+ onClick: () => onChange(option.value),
2955
+ disabled,
2956
+ children: option.label
2957
+ }, option.value))
2958
+ })]
2959
+ });
2960
+ }
2961
+ function normalizeTypographyScaleForControl(scale) {
2962
+ switch (scale) {
2963
+ case "compact":
2964
+ case "balanced":
2965
+ case "spacious": return scale;
2966
+ case "minorThird": return "compact";
2967
+ case "majorThird": return "balanced";
2968
+ case "perfectFourth": return "spacious";
2969
+ default: return "balanced";
2970
+ }
2971
+ }
2704
2972
  function TypographyPresetOption({ preset, selected, onSelect, disabled }) {
2705
2973
  return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
2706
2974
  type: "button",
@@ -2735,8 +3003,24 @@ function TypographyPresetOption({ preset, selected, onSelect, disabled }) {
2735
3003
  }
2736
3004
  function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChange, disabled }) {
2737
3005
  const [query, setQuery] = useState("");
3006
+ const [manualFamilyDraft, setManualFamilyDraft] = useState(value);
2738
3007
  const defaultFont = primaryFontFamily(preset.defaultFonts[slot]);
2739
- const selectedFamily = value ?? defaultFont;
3008
+ const selectedFamily = primaryFontFamily(value);
3009
+ useEffect(() => {
3010
+ setManualFamilyDraft(value);
3011
+ }, [value]);
3012
+ const commitManualFamilyDraft = useCallback(() => {
3013
+ const normalized = normalizeFontFamilyOverride(manualFamilyDraft);
3014
+ if (!normalized) {
3015
+ setManualFamilyDraft(value);
3016
+ return;
3017
+ }
3018
+ onChange(normalized);
3019
+ }, [
3020
+ manualFamilyDraft,
3021
+ onChange,
3022
+ value
3023
+ ]);
2740
3024
  const recordsByFamily = useMemo(() => indexFontsByFamily(catalog.fonts), [catalog.fonts]);
2741
3025
  const selectedFit = evaluateTypographyFontSlot({
2742
3026
  slot,
@@ -2768,7 +3052,7 @@ function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChang
2768
3052
  children: label
2769
3053
  }), /* @__PURE__ */ jsx("div", {
2770
3054
  className: "truncate text-sm",
2771
- children: value ? selectedFamily : `${defaultFont} (preset)`
3055
+ children: selectedFamily
2772
3056
  })]
2773
3057
  }), /* @__PURE__ */ jsx(TypographyFontFitBadge, { fit: selectedFit })]
2774
3058
  }),
@@ -2776,19 +3060,19 @@ function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChang
2776
3060
  className: "grid grid-cols-1 gap-1",
2777
3061
  children: [/* @__PURE__ */ jsxs("button", {
2778
3062
  type: "button",
2779
- className: cn("rounded-md border px-3 py-2 text-left text-sm transition disabled:cursor-not-allowed disabled:opacity-50", value === null ? "border-foreground bg-accent/40" : "border-transparent hover:border-foreground/40 hover:bg-accent/20"),
2780
- onClick: () => onChange(null),
3063
+ className: cn("rounded-md border px-3 py-2 text-left text-sm transition disabled:cursor-not-allowed disabled:opacity-50", selectedFamily === defaultFont ? "border-foreground bg-accent/40" : "border-transparent hover:border-foreground/40 hover:bg-accent/20"),
3064
+ onClick: () => onChange(preset.defaultFonts[slot]),
2781
3065
  disabled,
2782
3066
  children: [/* @__PURE__ */ jsx("span", {
2783
3067
  className: "font-medium",
2784
- children: "Use preset font"
3068
+ children: "Use recipe font"
2785
3069
  }), /* @__PURE__ */ jsx("span", {
2786
3070
  className: "ml-2 text-xs text-muted-foreground",
2787
3071
  children: defaultFont
2788
3072
  })]
2789
3073
  }), recommendedOptions.map((family) => /* @__PURE__ */ jsx(FontFamilyOption, {
2790
3074
  family,
2791
- selected: value === family,
3075
+ selected: selectedFamily === family,
2792
3076
  fit: evaluateTypographyFontSlot({
2793
3077
  slot,
2794
3078
  policy: preset.slotPolicies[slot],
@@ -2804,6 +3088,7 @@ function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChang
2804
3088
  /* @__PURE__ */ jsx("input", {
2805
3089
  type: "search",
2806
3090
  value: query,
3091
+ "aria-label": `Search ${slot} fonts`,
2807
3092
  placeholder: `Search ${slot} fonts`,
2808
3093
  onChange: (event) => setQuery(event.currentTarget.value),
2809
3094
  disabled: disabled || catalog.kind === "loading",
@@ -2820,7 +3105,7 @@ function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChang
2820
3105
  className: "max-h-56 space-y-1 overflow-y-auto pr-1",
2821
3106
  children: browseOptions.map((font) => /* @__PURE__ */ jsx(FontFamilyOption, {
2822
3107
  family: font.family,
2823
- selected: value === font.family,
3108
+ selected: selectedFamily === font.family,
2824
3109
  fit: evaluateTypographyFontSlot({
2825
3110
  slot,
2826
3111
  policy: preset.slotPolicies[slot],
@@ -2842,9 +3127,14 @@ function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChang
2842
3127
  children: "Brand or uploaded font name"
2843
3128
  }), /* @__PURE__ */ jsx("input", {
2844
3129
  type: "text",
2845
- value: value ?? "",
3130
+ value: manualFamilyDraft,
2846
3131
  placeholder: "Enter any font family",
2847
- onChange: (event) => onChange(normalizeFontFamilyOverride(event.currentTarget.value)),
3132
+ onChange: (event) => setManualFamilyDraft(event.currentTarget.value),
3133
+ onBlur: commitManualFamilyDraft,
3134
+ onKeyDown: (event) => {
3135
+ if (event.key !== "Enter") return;
3136
+ event.currentTarget.blur();
3137
+ },
2848
3138
  disabled,
2849
3139
  className: "h-8 w-full rounded-md border bg-background px-2 text-sm outline-none focus:border-primary disabled:cursor-not-allowed disabled:opacity-50"
2850
3140
  })]
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { Bd as EllipsisVertical, Cd as Palette, Dd as LoaderCircle, Dt as useMultiAutosave, Il as DialogHeader, Ll as DialogTitle, Nl as DialogContent, Pl as DialogDescription, Qd as ChevronDown, Ql as DropdownMenuItem, Rd as Eye, Sd as PenLine, Xl as DropdownMenu, Zl as DropdownMenuContent, _t as useEditorUiStore, _u as Button, a as previewDesignHistoryDomainForCommand, bu as cn, cd as Undo2, gt as classifyHistoryShortcut, ht as useEntryEditorController, i as usePreviewDesignHistoryOrder, jl as Dialog, ld as TriangleAlert, ll as TooltipTrigger, lt as useEditor, md as Sparkles, n as useSiteChromeCustomizeOptional, o as selectPreviewDesignHistoryDomain, ol as Tooltip, sl as TooltipContent, tu as DropdownMenuTrigger, vt as useEditorUiStoreInstance, vu as cva, xd as Pencil, yd as Redo2 } from "./SiteChromeCustomizeContext-GwZc89KN.mjs";
3
- import { d as unwrapResponse, r as usePreviewAuth } from "./previewAuthStore-Da74OL0X.mjs";
4
- import { C as FixedBottomSurface, a as usePreviewPageDesignEditorState, c as applyPreviewChromeSurfaceToElement, l as resolvePreviewChromeSurface, o as PREVIEW_CHROME_PORTAL_CLASS_NAME, s as PREVIEW_CHROME_THEME_CLASS_NAME, u as setPreviewSidebarTab } from "./SdkPreviewModeRuntime-DFQP-Q53.mjs";
2
+ import { $l as DropdownMenuContent, Bd as Eye, Cd as Pencil, Fl as DialogContent, Hd as EllipsisVertical, Il as DialogDescription, Nl as Dialog, Ot as useMultiAutosave, Ql as DropdownMenu, Rl as DialogHeader, Su as cn, Td as Palette, _t as useEditorUiStore, a as previewDesignHistoryDomainForCommand, bu as cva, cl as Tooltip, dd as TriangleAlert, dl as TooltipTrigger, ef as ChevronDown, eu as DropdownMenuItem, gd as Sparkles, gt as classifyHistoryShortcut, ht as useEntryEditorController, i as usePreviewDesignHistoryOrder, kd as LoaderCircle, ll as TooltipContent, lt as useEditor, n as useSiteChromeCustomizeOptional, o as selectPreviewDesignHistoryDomain, ru as DropdownMenuTrigger, ud as Undo2, vt as useEditorUiStoreInstance, wd as PenLine, xd as Redo2, yu as Button, zl as DialogTitle } from "./SiteChromeCustomizeContext-Bh9-DtMQ.mjs";
3
+ import { d as unwrapResponse, r as usePreviewAuth } from "./previewAuthStore-ByPPZqmp.mjs";
4
+ import { C as FixedBottomSurface, a as usePreviewPageDesignEditorState, c as applyPreviewChromeSurfaceToElement, l as resolvePreviewChromeSurface, o as PREVIEW_CHROME_PORTAL_CLASS_NAME, s as PREVIEW_CHROME_THEME_CLASS_NAME, u as setPreviewSidebarTab } from "./SdkPreviewModeRuntime-CA2k7Z_T.mjs";
5
5
  import * as React$1 from "react";
6
6
  import { useCallback, useEffect, useMemo, useState, useTransition } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { n as markPreviewAuthExpired, s as ApiRequestError } from "./previewAuthStore-Da74OL0X.mjs";
2
+ import { n as markPreviewAuthExpired, s as ApiRequestError } from "./previewAuthStore-ByPPZqmp.mjs";
3
3
  import { createContext, useContext, useRef } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { MutationCache, QueryCache, QueryClient, QueryClientProvider } from "@tanstack/react-query";