@riverbankcms/sdk 0.104.3 → 0.107.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.
- package/README.md +84 -51
- package/dist/{PreviewEditorSidebar-CBMhU9p_.mjs → PreviewEditorSidebar-DpAbAl08.mjs} +1811 -1179
- package/dist/{PreviewEditorUI-C5KEw4M8.mjs → PreviewEditorUI-O7cn6Xxv.mjs} +3 -3
- package/dist/{PreviewQueryProvider-CStABBUh.mjs → PreviewQueryProvider-D0tnKl0t.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-Iq12HjL7.mjs → SdkPreviewModeRuntime-CVB7urtl.mjs} +2144 -393
- package/dist/{SiteChromeCustomizeContext-Cx0NMdyv.mjs → SiteChromeCustomizeContext-C_sizso-.mjs} +3825 -2653
- package/dist/_dts/ai/src/contracts/proposals.d.ts +32945 -1339
- package/dist/_dts/api/src/bookingConfig.d.ts +2 -0
- package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +5 -1
- package/dist/_dts/api/src/contentRuntime.d.ts +6 -15
- package/dist/_dts/api/src/courses.d.ts +68 -10
- package/dist/_dts/api/src/endpoints.d.ts +29 -0
- package/dist/_dts/api/src/index.d.ts +124 -124
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +9 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +116 -6
- package/dist/_dts/api/src/siteOperations.d.ts +1 -0
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +26 -4
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +31 -46
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +36 -4
- package/dist/_dts/blocks/src/definitions.d.ts +1 -1
- package/dist/_dts/blocks/src/portal/types.d.ts +25 -7
- package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +4 -0
- package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule-projection.d.ts +52 -0
- package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +22 -0
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +45 -0
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +10 -0
- package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +4 -1
- package/dist/_dts/blocks/src/system/blocks/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +9 -0
- package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +8 -2
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/index.d.ts +8 -8
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +24 -24
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/scheduleSummary.d.ts +29 -0
- package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -1
- package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
- package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +2 -5
- package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
- package/dist/_dts/blocks/src/system/designCapabilities.d.ts +1 -0
- package/dist/_dts/blocks/src/system/fragments/library/newsletterForm.d.ts +2 -2
- package/dist/_dts/blocks/src/system/node/fragments/styledCard.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/blockComposition.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +90 -6
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +45 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/commerce/shared/display.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details/logic.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details/view.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details.server.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/course-page-surface-scope.d.ts +17 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/types.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +9 -18
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +106 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/RecurringSchedule.d.ts +11 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +7 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +11 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +6 -6
- package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +11 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/shop.types.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/svg.d.ts +7 -0
- package/dist/_dts/core/src/branded.d.ts +44 -0
- package/dist/_dts/core/src/dated-offering-settlement.d.ts +47 -0
- package/dist/_dts/core/src/event-page-surface-subject.d.ts +44 -0
- package/dist/_dts/core/src/index.d.ts +49 -47
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +1452 -15
- package/dist/_dts/editor-blocks/src/block-editor/FeatureCardIconsPanel.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/block-editor/GeneratedIconSetDialog.d.ts +4 -1
- package/dist/_dts/media-core/src/index.d.ts +2 -1
- package/dist/_dts/media-core/src/storagePathDomain.d.ts +47 -0
- package/dist/_dts/media-core/src/url.d.ts +1 -21
- package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +4 -2
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +3 -9
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +7 -11
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +3 -9
- package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +2 -6
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +5 -9
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +81 -43
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.typography.d.ts +61 -0
- package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +7 -17
- package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +15 -8
- package/dist/_dts/preview-next/src/client/preview/typographyFontCatalog.d.ts +57 -0
- package/dist/_dts/sdk/src/cli/commands/pull.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/commands/push/execute/theme.d.ts +4 -7
- package/dist/_dts/sdk/src/cli/commands/style.d.ts +24 -10
- package/dist/_dts/sdk/src/cli/site-commands/oneOffCommands.d.ts +3 -3
- package/dist/_dts/sdk/src/cli/sync/media.d.ts +16 -2
- package/dist/_dts/sdk/src/client/management/blocks.d.ts +1 -1
- package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
- package/dist/_dts/sdk/src/client/management/types.d.ts +132 -23
- package/dist/_dts/sdk/src/client/types.d.ts +2 -0
- package/dist/_dts/sdk/src/config/types.d.ts +1 -1
- package/dist/_dts/sdk/src/config/validation.d.ts +3 -0
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +23 -3
- package/dist/_dts/sdk/src/data/dataLoaderContext.d.ts +17 -0
- package/dist/_dts/sdk/src/data/dataLoaderValue.d.ts +36 -0
- package/dist/_dts/sdk/src/data/defineOwnDataProperty.d.ts +2 -0
- package/dist/_dts/sdk/src/data/executeCodeLoaders.d.ts +36 -40
- package/dist/_dts/sdk/src/data/index.d.ts +3 -3
- package/dist/_dts/sdk/src/data/resolveBlockData.d.ts +54 -0
- package/dist/_dts/sdk/src/data/types.d.ts +43 -78
- package/dist/_dts/sdk/src/next/index.d.ts +1 -0
- package/dist/_dts/sdk/src/next/redirect-destination.d.ts +1 -1
- package/dist/_dts/sdk/src/next/resolveTheme.d.ts +2 -1
- package/dist/_dts/sdk/src/next/types.d.ts +10 -1
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +3 -8
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +9 -4
- package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +6 -10
- package/dist/_dts/sdk/src/rendering/index.d.ts +1 -0
- package/dist/_dts/sdk/src/server.d.ts +4 -3
- package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/site-commands/src/capabilityGaps.d.ts +2 -2
- package/dist/_dts/site-commands/src/commands.d.ts +921 -30
- package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +5 -1
- package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
- package/dist/_dts/theme-core/src/buttons/personalities/quiet-arrow.d.ts +17 -0
- package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/buttons/types.d.ts +9 -5
- package/dist/_dts/theme-core/src/data.d.ts +12 -0
- package/dist/_dts/theme-core/src/fonts/index.d.ts +1 -1
- package/dist/_dts/theme-core/src/fonts/types.d.ts +6 -0
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +36 -24
- package/dist/_dts/theme-core/src/palette/colors.d.ts +12 -0
- package/dist/_dts/theme-core/src/palette/curated/brand-led.d.ts +10 -5
- package/dist/_dts/theme-core/src/palette/curated/high-contrast.d.ts +6 -3
- package/dist/_dts/theme-core/src/palette/curated/index.d.ts +31 -236
- package/dist/_dts/theme-core/src/palette/curated/soft-natural.d.ts +8 -4
- package/dist/_dts/theme-core/src/palette/curated/types.d.ts +14 -12
- package/dist/_dts/theme-core/src/palette/curated/warm-dark.d.ts +4 -2
- package/dist/_dts/theme-core/src/palette/curated/warm-neutral.d.ts +8 -4
- package/dist/_dts/theme-core/src/palette/editorState.d.ts +33 -3
- package/dist/_dts/theme-core/src/palette/index.d.ts +0 -4
- package/dist/_dts/theme-core/src/palette/libraryModel.d.ts +12 -6
- package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +20 -72
- package/dist/_dts/theme-core/src/palette/resolveSelection.d.ts +29 -4
- package/dist/_dts/theme-core/src/palette/selection.d.ts +6 -4
- package/dist/_dts/theme-core/src/schema.d.ts +121 -4
- package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +218 -158
- package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +5 -6
- package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +218 -158
- package/dist/_dts/theme-core/src/site-styles/compositionBudget.d.ts +1 -0
- package/dist/_dts/theme-core/src/site-styles/contentTemplateRuntimeCompiler.d.ts +2 -1
- package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +161 -51
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +6 -0
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -1
- package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +24 -1
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +14 -48
- package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +10 -23
- package/dist/_dts/theme-core/src/site-styles/siteStyleThemeCompiler.d.ts +1 -2
- package/dist/_dts/theme-core/src/site-styles/siteStyleTypography.d.ts +456 -0
- package/dist/_dts/theme-core/src/site-styles/types.d.ts +52 -3
- package/dist/cli/index.mjs +3155 -1701
- package/dist/client/{DiscountCodeDisclosure-BXM73_E5.mjs → DiscountCodeDisclosure-BwGkvmVH.mjs} +1 -1
- package/dist/client/{EventCombined.client-DT5elP7j.mjs → EventCombined.client-JnWE6Hzc.mjs} +3 -3
- package/dist/client/{EventListing.client-pTYGfV9C.mjs → EventListing.client-DQewc_kg.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-dQrhlUe3.mjs → LeafletStaticMap-DPAU3SFt.mjs} +1 -1
- package/dist/client/{MagicLinkForm-u6Dul4j5.mjs → MagicLinkForm-D4kpWCbW.mjs} +2 -2
- package/dist/client/{StepIndicator-nWqineJ2.mjs → StepIndicator-CBlkb4rA.mjs} +2 -2
- package/dist/client/{accordion-CSJcTUyH.mjs → accordion-DAIBVpTS.mjs} +1 -1
- package/dist/client/{bookingForm-C73wOuVa.mjs → bookingForm-DZ-4l5_1.mjs} +7 -7
- package/dist/client/bookings.mjs +239 -110
- package/dist/client/{buttons-DfYyqt8C.mjs → buttons-DJgynGHQ.mjs} +122 -58
- package/dist/client/{carousel-fMBb0JSc.mjs → carousel-D-SLfX8r.mjs} +1 -1
- package/dist/client/{cart-BtaCwT3S.mjs → cart-CEgbgJhX.mjs} +3 -3
- package/dist/client/{checkout-DkTwZSnh.mjs → checkout-CXWrCRAA.mjs} +3 -3
- package/dist/client/client.mjs +4300 -1560
- package/dist/client/{colorStyles-Wyl6JujD.mjs → colorStyles-jZS6KfkP.mjs} +1 -1
- package/dist/client/{colorTokenParts-dT8MISgJ.mjs → colorTokenParts-CMugwvX_.mjs} +3 -1
- package/dist/client/{courseRegistration-DnLmapJu.mjs → courseRegistration-DVmLrRVz.mjs} +56 -21
- package/dist/client/{eventCalendar-BvLOc9KY.mjs → eventCalendar-DCuyPY_c.mjs} +29 -21
- package/dist/client/{eventCombined-kShgJPQr.mjs → eventCombined-kP2CA2D4.mjs} +2 -2
- package/dist/client/{eventDetails-C5NTM0Vo.mjs → eventDetails-DU0LeF5e.mjs} +4 -4
- package/dist/client/{eventListing-B82ZdKP6.mjs → eventListing-CcHF87BI.mjs} +2 -2
- package/dist/client/{eventRegistration-qJVFqBWo.mjs → eventRegistration-DJnR0yFH.mjs} +8 -8
- package/dist/client/{form-BvAcKiuu.mjs → form-CH1lCusH.mjs} +2 -2
- package/dist/client/{headerSection-NvAiEHAg.mjs → headerSection-CBPFZoku.mjs} +3 -3
- package/dist/client/hooks.mjs +2958 -1848
- package/dist/client/{locationMap-D0j52xfI.mjs → locationMap-Cx1hBg5n.mjs} +3 -3
- package/dist/client/{media-BCW_g2cQ.mjs → media-DHtSxS5V.mjs} +61 -56
- package/dist/client/{newsletterForm-B8_i93qH.mjs → newsletterForm-1ZL_ti9u.mjs} +3 -3
- package/dist/client/{pricing-DIYnyHOk.mjs → pricing-BIbzmV0G.mjs} +1 -1
- package/dist/client/{productDetail-w0eAHkuQ.mjs → productDetail-BTh5gHBV.mjs} +3 -3
- package/dist/client/{productList-Vsguq5Xt.mjs → productList-Cc7OMrqN.mjs} +3 -3
- package/dist/client/{propsDecoder-CD2pJ1WB.mjs → propsDecoder-oR-M-ISN.mjs} +192 -59
- package/dist/client/rendering/client.mjs +2031 -1239
- package/dist/client/rendering/islands.mjs +20 -20
- package/dist/client/rendering.mjs +4889 -1712
- package/dist/client/{shop-Dgxs-Q8F.mjs → shop-CQ_YbCnn.mjs} +8 -8
- package/dist/client/{shop-commerce-DJAhsTaT.mjs → shop-commerce-BM-AoD3M.mjs} +6 -6
- package/dist/client/{shop-commerce-store-CfCXltXW.mjs → shop-commerce-store-DFMQhU5p.mjs} +1 -1
- package/dist/client/{shopShared-CmDcPXUt.mjs → shopShared-D0SKO2Cu.mjs} +3 -3
- package/dist/client/{useDiscountCodeUi-CirrT2bM.mjs → useDiscountCodeUi-CrG4_ARt.mjs} +1 -1
- package/dist/client/{useEventFilters-CNZxlCcO.mjs → useEventFilters-CxK8Fekl.mjs} +6 -6
- package/dist/client/{usePolling-Baks_iBI.mjs → usePolling-jcVryNgZ.mjs} +2 -2
- package/dist/preview-next/before-render.mjs +40 -1
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/middleware.mjs +40 -1
- package/dist/{previewAuthStore-CfquDtTh.mjs → previewAuthStore-BPcJPzdz.mjs} +40 -1
- package/dist/{sdk-runtime-BfNiFeNJ.mjs → sdk-runtime-C39Rsk-x.mjs} +2 -2
- package/dist/{separator-BhAR_Xmf.mjs → separator-BoMSQnsP.mjs} +1 -1
- package/dist/server/components.mjs +4661 -2162
- package/dist/server/config-validation.mjs +2728 -1847
- package/dist/server/config.mjs +2728 -1847
- package/dist/server/data.mjs +3381 -1915
- package/dist/server/index.mjs +46 -4
- package/dist/server/next/middleware.mjs +1 -1
- package/dist/server/next.mjs +5555 -2225
- package/dist/server/page-converter.mjs +3058 -2182
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +4850 -2125
- package/dist/server/rendering.mjs +5664 -2464
- package/dist/server/routing.mjs +3027 -1509
- package/dist/server/server.mjs +3844 -2217
- package/dist/server/theme-bridge.mjs +9121 -7765
- package/dist/server/theme.mjs +152 -59
- package/dist/styles/index.css +1217 -31
- package/package.json +1 -1
- package/dist/_dts/preview-next/src/client/preview/typographySelectionInput.d.ts +0 -16
- package/dist/_dts/theme-core/src/palette/historicalThemePalette.d.ts +0 -44
- package/dist/_dts/theme-core/src/palette/legacyRuntimeProjection.d.ts +0 -55
- package/dist/_dts/theme-core/src/palette/legacySelection.d.ts +0 -45
- package/dist/_dts/theme-core/src/palette/paletteCompatibilityTransition.d.ts +0 -232
- package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +0 -234
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { d as unwrapResponse, f as getDashboardUrl, r as usePreviewAuth } from "./previewAuthStore-
|
|
4
|
-
import { S as isAdapterReferenceKind, T as
|
|
5
|
-
import { t as Separator } from "./separator-
|
|
2
|
+
import { A as markApplySaved, B as previewHeaderStyle, Bl as Popover, C as committedPaletteForSnapshot, Cf as ChevronLeft, Cu as DropdownMenuTrigger, D as dismissWarnings, E as deriveStyleConfiguratorCapabilities, F as prepareStalePaletteRetry, Fd as Tablet, Fl as SelectTrigger, G as setPaletteColors, Gl as TabsContent, H as previewSiteStyle, Hl as PopoverTrigger, Hu as cn, I as previewButtonPersonality, Ii as getCuratedSiteStyle, Il as SelectValue, It as deriveRouteMetadataPresentation, J as toggleRow, Jd as Monitor, K as styleConfiguratorHistoryEntryForPersistedSelection, Kc as buttonPersonalities, Kl as TabsList, Kt as createManifestValidation, L as previewCuratedPalette, Lt as resolvePageRouteSlug, M as openRow, Ml as Select, N as paletteMutationCapability, Nl as SelectContent, O as isPreviewingChange, P as palettePreviewProjection, Pi as curatedSiteStyles, Pl as SelectItem, R as previewFooterLook, Rd as Smartphone, Rt as resolveContentTitle, S as cancelPreview, Sf as ChevronRight, St as useEditorUiStoreInstance, Su as DropdownMenuSeparator, T as createStyleConfiguratorState, Tf as Check, U as reconcilePaletteLibraryActive, Ul as Input, V as previewSitePalette, Vl as PopoverContent, W as resetTypographyToSaved, Wd as Plus, Wl as Tabs, Wt as ManifestForm, Xd as Maximize2, Yt as createStoreBackend, Zd as LoaderCircle, _ as usePreviewDesignCoordinator, _a as findCuratedPalette, _u as Surface, b as applyResolvedSelections, ba as paletteColorsEqual, bu as DropdownMenuItem, c as selectionSnapshotFromApplySiteStyleSelectionResponse, cu as CollapsibleTrigger, d as cycleSiteChromeLookId, ea as requireEntriesForCuratedChoices, f as cycleableSiteChromeOptions, ga as curatedPalettes, h as planSiteStylePreviewChange, ht as useUISelector, ia as getHeaderStyle, in as listEntryPageContentSlots, j as markApplySaving, k as markApplyFailed, kd as X$1, l as resolveStyleConfiguratorInitialSnapshot, m as planSiteChromeLookSelection, md as assertNever$1, mt as ContentFieldsForm, n as useSiteChromeCustomizeOptional, na as getFooterLayout, nt as resolvePreviewSidebarTab, ou as Collapsible, p as planSiteChromeFooterLayoutSelection, q as syncStyleConfiguratorState, qc as findButtonPersonality, ql as TabsTrigger, qt as FormRenderer, qu as unsafeAsEditorBlockId, ra as getHeaderLayout, s as buildApplySiteStyleSelectionBody, su as CollapsibleContent, ta as findFooterLook, tt as createOptimisticActionRunner, u as buildSiteChromeLookModels, va as buildPaletteLibraryReadModel, vt as useEntryController, vu as DropdownMenu, w as createPalette, x as applyTypographyDraftPatch, xa as paletteColorsSchema, xt as useEditorUiStore, xu as DropdownMenuLabel, ya as paletteColorEntries, yu as DropdownMenuContent, z as previewHeaderLayout, zd as SlidersHorizontal, zl as SearchInput, zu as Button } from "./SiteChromeCustomizeContext-C_sizso-.mjs";
|
|
3
|
+
import { d as unwrapResponse, f as getDashboardUrl, r as usePreviewAuth } from "./previewAuthStore-BPcJPzdz.mjs";
|
|
4
|
+
import { C as buildFontPreviewUrl, D as Callout, O as CalloutDescription, S as isAdapterReferenceKind, T as getSiteFontsStorageUrl, _ 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 generateFontFaceCss, x as BlockEditor, y as PreviewFormProvider } from "./SdkPreviewModeRuntime-CVB7urtl.mjs";
|
|
5
|
+
import { t as Separator } from "./separator-BoMSQnsP.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";
|
|
@@ -1564,7 +1564,7 @@ function formatBlockKindLabel(blockKind) {
|
|
|
1564
1564
|
}
|
|
1565
1565
|
//#endregion
|
|
1566
1566
|
//#region ../preview-next/src/client/preview/PageBlockEditorPanel.tsx
|
|
1567
|
-
function PageBlockEditorPanel({ siteId, pageId, dashboardBaseUrl, theme, apiClient, bearerToken, supabaseUrl, blockItems, uiStoreForBlockEditor, blockEditorRef, onBlocksChange, metadataPanel, linkedEntrySection, designPanel, designOpenRequestId = null, sdkConfig, mediaAssets, bookingOfferingPresets, viewportMode, viewportWidth, zoom, onViewportModeChange, onViewportWidthChange, onZoomChange }) {
|
|
1567
|
+
function PageBlockEditorPanel({ siteId, pageId, dashboardBaseUrl, theme, apiClient, bearerToken, supabaseUrl, blockItems, uiStoreForBlockEditor, blockEditorRef, onBlocksChange, metadataPanel, linkedEntrySection, designPanel, designOpenRequestId = null, designTakeoverActive = false, sdkConfig, mediaAssets, bookingOfferingPresets, viewportMode, viewportWidth, zoom, onViewportModeChange, onViewportWidthChange, onZoomChange }) {
|
|
1568
1568
|
const customizeSelection = usePreviewBlockCustomizeSelectionOptional();
|
|
1569
1569
|
const [designOpen, setDesignOpen] = useState(false);
|
|
1570
1570
|
const [customizeOpen, setCustomizeOpen] = useState(false);
|
|
@@ -1627,35 +1627,48 @@ function PageBlockEditorPanel({ siteId, pageId, dashboardBaseUrl, theme, apiClie
|
|
|
1627
1627
|
bookingOfferingPresets,
|
|
1628
1628
|
sdkConfig: sdkConfig ?? null,
|
|
1629
1629
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1630
|
-
className:
|
|
1630
|
+
className: `min-h-0 flex-1 space-y-0 ${designTakeoverActive ? "flex flex-col overflow-hidden" : "overflow-auto"}`,
|
|
1631
|
+
"data-design-takeover-active": designTakeoverActive ? "true" : "false",
|
|
1631
1632
|
children: [
|
|
1632
|
-
linkedEntrySection ? /* @__PURE__ */ jsx(
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
children:
|
|
1633
|
+
linkedEntrySection ? /* @__PURE__ */ jsx("div", {
|
|
1634
|
+
hidden: designTakeoverActive,
|
|
1635
|
+
"data-design-takeover-sibling": true,
|
|
1636
|
+
children: /* @__PURE__ */ jsx(PreviewSidebarSection, {
|
|
1637
|
+
label: linkedEntrySection.label,
|
|
1638
|
+
openRequestId: linkedEntrySection.openRequestId,
|
|
1639
|
+
children: linkedEntrySection.content
|
|
1640
|
+
})
|
|
1636
1641
|
}) : null,
|
|
1637
1642
|
designPanel ? /* @__PURE__ */ jsx(Collapsible, {
|
|
1638
|
-
|
|
1639
|
-
|
|
1643
|
+
className: designTakeoverActive ? "flex min-h-0 flex-1 flex-col overflow-hidden" : void 0,
|
|
1644
|
+
open: designTakeoverActive || designOpen,
|
|
1645
|
+
onOpenChange: (open) => {
|
|
1646
|
+
if (!designTakeoverActive) setDesignOpen(open);
|
|
1647
|
+
},
|
|
1640
1648
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1641
1649
|
ref: designSectionRef,
|
|
1642
|
-
className: "border-b",
|
|
1650
|
+
className: designTakeoverActive ? "flex min-h-0 flex-1 flex-col overflow-hidden" : "border-b",
|
|
1643
1651
|
children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
1644
1652
|
asChild: true,
|
|
1645
1653
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1646
|
-
className:
|
|
1647
|
-
children: [/* @__PURE__ */ jsx(ChevronRight, { className: `h-4 w-4 transition ${designOpen ? "rotate-90" : ""}` }), /* @__PURE__ */ jsx("span", {
|
|
1654
|
+
className: `flex shrink-0 cursor-pointer items-center gap-2 px-4 py-3 hover:bg-accent/40 ${designTakeoverActive ? "border-b" : ""}`,
|
|
1655
|
+
children: [/* @__PURE__ */ jsx(ChevronRight, { className: `h-4 w-4 transition ${designTakeoverActive || designOpen ? "rotate-90" : ""}` }), /* @__PURE__ */ jsx("span", {
|
|
1648
1656
|
className: "text-sm font-semibold",
|
|
1649
1657
|
children: "Design"
|
|
1650
1658
|
})]
|
|
1651
1659
|
})
|
|
1652
|
-
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
1653
|
-
className: "
|
|
1654
|
-
children:
|
|
1655
|
-
|
|
1660
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
1661
|
+
className: designTakeoverActive ? "min-h-0 flex-1 data-[state=open]:h-full data-[state=open]:overflow-hidden" : void 0,
|
|
1662
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1663
|
+
className: designTakeoverActive ? "h-full min-h-0" : "px-4 pb-4",
|
|
1664
|
+
children: designPanel
|
|
1665
|
+
})
|
|
1666
|
+
})]
|
|
1656
1667
|
})
|
|
1657
1668
|
}) : null,
|
|
1658
1669
|
/* @__PURE__ */ jsx(Collapsible, {
|
|
1670
|
+
hidden: designTakeoverActive,
|
|
1671
|
+
"data-design-takeover-sibling": true,
|
|
1659
1672
|
open: customizeOpen,
|
|
1660
1673
|
onOpenChange: setCustomizeOpen,
|
|
1661
1674
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -1682,6 +1695,8 @@ function PageBlockEditorPanel({ siteId, pageId, dashboardBaseUrl, theme, apiClie
|
|
|
1682
1695
|
})
|
|
1683
1696
|
}),
|
|
1684
1697
|
/* @__PURE__ */ jsx(Collapsible, {
|
|
1698
|
+
hidden: designTakeoverActive,
|
|
1699
|
+
"data-design-takeover-sibling": true,
|
|
1685
1700
|
open: contentOpen,
|
|
1686
1701
|
onOpenChange: setContentOpen,
|
|
1687
1702
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -1718,6 +1733,8 @@ function PageBlockEditorPanel({ siteId, pageId, dashboardBaseUrl, theme, apiClie
|
|
|
1718
1733
|
})
|
|
1719
1734
|
}),
|
|
1720
1735
|
metadataPanel ? /* @__PURE__ */ jsx(Collapsible, {
|
|
1736
|
+
hidden: designTakeoverActive,
|
|
1737
|
+
"data-design-takeover-sibling": true,
|
|
1721
1738
|
open: detailsOpen,
|
|
1722
1739
|
onOpenChange: setDetailsOpen,
|
|
1723
1740
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -2061,712 +2078,516 @@ function ContrastSwatch({ hex, label }) {
|
|
|
2061
2078
|
});
|
|
2062
2079
|
}
|
|
2063
2080
|
//#endregion
|
|
2064
|
-
//#region ../preview-next/src/client/preview/
|
|
2065
|
-
const
|
|
2066
|
-
const MAX_FONT_RESULTS_WHEN_BROWSING = 8;
|
|
2067
|
-
const PALETTE_BRAND_ROLES = [
|
|
2081
|
+
//#region ../preview-next/src/client/preview/typographyFontCatalog.ts
|
|
2082
|
+
const typographyFontCategories = [
|
|
2068
2083
|
{
|
|
2069
|
-
|
|
2070
|
-
label: "
|
|
2084
|
+
value: "all",
|
|
2085
|
+
label: "All"
|
|
2071
2086
|
},
|
|
2072
2087
|
{
|
|
2073
|
-
|
|
2074
|
-
label: "
|
|
2088
|
+
value: "sans-serif",
|
|
2089
|
+
label: "Sans"
|
|
2075
2090
|
},
|
|
2076
2091
|
{
|
|
2077
|
-
|
|
2078
|
-
label: "
|
|
2092
|
+
value: "serif",
|
|
2093
|
+
label: "Serif"
|
|
2079
2094
|
},
|
|
2080
2095
|
{
|
|
2081
|
-
|
|
2082
|
-
label: "
|
|
2083
|
-
}
|
|
2084
|
-
];
|
|
2085
|
-
const PALETTE_FEEDBACK_ROLES = [
|
|
2086
|
-
{
|
|
2087
|
-
key: "success",
|
|
2088
|
-
label: "Success"
|
|
2096
|
+
value: "display",
|
|
2097
|
+
label: "Display"
|
|
2089
2098
|
},
|
|
2090
2099
|
{
|
|
2091
|
-
|
|
2092
|
-
label: "
|
|
2100
|
+
value: "handwriting",
|
|
2101
|
+
label: "Handwriting"
|
|
2093
2102
|
},
|
|
2094
2103
|
{
|
|
2095
|
-
|
|
2096
|
-
label: "
|
|
2104
|
+
value: "monospace",
|
|
2105
|
+
label: "Mono"
|
|
2097
2106
|
}
|
|
2098
2107
|
];
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2108
|
+
function buildTypographyFontCatalog(input) {
|
|
2109
|
+
const normalizedQuery = input.query.trim().toLocaleLowerCase();
|
|
2110
|
+
const site = input.siteFonts.map(siteFontOption).filter((option) => fontOptionMatches(option, normalizedQuery, input.category)).sort(compareFontOptionsAlphabetically);
|
|
2111
|
+
const siteFamilies = new Set(input.siteFonts.map((font) => familyKey(font.familyName)));
|
|
2112
|
+
return {
|
|
2113
|
+
site,
|
|
2114
|
+
google: input.googleFonts.map(googleFontOption).filter((option) => !siteFamilies.has(familyKey(option.family))).filter((option) => fontOptionMatches(option, normalizedQuery, input.category)).sort(compareGoogleOptions)
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
function visibleTypographyFontOptions(input) {
|
|
2118
|
+
const initial = input.options.slice(0, input.limit);
|
|
2119
|
+
if (input.limit <= 0 || initial.some((option) => familyKey(option.family) === familyKey(input.selectedFamily))) return initial;
|
|
2120
|
+
const selected = input.options.find((option) => familyKey(option.family) === familyKey(input.selectedFamily));
|
|
2121
|
+
if (!selected) return initial;
|
|
2122
|
+
return [...initial.slice(0, Math.max(0, input.limit - 1)), selected];
|
|
2123
|
+
}
|
|
2124
|
+
function fontOptionForFamily(family, catalog) {
|
|
2125
|
+
const key = familyKey(primaryFontFamily(family));
|
|
2126
|
+
const site = catalog.siteFonts.find((font) => familyKey(font.familyName) === key);
|
|
2127
|
+
if (site) return siteFontOption(site);
|
|
2128
|
+
const google = catalog.googleFonts.find((font) => familyKey(font.family) === key);
|
|
2129
|
+
return google ? googleFontOption(google) : null;
|
|
2130
|
+
}
|
|
2131
|
+
function primaryFontFamily(cssFamily) {
|
|
2132
|
+
return cssFamily.split(",")[0]?.trim().replace(/^["']|["']$/gu, "") || cssFamily;
|
|
2133
|
+
}
|
|
2134
|
+
function siteFontOption(font) {
|
|
2135
|
+
return {
|
|
2136
|
+
source: "site",
|
|
2137
|
+
family: font.familyName,
|
|
2138
|
+
label: font.displayName ?? font.familyName,
|
|
2139
|
+
category: normalizeCategory(font.category),
|
|
2140
|
+
siteFont: font
|
|
2141
|
+
};
|
|
2142
|
+
}
|
|
2143
|
+
function googleFontOption(font) {
|
|
2144
|
+
return {
|
|
2145
|
+
source: "google",
|
|
2146
|
+
family: font.family,
|
|
2147
|
+
label: font.family,
|
|
2148
|
+
category: normalizeCategory(font.category),
|
|
2149
|
+
googleFont: font
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
function normalizeCategory(category) {
|
|
2153
|
+
switch (category) {
|
|
2154
|
+
case "sans-serif":
|
|
2155
|
+
case "serif":
|
|
2156
|
+
case "display":
|
|
2157
|
+
case "handwriting":
|
|
2158
|
+
case "monospace": return category;
|
|
2159
|
+
default: return null;
|
|
2123
2160
|
}
|
|
2124
|
-
|
|
2125
|
-
function
|
|
2126
|
-
const
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
]
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
const
|
|
2153
|
-
const
|
|
2154
|
-
const runnerRef = useRef(createOptimisticActionRunner());
|
|
2155
|
-
const appliedExpandedRowRequestIdRef = useRef(null);
|
|
2156
|
-
useEffect(() => {
|
|
2157
|
-
stateRef.current = state;
|
|
2158
|
-
}, [state]);
|
|
2159
|
-
useEffect(() => {
|
|
2160
|
-
clearPreviewRef.current = clearPreview;
|
|
2161
|
-
}, [clearPreview]);
|
|
2161
|
+
}
|
|
2162
|
+
function fontOptionMatches(option, normalizedQuery, category) {
|
|
2163
|
+
const matchesQuery = normalizedQuery.length === 0 || option.family.toLocaleLowerCase().includes(normalizedQuery) || option.label.toLocaleLowerCase().includes(normalizedQuery);
|
|
2164
|
+
const matchesCategory = category === "all" || option.category === category;
|
|
2165
|
+
return matchesQuery && matchesCategory;
|
|
2166
|
+
}
|
|
2167
|
+
function compareGoogleOptions(left, right) {
|
|
2168
|
+
if (left.source !== "google" || right.source !== "google") return compareFontOptionsAlphabetically(left, right);
|
|
2169
|
+
return (left.googleFont.popularity ?? Number.POSITIVE_INFINITY) - (right.googleFont.popularity ?? Number.POSITIVE_INFINITY) || compareFontOptionsAlphabetically(left, right);
|
|
2170
|
+
}
|
|
2171
|
+
function compareFontOptionsAlphabetically(left, right) {
|
|
2172
|
+
return left.label.localeCompare(right.label);
|
|
2173
|
+
}
|
|
2174
|
+
function familyKey(family) {
|
|
2175
|
+
return family.trim().toLocaleLowerCase();
|
|
2176
|
+
}
|
|
2177
|
+
//#endregion
|
|
2178
|
+
//#region ../preview-next/src/client/preview/StyleConfigurator.typography.tsx
|
|
2179
|
+
const typographyOverviewSurface = { kind: "overview" };
|
|
2180
|
+
function useTypographyFontCatalog(apiClient, siteId, enabled) {
|
|
2181
|
+
const [google, setGoogle] = useState({
|
|
2182
|
+
kind: "idle",
|
|
2183
|
+
value: []
|
|
2184
|
+
});
|
|
2185
|
+
const [site, setSite] = useState({
|
|
2186
|
+
kind: "idle",
|
|
2187
|
+
value: []
|
|
2188
|
+
});
|
|
2189
|
+
const googleRequestRef = useRef(null);
|
|
2190
|
+
const siteRequestRef = useRef(null);
|
|
2162
2191
|
useEffect(() => {
|
|
2163
|
-
if (!
|
|
2164
|
-
|
|
2192
|
+
if (!enabled) return;
|
|
2193
|
+
if (googleRequestRef.current?.apiClient === apiClient) return;
|
|
2194
|
+
let cancelled = false;
|
|
2195
|
+
googleRequestRef.current = {
|
|
2196
|
+
apiClient,
|
|
2197
|
+
status: "loading"
|
|
2198
|
+
};
|
|
2199
|
+
setGoogle((current) => ({
|
|
2200
|
+
kind: "loading",
|
|
2201
|
+
value: current.value
|
|
2202
|
+
}));
|
|
2203
|
+
async function loadGoogleFonts() {
|
|
2204
|
+
try {
|
|
2205
|
+
const value = unwrapResponse(await apiClient({ endpoint: "listFonts" }));
|
|
2206
|
+
if (!cancelled) {
|
|
2207
|
+
googleRequestRef.current = {
|
|
2208
|
+
apiClient,
|
|
2209
|
+
status: "loaded"
|
|
2210
|
+
};
|
|
2211
|
+
setGoogle({
|
|
2212
|
+
kind: "loaded",
|
|
2213
|
+
value: Array.isArray(value) ? value : []
|
|
2214
|
+
});
|
|
2215
|
+
}
|
|
2216
|
+
} catch (error) {
|
|
2217
|
+
if (!cancelled) {
|
|
2218
|
+
googleRequestRef.current = null;
|
|
2219
|
+
setGoogle({
|
|
2220
|
+
kind: "failed",
|
|
2221
|
+
value: [],
|
|
2222
|
+
message: errorMessage(error, "Unable to load Google Fonts.")
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
loadGoogleFonts();
|
|
2165
2228
|
return () => {
|
|
2166
|
-
|
|
2229
|
+
cancelled = true;
|
|
2230
|
+
if (googleRequestRef.current?.status === "loading") googleRequestRef.current = null;
|
|
2167
2231
|
};
|
|
2168
|
-
}, [
|
|
2169
|
-
useEffect(() => {
|
|
2170
|
-
if (!baseSnapshot) return;
|
|
2171
|
-
setState((current) => current ? syncStyleConfiguratorState(current, baseSnapshot) : createStyleConfiguratorState(baseSnapshot));
|
|
2172
|
-
}, [baseSnapshot]);
|
|
2232
|
+
}, [apiClient, enabled]);
|
|
2173
2233
|
useEffect(() => {
|
|
2174
|
-
if (!
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2234
|
+
if (!enabled) return;
|
|
2235
|
+
if (siteRequestRef.current?.apiClient === apiClient && siteRequestRef.current.siteId === siteId) return;
|
|
2236
|
+
let cancelled = false;
|
|
2237
|
+
siteRequestRef.current = {
|
|
2238
|
+
apiClient,
|
|
2239
|
+
siteId,
|
|
2240
|
+
status: "loading"
|
|
2241
|
+
};
|
|
2242
|
+
setSite((current) => ({
|
|
2243
|
+
kind: "loading",
|
|
2244
|
+
value: current.value
|
|
2245
|
+
}));
|
|
2246
|
+
async function loadSiteFonts() {
|
|
2247
|
+
try {
|
|
2248
|
+
const value = unwrapResponse(await apiClient({
|
|
2249
|
+
endpoint: "listSiteFonts",
|
|
2250
|
+
params: { siteId }
|
|
2251
|
+
}));
|
|
2252
|
+
if (!cancelled) {
|
|
2253
|
+
siteRequestRef.current = {
|
|
2254
|
+
apiClient,
|
|
2255
|
+
siteId,
|
|
2256
|
+
status: "loaded"
|
|
2257
|
+
};
|
|
2258
|
+
setSite({
|
|
2259
|
+
kind: "loaded",
|
|
2260
|
+
value: Array.isArray(value?.fonts) ? value.fonts : []
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
} catch (error) {
|
|
2264
|
+
if (!cancelled) {
|
|
2265
|
+
siteRequestRef.current = null;
|
|
2266
|
+
setSite({
|
|
2267
|
+
kind: "failed",
|
|
2268
|
+
value: [],
|
|
2269
|
+
message: errorMessage(error, "Unable to load your fonts.")
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2186
2273
|
}
|
|
2187
|
-
|
|
2188
|
-
siteStyle,
|
|
2189
|
-
selection: state.previewed,
|
|
2190
|
-
baseTheme: theme,
|
|
2191
|
-
headerSelectionContext,
|
|
2192
|
-
footerSelectionContext
|
|
2193
|
-
}).themeOverlay, "site-style");
|
|
2194
|
-
}, [
|
|
2195
|
-
state,
|
|
2196
|
-
baseSnapshot,
|
|
2197
|
-
clearPreview,
|
|
2198
|
-
previewTheme,
|
|
2199
|
-
headerSelectionContext,
|
|
2200
|
-
footerSelectionContext,
|
|
2201
|
-
theme
|
|
2202
|
-
]);
|
|
2203
|
-
useEffect(() => {
|
|
2204
|
-
const runner = runnerRef.current;
|
|
2274
|
+
loadSiteFonts();
|
|
2205
2275
|
return () => {
|
|
2206
|
-
|
|
2207
|
-
|
|
2276
|
+
cancelled = true;
|
|
2277
|
+
if (siteRequestRef.current?.status === "loading") siteRequestRef.current = null;
|
|
2208
2278
|
};
|
|
2209
|
-
}, []);
|
|
2210
|
-
useEffect(() => {
|
|
2211
|
-
if (!expandedRowRequest) return;
|
|
2212
|
-
if (appliedExpandedRowRequestIdRef.current === expandedRowRequest.id) return;
|
|
2213
|
-
setState((current) => {
|
|
2214
|
-
if (!current) return current;
|
|
2215
|
-
appliedExpandedRowRequestIdRef.current = expandedRowRequest.id;
|
|
2216
|
-
return openRow(current, expandedRowForPreviewDesignRow(expandedRowRequest.row));
|
|
2217
|
-
});
|
|
2218
|
-
}, [expandedRowRequest, hasLoadedState]);
|
|
2219
|
-
const handlePreviewSiteStyle = useCallback((siteStyleId) => {
|
|
2220
|
-
setState((current) => {
|
|
2221
|
-
if (!current) return current;
|
|
2222
|
-
const next = previewSiteStyle(current, siteStyleId);
|
|
2223
|
-
const siteStyle = getCuratedSiteStyle(siteStyleId);
|
|
2224
|
-
if (!siteStyle) return next;
|
|
2225
|
-
const result = planSiteStylePreviewChange({
|
|
2226
|
-
siteStyle,
|
|
2227
|
-
selection: next.previewed,
|
|
2228
|
-
baseTheme: theme,
|
|
2229
|
-
headerSelectionContext,
|
|
2230
|
-
footerSelectionContext
|
|
2231
|
-
});
|
|
2232
|
-
return applyResolvedSelections(next, {
|
|
2233
|
-
resolved: result.resolvedSelections,
|
|
2234
|
-
...result.resolvedSelections.typographySelection.kind === "custom" ? { typographySelection: {
|
|
2235
|
-
kind: "custom",
|
|
2236
|
-
typography: result.themeOverlay.typography
|
|
2237
|
-
} } : {},
|
|
2238
|
-
warnings: result.warnings
|
|
2239
|
-
});
|
|
2240
|
-
});
|
|
2241
2279
|
}, [
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2280
|
+
apiClient,
|
|
2281
|
+
enabled,
|
|
2282
|
+
siteId
|
|
2245
2283
|
]);
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
}, []);
|
|
2253
|
-
const handlePreviewHeaderStyle = useCallback((id) => {
|
|
2254
|
-
if (!id) return;
|
|
2255
|
-
setState((current) => current ? previewHeaderStyle(current, id) : current);
|
|
2256
|
-
}, []);
|
|
2257
|
-
const handlePreviewFooterLook = useCallback((id) => {
|
|
2258
|
-
const plan = planSiteChromeLookSelection({
|
|
2259
|
-
surface: "footer",
|
|
2260
|
-
lookId: id
|
|
2261
|
-
});
|
|
2262
|
-
if (plan.kind !== "footer") return;
|
|
2263
|
-
setState((current) => current ? previewFooterLook(current, plan.next.footerLookId) : current);
|
|
2264
|
-
}, []);
|
|
2265
|
-
const handlePreviewFooterLayout = useCallback((id) => {
|
|
2266
|
-
if (!id) return;
|
|
2267
|
-
setState((current) => {
|
|
2268
|
-
if (!current) return current;
|
|
2269
|
-
const siteStyle = getCuratedSiteStyle(current.previewed.siteStyleId);
|
|
2270
|
-
if (!siteStyle) return current;
|
|
2271
|
-
const models = buildSiteChromeLookModels({
|
|
2272
|
-
state: current,
|
|
2273
|
-
siteStyle,
|
|
2274
|
-
headerSelectionContext,
|
|
2275
|
-
footerSelectionContext
|
|
2276
|
-
});
|
|
2277
|
-
const nextLookId = planSiteChromeFooterLayoutSelection({
|
|
2278
|
-
layoutId: id,
|
|
2279
|
-
currentLookId: current.previewed.footerLookId ?? models.footer.renderedLookId
|
|
2280
|
-
});
|
|
2281
|
-
return nextLookId ? previewFooterLook(current, nextLookId) : current;
|
|
2282
|
-
});
|
|
2283
|
-
}, [footerSelectionContext, headerSelectionContext]);
|
|
2284
|
-
const handlePreviewPalette = useCallback((id) => {
|
|
2285
|
-
const curated = findCuratedPalette(id);
|
|
2286
|
-
if (!curated) return;
|
|
2287
|
-
setState((current) => current ? previewCuratedPalette(current, {
|
|
2288
|
-
paletteId: curated.id,
|
|
2289
|
-
colors: curated.colors,
|
|
2290
|
-
mode: curated.mode
|
|
2291
|
-
}) : current);
|
|
2292
|
-
}, []);
|
|
2293
|
-
const handlePreviewTypographyPreset = useCallback((id) => {
|
|
2294
|
-
setState((current) => current ? previewTypographyPreset(current, id) : current);
|
|
2295
|
-
}, []);
|
|
2296
|
-
const patchTypography = useCallback((patch) => {
|
|
2297
|
-
setState((current) => {
|
|
2298
|
-
if (!current) return current;
|
|
2299
|
-
const siteStyle = getCuratedSiteStyle(current.previewed.siteStyleId);
|
|
2300
|
-
if (!siteStyle) return current;
|
|
2301
|
-
return applyTypographyDraftPatch(current, planSiteStylePreviewChange({
|
|
2302
|
-
siteStyle,
|
|
2303
|
-
selection: current.previewed,
|
|
2304
|
-
baseTheme: theme,
|
|
2305
|
-
headerSelectionContext,
|
|
2306
|
-
footerSelectionContext
|
|
2307
|
-
}).themeOverlay.typography, patch);
|
|
2308
|
-
});
|
|
2309
|
-
}, [
|
|
2310
|
-
footerSelectionContext,
|
|
2311
|
-
headerSelectionContext,
|
|
2312
|
-
theme
|
|
2313
|
-
]);
|
|
2314
|
-
const handleHeadingTypographyChange = useCallback((patch) => {
|
|
2315
|
-
patchTypography({
|
|
2316
|
-
kind: "heading",
|
|
2317
|
-
patch
|
|
2318
|
-
});
|
|
2319
|
-
}, [patchTypography]);
|
|
2320
|
-
const handleBodyTypographyChange = useCallback((patch) => {
|
|
2321
|
-
patchTypography({
|
|
2322
|
-
kind: "body",
|
|
2323
|
-
patch
|
|
2324
|
-
});
|
|
2325
|
-
}, [patchTypography]);
|
|
2326
|
-
const handleTypographyScaleChange = useCallback((scale) => {
|
|
2327
|
-
patchTypography({
|
|
2328
|
-
kind: "scale",
|
|
2329
|
-
scale
|
|
2330
|
-
});
|
|
2331
|
-
}, [patchTypography]);
|
|
2332
|
-
const handleResetTypography = useCallback(() => {
|
|
2333
|
-
setState((current) => current ? resetTypographyToSaved(current) : current);
|
|
2334
|
-
}, []);
|
|
2335
|
-
const handleTokenOverride = useCallback((role, hex) => {
|
|
2336
|
-
setState((current) => {
|
|
2337
|
-
if (!current) return current;
|
|
2338
|
-
const palette = current.previewed.palette;
|
|
2339
|
-
if (palette.kind === "invalid") return current;
|
|
2340
|
-
if (!(role in palette.colors)) return current;
|
|
2341
|
-
const nextColors = paletteColorsSchema.safeParse({
|
|
2342
|
-
...palette.colors,
|
|
2343
|
-
[role]: hex
|
|
2344
|
-
});
|
|
2345
|
-
return nextColors.success ? setPaletteColors(current, nextColors.data) : current;
|
|
2346
|
-
});
|
|
2347
|
-
}, []);
|
|
2348
|
-
const handleResetOverrides = useCallback(() => {
|
|
2349
|
-
setState((current) => {
|
|
2350
|
-
if (!current || current.previewed.palette.kind !== "migrated-curated") return current;
|
|
2351
|
-
const curated = findCuratedPalette(current.previewed.palette.paletteId);
|
|
2352
|
-
return curated ? setPaletteColors(current, curated.colors) : current;
|
|
2353
|
-
});
|
|
2354
|
-
}, []);
|
|
2355
|
-
const handleToggleRow = useCallback((row) => {
|
|
2356
|
-
setState((current) => current ? toggleRow(current, row) : current);
|
|
2357
|
-
}, []);
|
|
2358
|
-
const handleCancel = useCallback(() => {
|
|
2359
|
-
setState((current) => current ? cancelPreview(current) : current);
|
|
2360
|
-
}, []);
|
|
2361
|
-
const handleDismissWarnings = useCallback(() => {
|
|
2362
|
-
setState((current) => current ? dismissWarnings(current) : current);
|
|
2363
|
-
}, []);
|
|
2364
|
-
const handleApply = useCallback(async () => {
|
|
2365
|
-
const live = stateRef.current;
|
|
2366
|
-
if (!live || !isPreviewingChange(live)) return;
|
|
2367
|
-
if (!deriveStyleConfiguratorCapabilities(live).canApplyStaged) return;
|
|
2368
|
-
const previewed = live.previewed;
|
|
2369
|
-
const siteStyle = getCuratedSiteStyle(previewed.siteStyleId);
|
|
2370
|
-
if (!siteStyle) return;
|
|
2371
|
-
const compiled = planSiteStylePreviewChange({
|
|
2372
|
-
siteStyle,
|
|
2373
|
-
selection: previewed,
|
|
2374
|
-
baseTheme: theme,
|
|
2375
|
-
headerSelectionContext,
|
|
2376
|
-
footerSelectionContext
|
|
2377
|
-
});
|
|
2378
|
-
await runnerRef.current.run({
|
|
2379
|
-
optimistic: () => {
|
|
2380
|
-
applyStarted("style-configurator");
|
|
2381
|
-
setState((current) => current ? markApplySaving(current) : current);
|
|
2382
|
-
},
|
|
2383
|
-
network: async () => {
|
|
2384
|
-
const body = buildApplySiteStyleSelectionBody({
|
|
2385
|
-
base: live.base,
|
|
2386
|
-
previewed: {
|
|
2387
|
-
...previewed,
|
|
2388
|
-
buttonPersonalityId: compiled.resolvedSelections.buttonPersonalityId,
|
|
2389
|
-
headerLayoutId: compiled.resolvedSelections.headerLayoutId,
|
|
2390
|
-
headerStyleId: compiled.resolvedSelections.headerStyleId,
|
|
2391
|
-
headerLookId: compiled.resolvedSelections.headerLookId,
|
|
2392
|
-
typographySelection: compiled.resolvedSelections.typographySelection.kind === "custom" ? {
|
|
2393
|
-
kind: "custom",
|
|
2394
|
-
typography: compiled.themeOverlay.typography
|
|
2395
|
-
} : typographySelectionSnapshotFromFlat(compiled.resolvedSelections)
|
|
2396
|
-
},
|
|
2397
|
-
selectionId
|
|
2398
|
-
});
|
|
2399
|
-
if (!body.ok) throw new Error(paletteApplyPlanErrorMessage(body.error));
|
|
2400
|
-
return unwrapResponse(await apiClient({
|
|
2401
|
-
endpoint: "applySiteStyleSelection",
|
|
2402
|
-
params: { siteId },
|
|
2403
|
-
body: body.body
|
|
2404
|
-
}));
|
|
2405
|
-
},
|
|
2406
|
-
onSuccess: (saved) => {
|
|
2407
|
-
const persisted = selectionSnapshotFromApplySiteStyleSelectionResponse(saved, previewed);
|
|
2408
|
-
const historyEntry = styleConfiguratorHistoryEntryForPersistedSelection(live, persisted);
|
|
2409
|
-
setState((current) => current ? markApplySaved(current, persisted) : current);
|
|
2410
|
-
if (historyEntry) siteChromeCustomize?.siteStyleHistory?.recordAppliedSelection(historyEntry);
|
|
2411
|
-
applySucceeded("style-configurator");
|
|
2412
|
-
startRefreshTransition(() => {
|
|
2413
|
-
router.refresh();
|
|
2414
|
-
});
|
|
2415
|
-
},
|
|
2416
|
-
onError: (error) => {
|
|
2417
|
-
applyFailed("style-configurator");
|
|
2418
|
-
const applyError = classifyStyleApplyError(error);
|
|
2419
|
-
if (applyError.kind === "stale") startRefreshTransition(() => {
|
|
2420
|
-
router.refresh();
|
|
2421
|
-
});
|
|
2422
|
-
const message = applyError.message;
|
|
2423
|
-
setState((current) => current ? markApplyFailed(current, message, applyError.kind === "stale" ? "stale" : "retryable") : current);
|
|
2424
|
-
}
|
|
2425
|
-
});
|
|
2426
|
-
}, [
|
|
2427
|
-
apiClient,
|
|
2428
|
-
footerSelectionContext,
|
|
2429
|
-
headerSelectionContext,
|
|
2430
|
-
applyFailed,
|
|
2431
|
-
applyStarted,
|
|
2432
|
-
applySucceeded,
|
|
2433
|
-
router,
|
|
2434
|
-
selectionId,
|
|
2435
|
-
siteChromeCustomize?.siteStyleHistory,
|
|
2436
|
-
siteId,
|
|
2437
|
-
startRefreshTransition,
|
|
2438
|
-
theme
|
|
2439
|
-
]);
|
|
2440
|
-
if (!state || !baseSnapshot) return /* @__PURE__ */ jsx("p", {
|
|
2441
|
-
className: "text-sm text-muted-foreground",
|
|
2442
|
-
children: "Loading design controls..."
|
|
2443
|
-
});
|
|
2444
|
-
const applyAllowed = canApplySiteStyle(siteStyleAccess);
|
|
2445
|
-
const stagedCapabilities = deriveStyleConfiguratorCapabilities(state);
|
|
2446
|
-
const previewingChange = isPreviewingChange(state);
|
|
2447
|
-
const saving = stagedCapabilities.isApplyingStaged || isRefreshPending;
|
|
2448
|
-
const aggregateMutationControlsDisabled = saving || !stagedCapabilities.canPreviewStaged;
|
|
2449
|
-
const currentSiteStyle = getCuratedSiteStyle(state.previewed.siteStyleId);
|
|
2450
|
-
if (!currentSiteStyle) return /* @__PURE__ */ jsx("p", {
|
|
2451
|
-
className: "text-sm text-muted-foreground",
|
|
2452
|
-
children: "This site uses a Site Style that cannot be configured here."
|
|
2453
|
-
});
|
|
2454
|
-
const currentPersonality = findButtonPersonality(state.previewed.buttonPersonalityId);
|
|
2455
|
-
const currentPalette = state.previewed.palette;
|
|
2456
|
-
const paletteMutation = paletteMutationCapability(state);
|
|
2457
|
-
const paletteControlsDisabled = saving || paletteMutation.kind !== "editable";
|
|
2458
|
-
const currentCuratedPalette = currentPalette.kind === "migrated-curated" ? findCuratedPalette(currentPalette.paletteId) : null;
|
|
2459
|
-
const currentTypographyPreset = state.previewed.typographySelection.kind === "preset" && state.previewed.typographySelection.presetId ? findTypographyPreset(state.previewed.typographySelection.presetId) : null;
|
|
2460
|
-
const currentTypography = planSiteStylePreviewChange({
|
|
2461
|
-
siteStyle: currentSiteStyle,
|
|
2462
|
-
selection: state.previewed,
|
|
2463
|
-
baseTheme: theme,
|
|
2464
|
-
headerSelectionContext,
|
|
2465
|
-
footerSelectionContext
|
|
2466
|
-
}).themeOverlay.typography;
|
|
2467
|
-
const chromeLookModels = buildSiteChromeLookModels({
|
|
2468
|
-
state,
|
|
2469
|
-
siteStyle: currentSiteStyle,
|
|
2470
|
-
headerSelectionContext,
|
|
2471
|
-
footerSelectionContext
|
|
2472
|
-
});
|
|
2473
|
-
const currentHeaderLayout = getHeaderLayout(state.previewed.headerLayoutId);
|
|
2474
|
-
const currentHeaderStyle = getHeaderStyle(state.previewed.headerStyleId);
|
|
2475
|
-
const currentFooterLayout = getFooterLayout(chromeLookModels.footerLayout.renderedLayoutId);
|
|
2476
|
-
const currentFooterLook = state.previewed.footerLookId ? findFooterLook(state.previewed.footerLookId) : findFooterLook(chromeLookModels.footer.renderedLookId);
|
|
2477
|
-
const headerSurfaceState = siteChromeCustomize?.getSurfaceState("header") ?? { kind: "unavailable" };
|
|
2284
|
+
return {
|
|
2285
|
+
google,
|
|
2286
|
+
site
|
|
2287
|
+
};
|
|
2288
|
+
}
|
|
2289
|
+
function TypographyOverviewContent({ typography, catalog, onChooseFont, onOpenAdvanced, onReset, disabled }) {
|
|
2478
2290
|
return /* @__PURE__ */ jsxs("div", {
|
|
2479
2291
|
className: "space-y-3",
|
|
2480
2292
|
children: [
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2293
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2294
|
+
className: "space-y-2",
|
|
2295
|
+
children: [/* @__PURE__ */ jsx(TypographyRoleSummary, {
|
|
2296
|
+
slot: "heading",
|
|
2297
|
+
family: typography.headings.default.family,
|
|
2298
|
+
catalog,
|
|
2299
|
+
onChoose: () => onChooseFont("heading"),
|
|
2300
|
+
disabled
|
|
2301
|
+
}), /* @__PURE__ */ jsx(TypographyRoleSummary, {
|
|
2302
|
+
slot: "body",
|
|
2303
|
+
family: typography.body.family,
|
|
2304
|
+
catalog,
|
|
2305
|
+
onChoose: () => onChooseFont("body"),
|
|
2306
|
+
disabled
|
|
2307
|
+
})]
|
|
2491
2308
|
}),
|
|
2492
|
-
/* @__PURE__ */
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2309
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2310
|
+
className: "flex items-center gap-2 border-t pt-3",
|
|
2311
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
2312
|
+
type: "button",
|
|
2313
|
+
size: "sm",
|
|
2314
|
+
variant: "outline",
|
|
2315
|
+
className: "flex-1 justify-between",
|
|
2316
|
+
onClick: onOpenAdvanced,
|
|
2317
|
+
disabled,
|
|
2318
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
2319
|
+
className: "inline-flex items-center gap-2",
|
|
2320
|
+
children: [/* @__PURE__ */ jsx(SlidersHorizontal, {
|
|
2321
|
+
className: "h-3.5 w-3.5",
|
|
2322
|
+
"aria-hidden": "true"
|
|
2323
|
+
}), "Advanced typography"]
|
|
2324
|
+
}), /* @__PURE__ */ jsx(ChevronRight, {
|
|
2325
|
+
className: "h-3.5 w-3.5",
|
|
2326
|
+
"aria-hidden": "true"
|
|
2327
|
+
})]
|
|
2328
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2329
|
+
type: "button",
|
|
2330
|
+
size: "sm",
|
|
2331
|
+
variant: "ghost",
|
|
2332
|
+
onClick: onReset,
|
|
2333
|
+
disabled,
|
|
2334
|
+
children: "Reset"
|
|
2335
|
+
})]
|
|
2509
2336
|
}),
|
|
2510
|
-
/* @__PURE__ */ jsx(
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2337
|
+
/* @__PURE__ */ jsx(SiteFontFaceStyles, { siteFonts: catalog.site.value })
|
|
2338
|
+
]
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
function TypographyRoleSummary({ slot, family, catalog, onChoose, disabled }) {
|
|
2342
|
+
const primaryFamily = primaryFontFamily(family);
|
|
2343
|
+
const option = fontOptionForFamily(primaryFamily, {
|
|
2344
|
+
googleFonts: catalog.google.value,
|
|
2345
|
+
siteFonts: catalog.site.value
|
|
2346
|
+
});
|
|
2347
|
+
const label = slot === "heading" ? "Heading" : "Body";
|
|
2348
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
2349
|
+
type: "button",
|
|
2350
|
+
className: "group flex w-full items-center gap-3 rounded-md border bg-background px-3 py-3 text-left transition hover:border-foreground/30 hover:bg-accent/20 disabled:cursor-not-allowed disabled:opacity-50",
|
|
2351
|
+
"aria-label": `Choose ${label.toLocaleLowerCase()} font, currently ${primaryFamily}`,
|
|
2352
|
+
onClick: onChoose,
|
|
2353
|
+
disabled,
|
|
2354
|
+
children: [
|
|
2355
|
+
/* @__PURE__ */ jsx(FontPreviewText, {
|
|
2356
|
+
family: primaryFamily,
|
|
2357
|
+
source: option?.source ?? "unknown",
|
|
2358
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-muted/70 text-xl",
|
|
2359
|
+
children: slot === "heading" ? "Hh" : "Aa"
|
|
2533
2360
|
}),
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
onCycle: (direction) => {
|
|
2546
|
-
const next = cycleSiteChromeLookId(chromeLookModels.footerLayout.options, chromeLookModels.footerLayout.renderedLayoutId, direction);
|
|
2547
|
-
if (next !== void 0) handlePreviewFooterLayout(next);
|
|
2548
|
-
},
|
|
2549
|
-
onPreview: handlePreviewFooterLayout,
|
|
2550
|
-
disabled: aggregateMutationControlsDisabled
|
|
2551
|
-
}),
|
|
2552
|
-
/* @__PURE__ */ jsx(SiteChromeLookRow, {
|
|
2553
|
-
label: "Footer look",
|
|
2554
|
-
ariaLabel: "Footer look",
|
|
2555
|
-
defaultDescription: "Use the footer look chosen for this site style.",
|
|
2556
|
-
expanded: state.expandedRow === "footer",
|
|
2557
|
-
onToggle: () => handleToggleRow("footer"),
|
|
2558
|
-
currentId: state.previewed.footerLookId,
|
|
2559
|
-
currentLabel: state.previewed.footerLookId ? currentFooterLook?.label ?? "Unknown footer Look" : `${currentFooterLook?.label ?? "Site style"} (default)`,
|
|
2560
|
-
scopeDescription: "Changes the footer on every page.",
|
|
2561
|
-
options: chromeLookModels.footer.options,
|
|
2562
|
-
diagnostics: chromeLookModels.footer.diagnostics,
|
|
2563
|
-
onCycle: (direction) => {
|
|
2564
|
-
const next = cycleSiteChromeLookId(chromeLookModels.footer.options, state.previewed.footerLookId, direction);
|
|
2565
|
-
if (next !== void 0) handlePreviewFooterLook(next);
|
|
2566
|
-
},
|
|
2567
|
-
onPreview: handlePreviewFooterLook,
|
|
2568
|
-
disabled: aggregateMutationControlsDisabled
|
|
2569
|
-
}),
|
|
2570
|
-
/* @__PURE__ */ jsx(PersonalityRow, {
|
|
2571
|
-
expanded: state.expandedRow === "buttons",
|
|
2572
|
-
onToggle: () => handleToggleRow("buttons"),
|
|
2573
|
-
siteStyle: currentSiteStyle,
|
|
2574
|
-
currentId: state.previewed.buttonPersonalityId,
|
|
2575
|
-
currentLabel: currentPersonality?.name ?? state.previewed.buttonPersonalityId,
|
|
2576
|
-
onPreview: handlePreviewPersonality,
|
|
2577
|
-
disabled: aggregateMutationControlsDisabled
|
|
2361
|
+
/* @__PURE__ */ jsxs("span", {
|
|
2362
|
+
className: "min-w-0 flex-1",
|
|
2363
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2364
|
+
className: "block text-xs font-medium text-muted-foreground",
|
|
2365
|
+
children: label
|
|
2366
|
+
}), /* @__PURE__ */ jsx(FontPreviewText, {
|
|
2367
|
+
family: primaryFamily,
|
|
2368
|
+
source: option?.source ?? "unknown",
|
|
2369
|
+
className: "block truncate text-base",
|
|
2370
|
+
children: primaryFamily
|
|
2371
|
+
})]
|
|
2578
2372
|
}),
|
|
2579
|
-
/* @__PURE__ */ jsx(
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2373
|
+
/* @__PURE__ */ jsx(ChevronRight, {
|
|
2374
|
+
className: "h-4 w-4 shrink-0 text-muted-foreground transition group-hover:text-foreground",
|
|
2375
|
+
"aria-hidden": "true"
|
|
2376
|
+
})
|
|
2377
|
+
]
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
function TypographyFontPickerTakeover({ slot, value, catalog, onBack, onChange, disabled }) {
|
|
2381
|
+
const [query, setQuery] = useState("");
|
|
2382
|
+
const [category, setCategory] = useState("all");
|
|
2383
|
+
const [visibleGoogleCount, setVisibleGoogleCount] = useState(24);
|
|
2384
|
+
const selectedFamily = primaryFontFamily(value);
|
|
2385
|
+
const catalogResult = useMemo(() => buildTypographyFontCatalog({
|
|
2386
|
+
googleFonts: catalog.google.value,
|
|
2387
|
+
siteFonts: catalog.site.value,
|
|
2388
|
+
query,
|
|
2389
|
+
category
|
|
2390
|
+
}), [
|
|
2391
|
+
catalog.google.value,
|
|
2392
|
+
catalog.site.value,
|
|
2393
|
+
category,
|
|
2394
|
+
query
|
|
2395
|
+
]);
|
|
2396
|
+
const searching = query.trim().length > 0;
|
|
2397
|
+
const visibleGoogle = searching ? catalogResult.google : visibleTypographyFontOptions({
|
|
2398
|
+
options: catalogResult.google,
|
|
2399
|
+
selectedFamily,
|
|
2400
|
+
limit: visibleGoogleCount
|
|
2401
|
+
});
|
|
2402
|
+
const hasMore = !searching && visibleGoogle.length < catalogResult.google.length;
|
|
2403
|
+
const title = slot === "heading" ? "Heading font" : "Body font";
|
|
2404
|
+
useEffect(() => {
|
|
2405
|
+
setVisibleGoogleCount(24);
|
|
2406
|
+
}, [category, slot]);
|
|
2407
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2408
|
+
"aria-label": title,
|
|
2409
|
+
className: "flex min-h-0 flex-1 flex-col overflow-hidden bg-background",
|
|
2410
|
+
children: [
|
|
2411
|
+
/* @__PURE__ */ jsxs("header", {
|
|
2412
|
+
className: "shrink-0 space-y-3 border-b p-3",
|
|
2413
|
+
children: [
|
|
2414
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2415
|
+
className: "flex items-center gap-2",
|
|
2416
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2417
|
+
type: "button",
|
|
2418
|
+
size: "icon",
|
|
2419
|
+
variant: "ghost",
|
|
2420
|
+
className: "h-8 w-8 shrink-0",
|
|
2421
|
+
onClick: onBack,
|
|
2422
|
+
"aria-label": "Back to typography",
|
|
2423
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, {
|
|
2424
|
+
className: "h-4 w-4",
|
|
2425
|
+
"aria-hidden": "true"
|
|
2426
|
+
})
|
|
2427
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2428
|
+
className: "min-w-0",
|
|
2429
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
2430
|
+
className: "text-sm font-semibold",
|
|
2431
|
+
children: title
|
|
2432
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
2433
|
+
className: "truncate text-xs text-muted-foreground",
|
|
2434
|
+
children: ["Current: ", selectedFamily]
|
|
2435
|
+
})]
|
|
2436
|
+
})]
|
|
2437
|
+
}),
|
|
2438
|
+
/* @__PURE__ */ jsx(SearchInput, {
|
|
2439
|
+
value: query,
|
|
2440
|
+
onChange: (event) => setQuery(event.currentTarget.value),
|
|
2441
|
+
placeholder: "Search fonts",
|
|
2442
|
+
"aria-label": `Search ${slot} fonts`,
|
|
2443
|
+
disabled
|
|
2444
|
+
}),
|
|
2445
|
+
/* @__PURE__ */ jsx("div", {
|
|
2446
|
+
role: "group",
|
|
2447
|
+
"aria-label": "Font category",
|
|
2448
|
+
className: "flex gap-1 overflow-x-auto pb-0.5",
|
|
2449
|
+
children: typographyFontCategories.map((option) => /* @__PURE__ */ jsx(Button, {
|
|
2450
|
+
type: "button",
|
|
2451
|
+
size: "sm",
|
|
2452
|
+
variant: category === option.value ? "secondary" : "ghost",
|
|
2453
|
+
className: "h-7 shrink-0 px-2 text-xs",
|
|
2454
|
+
"aria-pressed": category === option.value,
|
|
2455
|
+
onClick: () => setCategory(option.value),
|
|
2456
|
+
disabled,
|
|
2457
|
+
children: option.label
|
|
2458
|
+
}, option.value))
|
|
2459
|
+
})
|
|
2460
|
+
]
|
|
2593
2461
|
}),
|
|
2594
|
-
/* @__PURE__ */
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2462
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2463
|
+
"data-typography-font-catalog-scroll": true,
|
|
2464
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2",
|
|
2465
|
+
children: [
|
|
2466
|
+
/* @__PURE__ */ jsx(FontCatalogFeedback, { catalog }),
|
|
2467
|
+
catalogResult.site.length > 0 ? /* @__PURE__ */ jsx(FontOptionSection, {
|
|
2468
|
+
label: "Your fonts",
|
|
2469
|
+
children: catalogResult.site.map((option) => /* @__PURE__ */ jsx(TypographyFontOptionRow, {
|
|
2470
|
+
option,
|
|
2471
|
+
selected: familyMatches(selectedFamily, option.family),
|
|
2472
|
+
onSelect: () => onChange(option.family),
|
|
2473
|
+
disabled
|
|
2474
|
+
}, `site:${option.family}`))
|
|
2475
|
+
}) : null,
|
|
2476
|
+
visibleGoogle.length > 0 ? /* @__PURE__ */ jsxs(FontOptionSection, {
|
|
2477
|
+
label: searching ? "Matching fonts" : "Popular fonts",
|
|
2478
|
+
children: [visibleGoogle.map((option) => /* @__PURE__ */ jsx(TypographyFontOptionRow, {
|
|
2479
|
+
option,
|
|
2480
|
+
selected: familyMatches(selectedFamily, option.family),
|
|
2481
|
+
onSelect: () => onChange(option.family),
|
|
2482
|
+
disabled
|
|
2483
|
+
}, `google:${option.family}`)), hasMore ? /* @__PURE__ */ jsx(Button, {
|
|
2484
|
+
type: "button",
|
|
2485
|
+
size: "sm",
|
|
2486
|
+
variant: "ghost",
|
|
2487
|
+
className: "mt-1 w-full",
|
|
2488
|
+
onClick: () => setVisibleGoogleCount((count) => count + 24),
|
|
2489
|
+
disabled,
|
|
2490
|
+
children: "Show more fonts"
|
|
2491
|
+
}) : null]
|
|
2492
|
+
}) : catalog.google.kind === "loaded" && catalog.site.kind === "loaded" ? /* @__PURE__ */ jsx("p", {
|
|
2493
|
+
className: "px-2 py-8 text-center text-sm text-muted-foreground",
|
|
2494
|
+
children: "No fonts match your search."
|
|
2495
|
+
}) : null
|
|
2496
|
+
]
|
|
2604
2497
|
}),
|
|
2605
|
-
|
|
2606
|
-
expanded: state.expandedRow === "colours",
|
|
2607
|
-
onToggle: () => handleToggleRow("colours"),
|
|
2608
|
-
palette: currentPalette.colors,
|
|
2609
|
-
isCustom: !currentCuratedPalette || currentPalette.mode !== currentCuratedPalette.mode || !paletteColorsEqual(currentPalette.colors, currentCuratedPalette.colors),
|
|
2610
|
-
onTokenChange: handleTokenOverride,
|
|
2611
|
-
onReset: handleResetOverrides,
|
|
2612
|
-
disabled: paletteControlsDisabled,
|
|
2613
|
-
mutationCapability: paletteMutation
|
|
2614
|
-
}) : null,
|
|
2615
|
-
previewingChange ? /* @__PURE__ */ jsxs("div", {
|
|
2616
|
-
className: "flex items-center gap-2 pt-2",
|
|
2617
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
2618
|
-
type: "button",
|
|
2619
|
-
size: "sm",
|
|
2620
|
-
variant: "outline",
|
|
2621
|
-
onClick: handleCancel,
|
|
2622
|
-
disabled: !stagedCapabilities.canCancelStaged || saving,
|
|
2623
|
-
children: "Cancel"
|
|
2624
|
-
}), applyAllowed ? /* @__PURE__ */ jsx(Button, {
|
|
2625
|
-
type: "button",
|
|
2626
|
-
size: "sm",
|
|
2627
|
-
onClick: handleApply,
|
|
2628
|
-
disabled: !stagedCapabilities.canApplyStaged || saving,
|
|
2629
|
-
children: saving ? "Applying…" : "Apply"
|
|
2630
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
2631
|
-
className: "text-xs text-muted-foreground",
|
|
2632
|
-
children: "Preview only — ask an admin to apply."
|
|
2633
|
-
})]
|
|
2634
|
-
}) : null,
|
|
2635
|
-
state.saveStatus.kind === "saved" ? /* @__PURE__ */ jsx("p", {
|
|
2636
|
-
className: "text-xs text-success",
|
|
2637
|
-
children: "Saved."
|
|
2638
|
-
}) : null,
|
|
2639
|
-
state.saveStatus.kind === "failed" ? /* @__PURE__ */ jsx("p", {
|
|
2640
|
-
className: "text-xs text-destructive",
|
|
2641
|
-
children: state.saveStatus.message
|
|
2642
|
-
}) : null
|
|
2498
|
+
/* @__PURE__ */ jsx(SiteFontFaceStyles, { siteFonts: catalog.site.value })
|
|
2643
2499
|
]
|
|
2644
2500
|
});
|
|
2645
2501
|
}
|
|
2646
|
-
function
|
|
2647
|
-
return /* @__PURE__ */
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
children: /* @__PURE__ */
|
|
2651
|
-
className: "
|
|
2652
|
-
children:
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
"aria-expanded": expanded,
|
|
2658
|
-
children: [
|
|
2659
|
-
/* @__PURE__ */ jsx(ChevronRight, { className: cn("h-4 w-4 transition", expanded && "rotate-90") }),
|
|
2660
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2661
|
-
className: "flex-1 min-w-0",
|
|
2662
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
2663
|
-
className: "text-xs uppercase tracking-wide text-muted-foreground",
|
|
2664
|
-
children: label
|
|
2665
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2666
|
-
className: "truncate text-sm font-medium",
|
|
2667
|
-
children: currentLabel
|
|
2668
|
-
})]
|
|
2669
|
-
}),
|
|
2670
|
-
swatch ? /* @__PURE__ */ jsx("span", {
|
|
2671
|
-
className: "h-5 w-5 shrink-0 rounded-full border border-black/10",
|
|
2672
|
-
style: { backgroundColor: swatch },
|
|
2673
|
-
"aria-hidden": "true"
|
|
2674
|
-
}) : null
|
|
2675
|
-
]
|
|
2676
|
-
})
|
|
2677
|
-
}), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", {
|
|
2678
|
-
className: "border-t px-3 py-3",
|
|
2679
|
-
children
|
|
2680
|
-
}) })]
|
|
2681
|
-
})
|
|
2502
|
+
function FontOptionSection({ label, children }) {
|
|
2503
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2504
|
+
"aria-label": label,
|
|
2505
|
+
className: "mb-3 last:mb-0",
|
|
2506
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
2507
|
+
className: "sticky top-0 z-[1] bg-background px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground",
|
|
2508
|
+
children: label
|
|
2509
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2510
|
+
className: "space-y-0.5",
|
|
2511
|
+
children
|
|
2512
|
+
})]
|
|
2682
2513
|
});
|
|
2683
2514
|
}
|
|
2684
|
-
function
|
|
2685
|
-
return /* @__PURE__ */
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
})
|
|
2515
|
+
function TypographyFontOptionRow({ option, selected, onSelect, disabled }) {
|
|
2516
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
2517
|
+
type: "button",
|
|
2518
|
+
"aria-pressed": selected,
|
|
2519
|
+
"aria-label": option.label,
|
|
2520
|
+
className: cn("flex min-h-11 w-full items-center gap-3 rounded-md border border-transparent px-3 py-2 text-left transition disabled:cursor-not-allowed disabled:opacity-50", selected ? "border-primary/60 bg-primary/10" : "hover:border-border hover:bg-accent/30"),
|
|
2521
|
+
onClick: onSelect,
|
|
2522
|
+
disabled,
|
|
2523
|
+
children: [/* @__PURE__ */ jsx(FontPreviewText, {
|
|
2524
|
+
family: option.family,
|
|
2525
|
+
source: option.source,
|
|
2526
|
+
className: "min-w-0 flex-1 truncate text-base",
|
|
2527
|
+
children: option.label
|
|
2528
|
+
}), selected ? /* @__PURE__ */ jsx(Check, {
|
|
2529
|
+
className: "h-4 w-4 shrink-0 text-primary",
|
|
2530
|
+
"aria-hidden": "true"
|
|
2531
|
+
}) : null]
|
|
2702
2532
|
});
|
|
2703
2533
|
}
|
|
2704
|
-
function
|
|
2705
|
-
return /* @__PURE__ */ jsx(
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
expanded,
|
|
2709
|
-
onToggle,
|
|
2710
|
-
children: /* @__PURE__ */ jsx("ul", {
|
|
2711
|
-
role: "radiogroup",
|
|
2712
|
-
"aria-label": "Button style",
|
|
2713
|
-
className: "list-none space-y-1 p-0",
|
|
2714
|
-
children: useMemo(() => requireEntriesForCuratedChoices(buttonPersonalities, siteStyle.buttonPersonalityChoices), [siteStyle.buttonPersonalityChoices]).map((personality) => /* @__PURE__ */ jsx(PickerOption, {
|
|
2715
|
-
selected: personality.id === currentId,
|
|
2716
|
-
label: personality.name,
|
|
2717
|
-
description: personality.description,
|
|
2718
|
-
onSelect: () => onPreview(personality.id),
|
|
2719
|
-
disabled
|
|
2720
|
-
}, personality.id))
|
|
2721
|
-
})
|
|
2534
|
+
function FontCatalogFeedback({ catalog }) {
|
|
2535
|
+
if ((catalog.google.kind === "loading" || catalog.google.kind === "idle") && catalog.google.value.length === 0) return /* @__PURE__ */ jsx("p", {
|
|
2536
|
+
className: "px-2 py-6 text-center text-sm text-muted-foreground",
|
|
2537
|
+
children: "Loading font catalog…"
|
|
2722
2538
|
});
|
|
2539
|
+
const failureMessages = [catalog.site.kind === "failed" ? catalog.site.message : null, catalog.google.kind === "failed" ? catalog.google.message : null].filter((message) => message !== null);
|
|
2540
|
+
if (failureMessages.length > 0) return /* @__PURE__ */ jsx("div", {
|
|
2541
|
+
className: "mb-2 space-y-1",
|
|
2542
|
+
children: failureMessages.map((message) => /* @__PURE__ */ jsx("p", {
|
|
2543
|
+
className: "rounded-md bg-muted/60 px-3 py-2 text-xs text-muted-foreground",
|
|
2544
|
+
children: message
|
|
2545
|
+
}, message))
|
|
2546
|
+
});
|
|
2547
|
+
return null;
|
|
2723
2548
|
}
|
|
2724
|
-
function
|
|
2725
|
-
const
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
const
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
className: "
|
|
2741
|
-
children:
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2549
|
+
function TypographyAdvancedTakeover({ typography, catalog, onBack, onHeadingChange, onBodyChange, onScaleChange, disabled }) {
|
|
2550
|
+
const headingOption = fontOptionForFamily(typography.headings.default.family, {
|
|
2551
|
+
googleFonts: catalog.google.value,
|
|
2552
|
+
siteFonts: catalog.site.value
|
|
2553
|
+
});
|
|
2554
|
+
const bodyOption = fontOptionForFamily(typography.body.family, {
|
|
2555
|
+
googleFonts: catalog.google.value,
|
|
2556
|
+
siteFonts: catalog.site.value
|
|
2557
|
+
});
|
|
2558
|
+
const headingWeightWarning = unsupportedWeightMessage(headingOption, typography.headings.default.weight, typography.headings.default.italic === true ? "italic" : "normal");
|
|
2559
|
+
const bodyWeightWarning = unsupportedWeightMessage(bodyOption, typography.body.weight, "normal");
|
|
2560
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2561
|
+
"aria-label": "Advanced typography",
|
|
2562
|
+
className: "flex min-h-0 flex-1 flex-col overflow-hidden bg-background",
|
|
2563
|
+
children: [
|
|
2564
|
+
/* @__PURE__ */ jsxs("header", {
|
|
2565
|
+
className: "flex items-center gap-2 border-b p-3",
|
|
2566
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2567
|
+
type: "button",
|
|
2568
|
+
size: "icon",
|
|
2569
|
+
variant: "ghost",
|
|
2570
|
+
className: "h-8 w-8 shrink-0",
|
|
2571
|
+
onClick: onBack,
|
|
2572
|
+
"aria-label": "Back to typography",
|
|
2573
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, {
|
|
2574
|
+
className: "h-4 w-4",
|
|
2575
|
+
"aria-hidden": "true"
|
|
2576
|
+
})
|
|
2577
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
|
|
2578
|
+
className: "text-sm font-semibold",
|
|
2579
|
+
children: "Advanced typography"
|
|
2580
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
2581
|
+
className: "text-xs text-muted-foreground",
|
|
2582
|
+
children: "Fine-tune the type system."
|
|
2583
|
+
})] })]
|
|
2584
|
+
}),
|
|
2585
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2586
|
+
className: "min-h-0 flex-1 space-y-2 overflow-y-auto p-3",
|
|
2587
|
+
children: [/* @__PURE__ */ jsxs(TypographyDisclosure, {
|
|
2757
2588
|
label: "Heading",
|
|
2758
|
-
|
|
2759
|
-
onOpenChange: setHeadingOpen,
|
|
2589
|
+
defaultOpen: true,
|
|
2760
2590
|
children: [
|
|
2761
|
-
/* @__PURE__ */ jsx(TypographyFontSlotPicker, {
|
|
2762
|
-
label: "Heading font",
|
|
2763
|
-
slot: "heading",
|
|
2764
|
-
preset: fontPolicyPreset,
|
|
2765
|
-
catalog: fontCatalog,
|
|
2766
|
-
value: typography.headings.default.family,
|
|
2767
|
-
onChange: (family) => onHeadingChange({ family }),
|
|
2768
|
-
disabled
|
|
2769
|
-
}),
|
|
2770
2591
|
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2771
2592
|
label: "Weight",
|
|
2772
2593
|
value: typography.headings.default.weight,
|
|
@@ -2774,6 +2595,7 @@ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, typography, c
|
|
|
2774
2595
|
onChange: (weight) => onHeadingChange({ weight }),
|
|
2775
2596
|
disabled
|
|
2776
2597
|
}),
|
|
2598
|
+
headingWeightWarning ? /* @__PURE__ */ jsx(ContextualFontWarning, { message: headingWeightWarning }) : null,
|
|
2777
2599
|
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2778
2600
|
label: "Line height",
|
|
2779
2601
|
value: typography.headings.default.lineHeight,
|
|
@@ -2781,6 +2603,13 @@ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, typography, c
|
|
|
2781
2603
|
onChange: (lineHeight) => onHeadingChange({ lineHeight }),
|
|
2782
2604
|
disabled
|
|
2783
2605
|
}),
|
|
2606
|
+
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2607
|
+
label: "Letter spacing",
|
|
2608
|
+
value: typography.headings.default.letterSpacing,
|
|
2609
|
+
options: typographyLetterSpacingOptions,
|
|
2610
|
+
onChange: (letterSpacing) => onHeadingChange({ letterSpacing }),
|
|
2611
|
+
disabled
|
|
2612
|
+
}),
|
|
2784
2613
|
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2785
2614
|
label: "Scale",
|
|
2786
2615
|
value: normalizeTypographyScaleForControl(typography.scale),
|
|
@@ -2788,27 +2617,31 @@ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, typography, c
|
|
|
2788
2617
|
onChange: onScaleChange,
|
|
2789
2618
|
disabled
|
|
2790
2619
|
}),
|
|
2620
|
+
/* @__PURE__ */ jsx(HeadingCaseControl, {
|
|
2621
|
+
value: typography.headings.default.case,
|
|
2622
|
+
onChange: (value) => onHeadingChange({ case: value }),
|
|
2623
|
+
disabled
|
|
2624
|
+
}),
|
|
2625
|
+
/* @__PURE__ */ jsxs("button", {
|
|
2626
|
+
type: "button",
|
|
2627
|
+
className: "flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm disabled:cursor-not-allowed disabled:opacity-50",
|
|
2628
|
+
"aria-pressed": typography.headings.default.italic === true,
|
|
2629
|
+
onClick: () => onHeadingChange({ italic: typography.headings.default.italic === true ? null : true }),
|
|
2630
|
+
disabled,
|
|
2631
|
+
children: ["Italic headings", /* @__PURE__ */ jsx("span", {
|
|
2632
|
+
className: "text-xs text-muted-foreground",
|
|
2633
|
+
children: typography.headings.default.italic === true ? "On" : "Default"
|
|
2634
|
+
})]
|
|
2635
|
+
}),
|
|
2791
2636
|
/* @__PURE__ */ jsx(TypographyColorTokenControl, {
|
|
2792
|
-
value: typography.headings.default.colorToken
|
|
2637
|
+
value: normalizeHeadingColorTokenForControl(typography.headings.default.colorToken),
|
|
2793
2638
|
onChange: (colorToken) => onHeadingChange({ colorToken: colorToken === "text" ? null : colorToken }),
|
|
2794
2639
|
disabled
|
|
2795
2640
|
})
|
|
2796
2641
|
]
|
|
2797
|
-
}),
|
|
2798
|
-
/* @__PURE__ */ jsxs(TypographyDisclosure, {
|
|
2642
|
+
}), /* @__PURE__ */ jsxs(TypographyDisclosure, {
|
|
2799
2643
|
label: "Body",
|
|
2800
|
-
open: bodyOpen,
|
|
2801
|
-
onOpenChange: setBodyOpen,
|
|
2802
2644
|
children: [
|
|
2803
|
-
/* @__PURE__ */ jsx(TypographyFontSlotPicker, {
|
|
2804
|
-
label: "Body font",
|
|
2805
|
-
slot: "body",
|
|
2806
|
-
preset: fontPolicyPreset,
|
|
2807
|
-
catalog: fontCatalog,
|
|
2808
|
-
value: typography.body.family,
|
|
2809
|
-
onChange: (family) => onBodyChange({ family }),
|
|
2810
|
-
disabled
|
|
2811
|
-
}),
|
|
2812
2645
|
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2813
2646
|
label: "Size",
|
|
2814
2647
|
value: typography.body.size,
|
|
@@ -2823,41 +2656,300 @@ function TypographyRow({ expanded, onToggle, apiClient, siteStyle, typography, c
|
|
|
2823
2656
|
onChange: (weight) => onBodyChange({ weight }),
|
|
2824
2657
|
disabled
|
|
2825
2658
|
}),
|
|
2659
|
+
bodyWeightWarning ? /* @__PURE__ */ jsx(ContextualFontWarning, { message: bodyWeightWarning }) : null,
|
|
2826
2660
|
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2827
2661
|
label: "Line height",
|
|
2828
2662
|
value: typography.body.lineHeight,
|
|
2829
2663
|
options: typographyLineHeightOptions,
|
|
2830
2664
|
onChange: (lineHeight) => onBodyChange({ lineHeight }),
|
|
2831
2665
|
disabled
|
|
2666
|
+
}),
|
|
2667
|
+
/* @__PURE__ */ jsx(TypographySelectControl, {
|
|
2668
|
+
label: "Letter spacing",
|
|
2669
|
+
value: typography.body.letterSpacing,
|
|
2670
|
+
options: typographyLetterSpacingOptions,
|
|
2671
|
+
onChange: (letterSpacing) => onBodyChange({ letterSpacing }),
|
|
2672
|
+
disabled
|
|
2832
2673
|
})
|
|
2833
2674
|
]
|
|
2834
|
-
})
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
variant: "outline",
|
|
2839
|
-
onClick: onReset,
|
|
2840
|
-
disabled,
|
|
2841
|
-
children: "Reset typography"
|
|
2842
|
-
})
|
|
2843
|
-
]
|
|
2844
|
-
})]
|
|
2675
|
+
})]
|
|
2676
|
+
}),
|
|
2677
|
+
/* @__PURE__ */ jsx(SiteFontFaceStyles, { siteFonts: catalog.site.value })
|
|
2678
|
+
]
|
|
2845
2679
|
});
|
|
2846
2680
|
}
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2681
|
+
function TypographyDisclosure({ label, defaultOpen = false, children }) {
|
|
2682
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
2683
|
+
return /* @__PURE__ */ jsx(Collapsible, {
|
|
2684
|
+
open,
|
|
2685
|
+
onOpenChange: setOpen,
|
|
2686
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2687
|
+
className: "rounded-md border bg-muted/10",
|
|
2688
|
+
children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
2689
|
+
asChild: true,
|
|
2690
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
2691
|
+
type: "button",
|
|
2692
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm font-medium hover:bg-accent/30",
|
|
2693
|
+
"aria-expanded": open,
|
|
2694
|
+
children: [/* @__PURE__ */ jsx(ChevronRight, {
|
|
2695
|
+
className: cn("h-4 w-4 transition", open && "rotate-90"),
|
|
2696
|
+
"aria-hidden": "true"
|
|
2697
|
+
}), label]
|
|
2698
|
+
})
|
|
2699
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", {
|
|
2700
|
+
className: "space-y-3 border-t px-3 py-3",
|
|
2701
|
+
children
|
|
2702
|
+
}) })]
|
|
2703
|
+
})
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
function TypographySelectControl({ label, value, options, onChange, disabled }) {
|
|
2707
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
2708
|
+
className: "block space-y-1",
|
|
2709
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2710
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
2711
|
+
children: label
|
|
2712
|
+
}), /* @__PURE__ */ jsxs(Select, {
|
|
2713
|
+
value,
|
|
2714
|
+
onValueChange: (next) => {
|
|
2715
|
+
const option = options.find((candidate) => candidate.value === next);
|
|
2716
|
+
if (option) onChange(option.value);
|
|
2717
|
+
},
|
|
2718
|
+
disabled,
|
|
2719
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
2720
|
+
size: "sm",
|
|
2721
|
+
className: "w-full",
|
|
2722
|
+
"aria-label": label,
|
|
2723
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
2724
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
2725
|
+
value: option.value,
|
|
2726
|
+
children: option.label
|
|
2727
|
+
}, option.value)) })]
|
|
2728
|
+
})]
|
|
2729
|
+
});
|
|
2730
|
+
}
|
|
2731
|
+
function HeadingCaseControl({ value, onChange, disabled }) {
|
|
2732
|
+
const options = [
|
|
2733
|
+
{
|
|
2734
|
+
value: "default",
|
|
2735
|
+
label: "Default",
|
|
2736
|
+
resolved: null
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
value: "normal",
|
|
2740
|
+
label: "Normal",
|
|
2741
|
+
resolved: "normal"
|
|
2742
|
+
},
|
|
2743
|
+
{
|
|
2744
|
+
value: "uppercase",
|
|
2745
|
+
label: "Uppercase",
|
|
2746
|
+
resolved: "uppercase"
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
value: "smallCaps",
|
|
2750
|
+
label: "Small caps",
|
|
2751
|
+
resolved: "smallCaps"
|
|
2752
|
+
}
|
|
2753
|
+
];
|
|
2754
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
2755
|
+
className: "block space-y-1",
|
|
2756
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2757
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
2758
|
+
children: "Case"
|
|
2759
|
+
}), /* @__PURE__ */ jsxs(Select, {
|
|
2760
|
+
value: value ?? "default",
|
|
2761
|
+
onValueChange: (next) => {
|
|
2762
|
+
const option = options.find((candidate) => candidate.value === next);
|
|
2763
|
+
if (option) onChange(option.resolved);
|
|
2764
|
+
},
|
|
2765
|
+
disabled,
|
|
2766
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
2767
|
+
size: "sm",
|
|
2768
|
+
className: "w-full",
|
|
2769
|
+
"aria-label": "Heading case",
|
|
2770
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
2771
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
2772
|
+
value: option.value,
|
|
2773
|
+
children: option.label
|
|
2774
|
+
}, option.value)) })]
|
|
2775
|
+
})]
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function TypographyColorTokenControl({ value, onChange, disabled }) {
|
|
2779
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2780
|
+
className: "space-y-2",
|
|
2781
|
+
"aria-label": "Default heading color",
|
|
2782
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [
|
|
2783
|
+
/* @__PURE__ */ jsx("div", {
|
|
2784
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
2785
|
+
children: "Default heading color"
|
|
2786
|
+
}),
|
|
2787
|
+
/* @__PURE__ */ jsx("p", {
|
|
2788
|
+
className: "text-[11px] text-muted-foreground",
|
|
2789
|
+
children: "Sections may override this for readability."
|
|
2790
|
+
}),
|
|
2791
|
+
value.kind === "existing" ? /* @__PURE__ */ jsxs("p", {
|
|
2792
|
+
className: "mt-1 text-[11px] text-muted-foreground",
|
|
2793
|
+
children: [
|
|
2794
|
+
"Current: ",
|
|
2795
|
+
formatColorTokenLabel(value.value),
|
|
2796
|
+
" (outside quick choices)"
|
|
2797
|
+
]
|
|
2798
|
+
}) : null
|
|
2799
|
+
] }), /* @__PURE__ */ jsx("div", {
|
|
2800
|
+
className: "grid grid-cols-2 gap-1",
|
|
2801
|
+
children: headingColorTokenOptions.map((option) => /* @__PURE__ */ jsx(Button, {
|
|
2802
|
+
type: "button",
|
|
2803
|
+
size: "sm",
|
|
2804
|
+
variant: value.kind === "curated" && value.value === option.value ? "secondary" : "outline",
|
|
2805
|
+
className: "justify-start text-xs",
|
|
2806
|
+
"aria-pressed": value.kind === "curated" && value.value === option.value,
|
|
2807
|
+
onClick: () => onChange(option.value),
|
|
2808
|
+
disabled,
|
|
2809
|
+
children: option.label
|
|
2810
|
+
}, option.value))
|
|
2811
|
+
})]
|
|
2812
|
+
});
|
|
2813
|
+
}
|
|
2814
|
+
function ContextualFontWarning({ message }) {
|
|
2815
|
+
return /* @__PURE__ */ jsx("p", {
|
|
2816
|
+
className: "rounded-md bg-warning/10 px-2 py-1.5 text-xs text-muted-foreground",
|
|
2817
|
+
children: message
|
|
2818
|
+
});
|
|
2819
|
+
}
|
|
2820
|
+
function FontPreviewText({ family, source, className, children }) {
|
|
2821
|
+
const elementRef = useRef(null);
|
|
2822
|
+
const [visible, setVisible] = useState(() => typeof globalThis.IntersectionObserver !== "function");
|
|
2823
|
+
useEffect(() => {
|
|
2824
|
+
if (visible || source !== "google") return;
|
|
2825
|
+
const element = elementRef.current;
|
|
2826
|
+
if (!element || typeof globalThis.IntersectionObserver !== "function") {
|
|
2827
|
+
setVisible(true);
|
|
2828
|
+
return;
|
|
2829
|
+
}
|
|
2830
|
+
const observer = new globalThis.IntersectionObserver((entries) => {
|
|
2831
|
+
if (!entries.some((entry) => entry.isIntersecting)) return;
|
|
2832
|
+
setVisible(true);
|
|
2833
|
+
observer.disconnect();
|
|
2834
|
+
}, { rootMargin: "160px 0px" });
|
|
2835
|
+
observer.observe(element);
|
|
2836
|
+
return () => observer.disconnect();
|
|
2837
|
+
}, [source, visible]);
|
|
2838
|
+
useEffect(() => {
|
|
2839
|
+
if (!visible || source !== "google") return;
|
|
2840
|
+
ensureGoogleFontPreviewLink(family);
|
|
2841
|
+
}, [
|
|
2842
|
+
family,
|
|
2843
|
+
source,
|
|
2844
|
+
visible
|
|
2845
|
+
]);
|
|
2846
|
+
return /* @__PURE__ */ jsx("span", {
|
|
2847
|
+
ref: elementRef,
|
|
2848
|
+
className,
|
|
2849
|
+
style: source === "site" || source === "google" ? { fontFamily: quoteFontFamily(family) } : void 0,
|
|
2850
|
+
children
|
|
2851
|
+
});
|
|
2852
|
+
}
|
|
2853
|
+
function SiteFontFaceStyles({ siteFonts }) {
|
|
2854
|
+
const css = useMemo(() => {
|
|
2855
|
+
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
2856
|
+
if (!supabaseUrl || siteFonts.length === 0) return "";
|
|
2857
|
+
return generateFontFaceCss([...siteFonts], getSiteFontsStorageUrl(supabaseUrl));
|
|
2858
|
+
}, [siteFonts]);
|
|
2859
|
+
return css ? /* @__PURE__ */ jsx("style", {
|
|
2860
|
+
"data-typography-site-fonts": true,
|
|
2861
|
+
children: css
|
|
2862
|
+
}) : null;
|
|
2863
|
+
}
|
|
2864
|
+
function ensureGoogleFontPreviewLink(family) {
|
|
2865
|
+
const url = buildFontPreviewUrl(family);
|
|
2866
|
+
if (Array.from(document.head.querySelectorAll("link[data-font-preview]")).some((link) => link.href === url)) return;
|
|
2867
|
+
const link = document.createElement("link");
|
|
2868
|
+
link.rel = "stylesheet";
|
|
2869
|
+
link.href = url;
|
|
2870
|
+
link.dataset.fontPreview = family;
|
|
2871
|
+
document.head.appendChild(link);
|
|
2872
|
+
}
|
|
2873
|
+
function unsupportedWeightMessage(option, weight, style) {
|
|
2874
|
+
if (!option) return null;
|
|
2875
|
+
const numericWeight = semanticFontWeight(weight);
|
|
2876
|
+
if (option.source === "site") {
|
|
2877
|
+
const font = option.siteFont;
|
|
2878
|
+
if (font.isVariable && font.variableWeightMin !== null && font.variableWeightMax !== null) return numericWeight >= font.variableWeightMin && numericWeight <= font.variableWeightMax && font.files.some((file) => file.style === style) ? null : unsupportedFontStyleMessage(option.label, style);
|
|
2879
|
+
return font.files.some((file) => file.weight === numericWeight && file.style === style) ? null : unsupportedFontStyleMessage(option.label, style);
|
|
2880
|
+
}
|
|
2881
|
+
const variants = new Set(option.googleFont.variants);
|
|
2882
|
+
return (style === "italic" ? variants.has(numericWeight === 400 ? "italic" : `${numericWeight}italic`) : variants.has(String(numericWeight)) || numericWeight === 400 && variants.has("regular")) ? null : unsupportedFontStyleMessage(option.label, style);
|
|
2883
|
+
}
|
|
2884
|
+
function unsupportedFontStyleMessage(family, style) {
|
|
2885
|
+
return style === "italic" ? `${family} may not include italics at this weight.` : `${family} may not include this weight.`;
|
|
2886
|
+
}
|
|
2887
|
+
function semanticFontWeight(weight) {
|
|
2888
|
+
switch (weight) {
|
|
2889
|
+
case "light": return 300;
|
|
2890
|
+
case "regular": return 400;
|
|
2891
|
+
case "medium": return 500;
|
|
2892
|
+
case "semibold": return 600;
|
|
2893
|
+
case "bold": return 700;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
function normalizeTypographyScaleForControl(scale) {
|
|
2897
|
+
switch (scale) {
|
|
2898
|
+
case "compact":
|
|
2899
|
+
case "balanced":
|
|
2900
|
+
case "spacious": return scale;
|
|
2901
|
+
case "minorThird": return "compact";
|
|
2902
|
+
case "majorThird": return "balanced";
|
|
2903
|
+
case "perfectFourth": return "spacious";
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
function normalizeHeadingColorTokenForControl(value) {
|
|
2907
|
+
switch (value) {
|
|
2908
|
+
case "primary":
|
|
2909
|
+
case "secondary":
|
|
2910
|
+
case "accent": return {
|
|
2911
|
+
kind: "curated",
|
|
2912
|
+
value
|
|
2913
|
+
};
|
|
2914
|
+
case "text":
|
|
2915
|
+
case void 0:
|
|
2916
|
+
case null: return {
|
|
2917
|
+
kind: "curated",
|
|
2918
|
+
value: "text"
|
|
2919
|
+
};
|
|
2920
|
+
default: return {
|
|
2921
|
+
kind: "existing",
|
|
2922
|
+
value
|
|
2923
|
+
};
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
function formatColorTokenLabel(value) {
|
|
2927
|
+
const words = value.replace(/([a-z])([A-Z])/gu, "$1 $2").replace(/[-_]+/gu, " ").toLocaleLowerCase();
|
|
2928
|
+
return `${words.charAt(0).toLocaleUpperCase()}${words.slice(1)}`;
|
|
2929
|
+
}
|
|
2930
|
+
function familyMatches(left, right) {
|
|
2931
|
+
return left.toLocaleLowerCase() === right.toLocaleLowerCase();
|
|
2932
|
+
}
|
|
2933
|
+
function quoteFontFamily(family) {
|
|
2934
|
+
return `"${family.replace(/["\\]/gu, "")}", sans-serif`;
|
|
2935
|
+
}
|
|
2936
|
+
function errorMessage(error, fallback) {
|
|
2937
|
+
return error instanceof Error && error.message ? error.message : fallback;
|
|
2938
|
+
}
|
|
2939
|
+
const typographyWeightOptions = [
|
|
2940
|
+
{
|
|
2941
|
+
value: "light",
|
|
2942
|
+
label: "Light"
|
|
2943
|
+
},
|
|
2944
|
+
{
|
|
2945
|
+
value: "regular",
|
|
2946
|
+
label: "Regular"
|
|
2947
|
+
},
|
|
2948
|
+
{
|
|
2949
|
+
value: "medium",
|
|
2950
|
+
label: "Medium"
|
|
2951
|
+
},
|
|
2952
|
+
{
|
|
2861
2953
|
value: "semibold",
|
|
2862
2954
|
label: "Semibold"
|
|
2863
2955
|
},
|
|
@@ -2880,6 +2972,20 @@ const typographyLineHeightOptions = [
|
|
|
2880
2972
|
label: "Loose"
|
|
2881
2973
|
}
|
|
2882
2974
|
];
|
|
2975
|
+
const typographyLetterSpacingOptions = [
|
|
2976
|
+
{
|
|
2977
|
+
value: "tight",
|
|
2978
|
+
label: "Tight"
|
|
2979
|
+
},
|
|
2980
|
+
{
|
|
2981
|
+
value: "normal",
|
|
2982
|
+
label: "Normal"
|
|
2983
|
+
},
|
|
2984
|
+
{
|
|
2985
|
+
value: "loose",
|
|
2986
|
+
label: "Loose"
|
|
2987
|
+
}
|
|
2988
|
+
];
|
|
2883
2989
|
const bodySizeOptions = [
|
|
2884
2990
|
{
|
|
2885
2991
|
value: "md",
|
|
@@ -2911,7 +3017,7 @@ const typographyScaleOptions = [
|
|
|
2911
3017
|
const headingColorTokenOptions = [
|
|
2912
3018
|
{
|
|
2913
3019
|
value: "text",
|
|
2914
|
-
label: "
|
|
3020
|
+
label: "Default text"
|
|
2915
3021
|
},
|
|
2916
3022
|
{
|
|
2917
3023
|
value: "primary",
|
|
@@ -2926,400 +3032,768 @@ const headingColorTokenOptions = [
|
|
|
2926
3032
|
label: "Accent"
|
|
2927
3033
|
}
|
|
2928
3034
|
];
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
3035
|
+
//#endregion
|
|
3036
|
+
//#region ../preview-next/src/client/preview/StyleConfigurator.tsx
|
|
3037
|
+
const PALETTE_BRAND_ROLES = [
|
|
3038
|
+
{
|
|
3039
|
+
key: "primary",
|
|
3040
|
+
label: "Primary"
|
|
3041
|
+
},
|
|
3042
|
+
{
|
|
3043
|
+
key: "primaryForeground",
|
|
3044
|
+
label: "Primary text"
|
|
3045
|
+
},
|
|
3046
|
+
{
|
|
3047
|
+
key: "secondary",
|
|
3048
|
+
label: "Secondary"
|
|
3049
|
+
},
|
|
3050
|
+
{
|
|
3051
|
+
key: "accent",
|
|
3052
|
+
label: "Accent"
|
|
3053
|
+
}
|
|
3054
|
+
];
|
|
3055
|
+
const PALETTE_FEEDBACK_ROLES = [
|
|
3056
|
+
{
|
|
3057
|
+
key: "success",
|
|
3058
|
+
label: "Success"
|
|
3059
|
+
},
|
|
3060
|
+
{
|
|
3061
|
+
key: "warning",
|
|
3062
|
+
label: "Warning"
|
|
3063
|
+
},
|
|
3064
|
+
{
|
|
3065
|
+
key: "destructive",
|
|
3066
|
+
label: "Destructive"
|
|
3067
|
+
}
|
|
3068
|
+
];
|
|
3069
|
+
const PALETTE_SURFACE_ROLES = [
|
|
3070
|
+
{
|
|
3071
|
+
key: "background",
|
|
3072
|
+
label: "Background"
|
|
3073
|
+
},
|
|
3074
|
+
{
|
|
3075
|
+
key: "surface",
|
|
3076
|
+
label: "Surface"
|
|
3077
|
+
},
|
|
3078
|
+
{
|
|
3079
|
+
key: "surfaceAlt",
|
|
3080
|
+
label: "Alternate surface"
|
|
3081
|
+
},
|
|
3082
|
+
{
|
|
3083
|
+
key: "muted",
|
|
3084
|
+
label: "Muted surface"
|
|
3085
|
+
},
|
|
3086
|
+
{
|
|
3087
|
+
key: "text",
|
|
3088
|
+
label: "Text"
|
|
3089
|
+
},
|
|
3090
|
+
{
|
|
3091
|
+
key: "border",
|
|
3092
|
+
label: "Border"
|
|
3093
|
+
}
|
|
3094
|
+
];
|
|
3095
|
+
function StyleConfigurator({ siteId, apiClient, theme, selectionId, selectionVersion = null, selectionUpdatedAt, initialSelections, headerSelectionContext, footerSelectionContext, expandedRowRequest = null, onFocusedSurfaceChange, siteStyleAccess }) {
|
|
3096
|
+
const router = useRouter();
|
|
3097
|
+
const previewDesign = usePreviewDesignCoordinator();
|
|
3098
|
+
const siteChromeCustomize = useSiteChromeCustomizeOptional();
|
|
3099
|
+
const setSiteStyleStagedPreviewActive = siteChromeCustomize?.siteStyleHistory?.setStagedPreviewActive;
|
|
3100
|
+
const { applyFailed, applyStarted, applySucceeded, clearPreview, previewTheme } = previewDesign;
|
|
3101
|
+
const [isRefreshPending, startRefreshTransition] = useTransition();
|
|
3102
|
+
const baseSnapshot = useMemo(() => resolveStyleConfiguratorInitialSnapshot({
|
|
3103
|
+
theme,
|
|
3104
|
+
initialSelections: {
|
|
3105
|
+
...initialSelections,
|
|
3106
|
+
selectionVersion: initialSelections.selectionVersion ?? selectionVersion ?? 0,
|
|
3107
|
+
selectionUpdatedAt: initialSelections.selectionUpdatedAt ?? selectionUpdatedAt ?? null
|
|
3108
|
+
},
|
|
3109
|
+
headerSelectionContext,
|
|
3110
|
+
footerSelectionContext
|
|
3111
|
+
}), [
|
|
3112
|
+
footerSelectionContext,
|
|
3113
|
+
headerSelectionContext,
|
|
3114
|
+
theme,
|
|
3115
|
+
initialSelections,
|
|
3116
|
+
selectionUpdatedAt,
|
|
3117
|
+
selectionVersion
|
|
3118
|
+
]);
|
|
3119
|
+
const [state, setState] = useState(() => baseSnapshot ? createStyleConfiguratorState(baseSnapshot) : null);
|
|
3120
|
+
const [typographySurface, setTypographySurface] = useState(typographyOverviewSurface);
|
|
3121
|
+
const fontCatalog = useTypographyFontCatalog(apiClient, siteId, state?.expandedRow === "typography");
|
|
3122
|
+
const hasLoadedState = state !== null;
|
|
3123
|
+
const hasStagedSiteStylePreview = state ? isPreviewingChange(state) : false;
|
|
3124
|
+
const hasFocusedTypographySurface = state?.expandedRow === "typography" && typographySurface.kind !== "overview";
|
|
3125
|
+
const stateRef = useRef(state);
|
|
3126
|
+
const clearPreviewRef = useRef(clearPreview);
|
|
3127
|
+
const runnerRef = useRef(createOptimisticActionRunner());
|
|
3128
|
+
const appliedExpandedRowRequestIdRef = useRef(null);
|
|
3129
|
+
useEffect(() => {
|
|
3130
|
+
stateRef.current = state;
|
|
3131
|
+
}, [state]);
|
|
3132
|
+
useEffect(() => {
|
|
3133
|
+
if (state?.expandedRow !== "typography" && typographySurface.kind !== "overview") setTypographySurface(typographyOverviewSurface);
|
|
3134
|
+
}, [state?.expandedRow, typographySurface.kind]);
|
|
3135
|
+
useEffect(() => {
|
|
3136
|
+
onFocusedSurfaceChange?.(hasFocusedTypographySurface);
|
|
3137
|
+
return () => {
|
|
3138
|
+
if (hasFocusedTypographySurface) onFocusedSurfaceChange?.(false);
|
|
3139
|
+
};
|
|
3140
|
+
}, [hasFocusedTypographySurface, onFocusedSurfaceChange]);
|
|
3141
|
+
useEffect(() => {
|
|
3142
|
+
clearPreviewRef.current = clearPreview;
|
|
3143
|
+
}, [clearPreview]);
|
|
3144
|
+
useEffect(() => {
|
|
3145
|
+
if (!setSiteStyleStagedPreviewActive) return;
|
|
3146
|
+
setSiteStyleStagedPreviewActive(hasStagedSiteStylePreview);
|
|
3147
|
+
return () => {
|
|
3148
|
+
setSiteStyleStagedPreviewActive(false);
|
|
3149
|
+
};
|
|
3150
|
+
}, [hasStagedSiteStylePreview, setSiteStyleStagedPreviewActive]);
|
|
3151
|
+
useEffect(() => {
|
|
3152
|
+
if (!baseSnapshot) return;
|
|
3153
|
+
setState((current) => current ? syncStyleConfiguratorState(current, baseSnapshot) : createStyleConfiguratorState(baseSnapshot));
|
|
3154
|
+
}, [baseSnapshot]);
|
|
3155
|
+
useEffect(() => {
|
|
3156
|
+
if (!state || !baseSnapshot) {
|
|
3157
|
+
clearPreview("style-configurator");
|
|
3158
|
+
return;
|
|
3159
|
+
}
|
|
3160
|
+
if (!isPreviewingChange(state)) {
|
|
3161
|
+
clearPreview("style-configurator");
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3164
|
+
const siteStyle = getCuratedSiteStyle(state.previewed.siteStyleId);
|
|
3165
|
+
if (!siteStyle) {
|
|
3166
|
+
clearPreview("style-configurator");
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
previewTheme("style-configurator", planSiteStylePreviewChange({
|
|
3170
|
+
siteStyle,
|
|
3171
|
+
selection: state.previewed,
|
|
3172
|
+
baseTheme: theme,
|
|
3173
|
+
headerSelectionContext,
|
|
3174
|
+
footerSelectionContext
|
|
3175
|
+
}).themeOverlay, "site-style");
|
|
3176
|
+
}, [
|
|
3177
|
+
state,
|
|
3178
|
+
baseSnapshot,
|
|
3179
|
+
clearPreview,
|
|
3180
|
+
previewTheme,
|
|
3181
|
+
headerSelectionContext,
|
|
3182
|
+
footerSelectionContext,
|
|
3183
|
+
theme
|
|
3184
|
+
]);
|
|
3185
|
+
useEffect(() => {
|
|
3186
|
+
const runner = runnerRef.current;
|
|
3187
|
+
return () => {
|
|
3188
|
+
runner.invalidate();
|
|
3189
|
+
clearPreviewRef.current("style-configurator");
|
|
3190
|
+
};
|
|
3191
|
+
}, []);
|
|
3192
|
+
useEffect(() => {
|
|
3193
|
+
if (!expandedRowRequest) return;
|
|
3194
|
+
if (appliedExpandedRowRequestIdRef.current === expandedRowRequest.id) return;
|
|
3195
|
+
setState((current) => {
|
|
3196
|
+
if (!current) return current;
|
|
3197
|
+
appliedExpandedRowRequestIdRef.current = expandedRowRequest.id;
|
|
3198
|
+
return openRow(current, expandedRowForPreviewDesignRow(expandedRowRequest.row));
|
|
3199
|
+
});
|
|
3200
|
+
}, [expandedRowRequest, hasLoadedState]);
|
|
3201
|
+
const handlePreviewSiteStyle = useCallback((siteStyleId) => {
|
|
3202
|
+
setState((current) => {
|
|
3203
|
+
if (!current) return current;
|
|
3204
|
+
const next = previewSiteStyle(current, siteStyleId);
|
|
3205
|
+
const siteStyle = getCuratedSiteStyle(siteStyleId);
|
|
3206
|
+
if (!siteStyle) return next;
|
|
3207
|
+
const result = planSiteStylePreviewChange({
|
|
3208
|
+
siteStyle,
|
|
3209
|
+
selection: next.previewed,
|
|
3210
|
+
baseTheme: theme,
|
|
3211
|
+
headerSelectionContext,
|
|
3212
|
+
footerSelectionContext
|
|
3213
|
+
});
|
|
3214
|
+
return applyResolvedSelections(next, {
|
|
3215
|
+
resolved: {
|
|
3216
|
+
...result.resolvedSelections,
|
|
3217
|
+
typography: result.themeOverlay.typography
|
|
3218
|
+
},
|
|
3219
|
+
warnings: result.warnings
|
|
3220
|
+
});
|
|
3221
|
+
});
|
|
3222
|
+
}, [
|
|
3223
|
+
footerSelectionContext,
|
|
3224
|
+
headerSelectionContext,
|
|
3225
|
+
theme
|
|
3226
|
+
]);
|
|
3227
|
+
const handlePreviewPersonality = useCallback((id) => {
|
|
3228
|
+
setState((current) => current ? previewButtonPersonality(current, id) : current);
|
|
3229
|
+
}, []);
|
|
3230
|
+
const handlePreviewHeaderLayout = useCallback((id) => {
|
|
3231
|
+
if (!id) return;
|
|
3232
|
+
setState((current) => current ? previewHeaderLayout(current, id) : current);
|
|
3233
|
+
}, []);
|
|
3234
|
+
const handlePreviewHeaderStyle = useCallback((id) => {
|
|
3235
|
+
if (!id) return;
|
|
3236
|
+
setState((current) => current ? previewHeaderStyle(current, id) : current);
|
|
3237
|
+
}, []);
|
|
3238
|
+
const handlePreviewFooterLook = useCallback((id) => {
|
|
3239
|
+
const plan = planSiteChromeLookSelection({
|
|
3240
|
+
surface: "footer",
|
|
3241
|
+
lookId: id
|
|
3242
|
+
});
|
|
3243
|
+
if (plan.kind !== "footer") return;
|
|
3244
|
+
setState((current) => current ? previewFooterLook(current, plan.next.footerLookId) : current);
|
|
3245
|
+
}, []);
|
|
3246
|
+
const handlePreviewFooterLayout = useCallback((id) => {
|
|
3247
|
+
if (!id) return;
|
|
3248
|
+
setState((current) => {
|
|
3249
|
+
if (!current) return current;
|
|
3250
|
+
const siteStyle = getCuratedSiteStyle(current.previewed.siteStyleId);
|
|
3251
|
+
if (!siteStyle) return current;
|
|
3252
|
+
const models = buildSiteChromeLookModels({
|
|
3253
|
+
state: current,
|
|
3254
|
+
siteStyle,
|
|
3255
|
+
headerSelectionContext,
|
|
3256
|
+
footerSelectionContext
|
|
3257
|
+
});
|
|
3258
|
+
const nextLookId = planSiteChromeFooterLayoutSelection({
|
|
3259
|
+
layoutId: id,
|
|
3260
|
+
currentLookId: current.previewed.footerLookId ?? models.footer.renderedLookId
|
|
3261
|
+
});
|
|
3262
|
+
return nextLookId ? previewFooterLook(current, nextLookId) : current;
|
|
3263
|
+
});
|
|
3264
|
+
}, [footerSelectionContext, headerSelectionContext]);
|
|
3265
|
+
const handlePreviewPaletteItem = useCallback((item) => {
|
|
3266
|
+
setState((current) => {
|
|
3267
|
+
if (!current) return current;
|
|
3268
|
+
if (item.kind === "curated") return previewCuratedPalette(current, item.valueKey);
|
|
3269
|
+
return previewSitePalette(current, {
|
|
3270
|
+
paletteId: item.paletteId,
|
|
3271
|
+
colors: item.colors,
|
|
3272
|
+
mode: item.mode,
|
|
3273
|
+
version: item.version
|
|
3274
|
+
});
|
|
3275
|
+
});
|
|
3276
|
+
}, []);
|
|
3277
|
+
const handleCreatePalette = useCallback(() => {
|
|
3278
|
+
setState((current) => current ? createPalette(current) : current);
|
|
3279
|
+
}, []);
|
|
3280
|
+
const handlePaletteLibraryLoaded = useCallback((response) => {
|
|
3281
|
+
setState((current) => current ? reconcilePaletteLibraryActive(current, response.active, response.palettes) : current);
|
|
3282
|
+
}, []);
|
|
3283
|
+
const patchTypography = useCallback((patch) => {
|
|
3284
|
+
setState((current) => {
|
|
3285
|
+
if (!current) return current;
|
|
3286
|
+
const siteStyle = getCuratedSiteStyle(current.previewed.siteStyleId);
|
|
3287
|
+
if (!siteStyle) return current;
|
|
3288
|
+
return applyTypographyDraftPatch(current, planSiteStylePreviewChange({
|
|
3289
|
+
siteStyle,
|
|
3290
|
+
selection: current.previewed,
|
|
3291
|
+
baseTheme: theme,
|
|
3292
|
+
headerSelectionContext,
|
|
3293
|
+
footerSelectionContext
|
|
3294
|
+
}).themeOverlay.typography, patch);
|
|
3295
|
+
});
|
|
3296
|
+
}, [
|
|
3297
|
+
footerSelectionContext,
|
|
3298
|
+
headerSelectionContext,
|
|
3299
|
+
theme
|
|
3300
|
+
]);
|
|
3301
|
+
const handleHeadingTypographyChange = useCallback((patch) => {
|
|
3302
|
+
patchTypography({
|
|
3303
|
+
kind: "heading",
|
|
3304
|
+
patch
|
|
3305
|
+
});
|
|
3306
|
+
}, [patchTypography]);
|
|
3307
|
+
const handleBodyTypographyChange = useCallback((patch) => {
|
|
3308
|
+
patchTypography({
|
|
3309
|
+
kind: "body",
|
|
3310
|
+
patch
|
|
3311
|
+
});
|
|
3312
|
+
}, [patchTypography]);
|
|
3313
|
+
const handleTypographyScaleChange = useCallback((scale) => {
|
|
3314
|
+
patchTypography({
|
|
3315
|
+
kind: "scale",
|
|
3316
|
+
scale
|
|
3317
|
+
});
|
|
3318
|
+
}, [patchTypography]);
|
|
3319
|
+
const handleResetTypography = useCallback(() => {
|
|
3320
|
+
setState((current) => current ? resetTypographyToSaved(current) : current);
|
|
3321
|
+
}, []);
|
|
3322
|
+
const handleTokenOverride = useCallback((role, hex) => {
|
|
3323
|
+
setState((current) => {
|
|
3324
|
+
if (!current) return current;
|
|
3325
|
+
const palette = palettePreviewProjection(current.previewed.palette);
|
|
3326
|
+
if (palette.kind === "invalid") return current;
|
|
3327
|
+
if (!(role in palette.colors)) return current;
|
|
3328
|
+
const nextColors = paletteColorsSchema.safeParse({
|
|
3329
|
+
...palette.colors,
|
|
3330
|
+
[role]: hex
|
|
3331
|
+
});
|
|
3332
|
+
return nextColors.success ? setPaletteColors(current, nextColors.data) : current;
|
|
3333
|
+
});
|
|
3334
|
+
}, []);
|
|
3335
|
+
const handleResetOverrides = useCallback(() => {
|
|
3336
|
+
setState((current) => {
|
|
3337
|
+
if (!current) return current;
|
|
3338
|
+
const palette = palettePreviewProjection(current.previewed.palette);
|
|
3339
|
+
const sourceValueKey = palette.kind === "curated" ? palette.valueKey : palette.kind === "curated-fork" ? palette.sourceValueKey : null;
|
|
3340
|
+
if (!sourceValueKey) return current;
|
|
3341
|
+
const curated = findCuratedPalette(sourceValueKey);
|
|
3342
|
+
return curated ? setPaletteColors(current, curated.colors) : current;
|
|
3343
|
+
});
|
|
3344
|
+
}, []);
|
|
3345
|
+
const handleToggleRow = useCallback((row) => {
|
|
3346
|
+
if (row === "typography") setTypographySurface(typographyOverviewSurface);
|
|
3347
|
+
setState((current) => current ? toggleRow(current, row) : current);
|
|
3348
|
+
}, []);
|
|
3349
|
+
const handleCancel = useCallback(() => {
|
|
3350
|
+
setTypographySurface(typographyOverviewSurface);
|
|
3351
|
+
setState((current) => current ? cancelPreview(current) : current);
|
|
3352
|
+
}, []);
|
|
3353
|
+
const handleDismissWarnings = useCallback(() => {
|
|
3354
|
+
setState((current) => current ? dismissWarnings(current) : current);
|
|
3355
|
+
}, []);
|
|
3356
|
+
const handleApply = useCallback(async (retry = false) => {
|
|
3357
|
+
const current = stateRef.current;
|
|
3358
|
+
let live = current;
|
|
3359
|
+
if (current && retry) try {
|
|
3360
|
+
const paletteAuthority = await apiClient({
|
|
3361
|
+
endpoint: "listSiteThemePalettes",
|
|
3362
|
+
params: { siteId }
|
|
3363
|
+
}).then(unwrapResponse);
|
|
3364
|
+
live = prepareStalePaletteRetry(reconcilePaletteLibraryActive(current, paletteAuthority.active, paletteAuthority.palettes), { sitePalettes: paletteAuthority.palettes });
|
|
3365
|
+
} catch (error) {
|
|
3366
|
+
const message = error instanceof Error ? error.message : "Unable to refresh palette authority. Your palette draft is still here.";
|
|
3367
|
+
setState((latest) => latest ? markApplyFailed(latest, message, "stale") : latest);
|
|
3368
|
+
return;
|
|
3369
|
+
}
|
|
3370
|
+
if (!live || !isPreviewingChange(live)) return;
|
|
3371
|
+
if (!deriveStyleConfiguratorCapabilities(live).canApplyStaged) return;
|
|
3372
|
+
if (live !== current) {
|
|
3373
|
+
stateRef.current = live;
|
|
3374
|
+
setState(live);
|
|
3375
|
+
}
|
|
3376
|
+
const previewed = live.previewed;
|
|
3377
|
+
const siteStyle = getCuratedSiteStyle(previewed.siteStyleId);
|
|
3378
|
+
if (!siteStyle) return;
|
|
3379
|
+
const compiled = planSiteStylePreviewChange({
|
|
3380
|
+
siteStyle,
|
|
3381
|
+
selection: previewed,
|
|
3382
|
+
baseTheme: theme,
|
|
3383
|
+
headerSelectionContext,
|
|
3384
|
+
footerSelectionContext
|
|
3385
|
+
});
|
|
3386
|
+
await runnerRef.current.run({
|
|
3387
|
+
optimistic: () => {
|
|
3388
|
+
applyStarted("style-configurator");
|
|
3389
|
+
setState((current) => current ? markApplySaving(current) : current);
|
|
3390
|
+
},
|
|
3391
|
+
network: async () => {
|
|
3392
|
+
const body = buildApplySiteStyleSelectionBody({
|
|
3393
|
+
base: live.base,
|
|
3394
|
+
previewed: {
|
|
3395
|
+
...previewed,
|
|
3396
|
+
buttonPersonalityId: compiled.resolvedSelections.buttonPersonalityId,
|
|
3397
|
+
headerLayoutId: compiled.resolvedSelections.headerLayoutId,
|
|
3398
|
+
headerStyleId: compiled.resolvedSelections.headerStyleId,
|
|
3399
|
+
headerLookId: compiled.resolvedSelections.headerLookId,
|
|
3400
|
+
typography: compiled.themeOverlay.typography
|
|
3401
|
+
},
|
|
3402
|
+
selectionId
|
|
3403
|
+
});
|
|
3404
|
+
if (!body.ok) throw new Error(paletteApplyPlanErrorMessage(body.error));
|
|
3405
|
+
return unwrapResponse(await apiClient({
|
|
3406
|
+
endpoint: "applySiteStyleSelection",
|
|
3407
|
+
params: { siteId },
|
|
3408
|
+
body: body.body
|
|
3409
|
+
}));
|
|
3410
|
+
},
|
|
3411
|
+
onSuccess: (saved) => {
|
|
3412
|
+
const persisted = selectionSnapshotFromApplySiteStyleSelectionResponse(saved, previewed);
|
|
3413
|
+
const historyEntry = styleConfiguratorHistoryEntryForPersistedSelection(live, persisted);
|
|
3414
|
+
setState((current) => current ? markApplySaved(current, persisted) : current);
|
|
3415
|
+
if (historyEntry) siteChromeCustomize?.siteStyleHistory?.recordAppliedSelection(historyEntry);
|
|
3416
|
+
applySucceeded("style-configurator");
|
|
3417
|
+
startRefreshTransition(() => {
|
|
3418
|
+
router.refresh();
|
|
3419
|
+
});
|
|
3420
|
+
},
|
|
3421
|
+
onError: (error) => {
|
|
3422
|
+
applyFailed("style-configurator");
|
|
3423
|
+
const applyError = classifyStyleApplyError(error);
|
|
3424
|
+
if (applyError.kind === "stale") startRefreshTransition(() => {
|
|
3425
|
+
router.refresh();
|
|
3426
|
+
});
|
|
3427
|
+
const message = applyError.message;
|
|
3428
|
+
setState((current) => current ? markApplyFailed(current, message, applyError.kind === "stale" ? "stale" : "retryable") : current);
|
|
3429
|
+
}
|
|
3430
|
+
});
|
|
3431
|
+
}, [
|
|
3432
|
+
apiClient,
|
|
3433
|
+
footerSelectionContext,
|
|
3434
|
+
headerSelectionContext,
|
|
3435
|
+
applyFailed,
|
|
3436
|
+
applyStarted,
|
|
3437
|
+
applySucceeded,
|
|
3438
|
+
router,
|
|
3439
|
+
selectionId,
|
|
3440
|
+
siteChromeCustomize?.siteStyleHistory,
|
|
3441
|
+
siteId,
|
|
3442
|
+
startRefreshTransition,
|
|
3443
|
+
theme
|
|
3444
|
+
]);
|
|
3445
|
+
if (!state || !baseSnapshot) return /* @__PURE__ */ jsx("p", {
|
|
3446
|
+
className: "text-sm text-muted-foreground",
|
|
3447
|
+
children: "Loading design controls..."
|
|
2951
3448
|
});
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
onChange: (event) => onChange(event.currentTarget.value),
|
|
2962
|
-
disabled,
|
|
2963
|
-
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",
|
|
2964
|
-
children: options.map((option) => /* @__PURE__ */ jsx("option", {
|
|
2965
|
-
value: option.value,
|
|
2966
|
-
children: option.label
|
|
2967
|
-
}, option.value))
|
|
2968
|
-
})]
|
|
3449
|
+
const applyAllowed = canApplySiteStyle(siteStyleAccess);
|
|
3450
|
+
const stagedCapabilities = deriveStyleConfiguratorCapabilities(state);
|
|
3451
|
+
const previewingChange = isPreviewingChange(state);
|
|
3452
|
+
const saving = stagedCapabilities.isApplyingStaged || isRefreshPending;
|
|
3453
|
+
const aggregateMutationControlsDisabled = saving || !stagedCapabilities.canPreviewStaged;
|
|
3454
|
+
const currentSiteStyle = getCuratedSiteStyle(state.previewed.siteStyleId);
|
|
3455
|
+
if (!currentSiteStyle) return /* @__PURE__ */ jsx("p", {
|
|
3456
|
+
className: "text-sm text-muted-foreground",
|
|
3457
|
+
children: "This site uses a Site Style that cannot be configured here."
|
|
2969
3458
|
});
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
3459
|
+
const currentPersonality = findButtonPersonality(state.previewed.buttonPersonalityId);
|
|
3460
|
+
const currentPalette = palettePreviewProjection(state.previewed.palette);
|
|
3461
|
+
const paletteMutation = paletteMutationCapability(state);
|
|
3462
|
+
const paletteControlsDisabled = saving || !stagedCapabilities.canPreviewStaged || paletteMutation.kind !== "editable";
|
|
3463
|
+
const currentCuratedValueKey = currentPalette.kind === "curated" ? currentPalette.valueKey : currentPalette.kind === "curated-fork" ? currentPalette.sourceValueKey : null;
|
|
3464
|
+
const currentCuratedPalette = currentCuratedValueKey ? findCuratedPalette(currentCuratedValueKey) : null;
|
|
3465
|
+
const paletteIsCustom = currentPalette.kind !== "invalid" && (!currentCuratedPalette || currentPalette.mode !== currentCuratedPalette.mode || !paletteColorsEqual(currentPalette.colors, currentCuratedPalette.colors));
|
|
3466
|
+
const currentTypography = planSiteStylePreviewChange({
|
|
3467
|
+
siteStyle: currentSiteStyle,
|
|
3468
|
+
selection: state.previewed,
|
|
3469
|
+
baseTheme: theme,
|
|
3470
|
+
headerSelectionContext,
|
|
3471
|
+
footerSelectionContext
|
|
3472
|
+
}).themeOverlay.typography;
|
|
3473
|
+
const chromeLookModels = buildSiteChromeLookModels({
|
|
3474
|
+
state,
|
|
3475
|
+
siteStyle: currentSiteStyle,
|
|
3476
|
+
headerSelectionContext,
|
|
3477
|
+
footerSelectionContext
|
|
3478
|
+
});
|
|
3479
|
+
const currentHeaderLayout = getHeaderLayout(state.previewed.headerLayoutId);
|
|
3480
|
+
const currentHeaderStyle = getHeaderStyle(state.previewed.headerStyleId);
|
|
3481
|
+
const currentFooterLayout = getFooterLayout(chromeLookModels.footerLayout.renderedLayoutId);
|
|
3482
|
+
const currentFooterLook = state.previewed.footerLookId ? findFooterLook(state.previewed.footerLookId) : findFooterLook(chromeLookModels.footer.renderedLookId);
|
|
3483
|
+
const headerSurfaceState = siteChromeCustomize?.getSurfaceState("header") ?? { kind: "unavailable" };
|
|
3484
|
+
if (state.expandedRow === "typography" && typographySurface.kind !== "overview") return /* @__PURE__ */ jsxs("div", {
|
|
3485
|
+
className: "flex h-full min-h-0 flex-col",
|
|
3486
|
+
"data-style-configurator-focused-surface": true,
|
|
3487
|
+
children: [typographySurface.kind === "font-picker" ? /* @__PURE__ */ jsx(TypographyFontPickerTakeover, {
|
|
3488
|
+
slot: typographySurface.slot,
|
|
3489
|
+
value: typographySurface.slot === "heading" ? currentTypography.headings.default.family : currentTypography.body.family,
|
|
3490
|
+
catalog: fontCatalog,
|
|
3491
|
+
onBack: () => setTypographySurface(typographyOverviewSurface),
|
|
3492
|
+
onChange: (family) => typographySurface.slot === "heading" ? handleHeadingTypographyChange({ family }) : handleBodyTypographyChange({ family }),
|
|
3493
|
+
disabled: aggregateMutationControlsDisabled
|
|
3494
|
+
}) : /* @__PURE__ */ jsx(TypographyAdvancedTakeover, {
|
|
3495
|
+
typography: currentTypography,
|
|
3496
|
+
catalog: fontCatalog,
|
|
3497
|
+
onBack: () => setTypographySurface(typographyOverviewSurface),
|
|
3498
|
+
onHeadingChange: handleHeadingTypographyChange,
|
|
3499
|
+
onBodyChange: handleBodyTypographyChange,
|
|
3500
|
+
onScaleChange: handleTypographyScaleChange,
|
|
3501
|
+
disabled: aggregateMutationControlsDisabled
|
|
2984
3502
|
}), /* @__PURE__ */ jsx("div", {
|
|
2985
|
-
className: "
|
|
2986
|
-
children:
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3503
|
+
className: "shrink-0 px-3 pb-3",
|
|
3504
|
+
children: /* @__PURE__ */ jsx(StyleConfiguratorSaveControls, {
|
|
3505
|
+
previewingChange,
|
|
3506
|
+
applyAllowed,
|
|
3507
|
+
saving,
|
|
3508
|
+
canCancel: stagedCapabilities.canCancelStaged,
|
|
3509
|
+
canApply: stagedCapabilities.canApplyStaged,
|
|
3510
|
+
saveStatus: state.saveStatus,
|
|
3511
|
+
onCancel: handleCancel,
|
|
3512
|
+
onApply: () => void handleApply(),
|
|
3513
|
+
onRetry: () => void handleApply(true)
|
|
3514
|
+
})
|
|
2994
3515
|
})]
|
|
2995
3516
|
});
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
switch (scale) {
|
|
2999
|
-
case "compact":
|
|
3000
|
-
case "balanced":
|
|
3001
|
-
case "spacious": return scale;
|
|
3002
|
-
case "minorThird": return "compact";
|
|
3003
|
-
case "majorThird": return "balanced";
|
|
3004
|
-
case "perfectFourth": return "spacious";
|
|
3005
|
-
default: return "balanced";
|
|
3006
|
-
}
|
|
3007
|
-
}
|
|
3008
|
-
function TypographyPresetOption({ preset, selected, onSelect, disabled }) {
|
|
3009
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
3010
|
-
type: "button",
|
|
3011
|
-
role: "radio",
|
|
3012
|
-
"aria-checked": selected,
|
|
3013
|
-
onClick: onSelect,
|
|
3014
|
-
disabled,
|
|
3015
|
-
className: cn("w-full rounded-md border px-3 py-2 text-left transition disabled:cursor-not-allowed disabled:opacity-50", selected ? "border-primary bg-primary/5" : "border-border hover:bg-muted/60"),
|
|
3016
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
3017
|
-
className: "flex items-start justify-between gap-3",
|
|
3018
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
3019
|
-
className: "min-w-0",
|
|
3020
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3021
|
-
className: "text-sm font-medium",
|
|
3022
|
-
children: preset.name
|
|
3023
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
3024
|
-
className: "text-xs text-muted-foreground",
|
|
3025
|
-
children: preset.description
|
|
3026
|
-
})]
|
|
3027
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3028
|
-
className: "shrink-0 text-right",
|
|
3029
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3030
|
-
className: "text-[11px] font-semibold uppercase tracking-wide",
|
|
3031
|
-
children: preset.defaultFonts.heading.split(",")[0]
|
|
3032
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
3033
|
-
className: "text-[11px] text-muted-foreground",
|
|
3034
|
-
children: preset.defaultFonts.body.split(",")[0]
|
|
3035
|
-
})]
|
|
3036
|
-
})]
|
|
3037
|
-
})
|
|
3038
|
-
}) });
|
|
3039
|
-
}
|
|
3040
|
-
function TypographyFontSlotPicker({ label, slot, preset, catalog, value, onChange, disabled }) {
|
|
3041
|
-
const [query, setQuery] = useState("");
|
|
3042
|
-
const [manualFamilyDraft, setManualFamilyDraft] = useState(value);
|
|
3043
|
-
const defaultFont = primaryFontFamily(preset.defaultFonts[slot]);
|
|
3044
|
-
const selectedFamily = primaryFontFamily(value);
|
|
3045
|
-
useEffect(() => {
|
|
3046
|
-
setManualFamilyDraft(value);
|
|
3047
|
-
}, [value]);
|
|
3048
|
-
const commitManualFamilyDraft = useCallback(() => {
|
|
3049
|
-
const normalized = normalizeFontFamilyOverride(manualFamilyDraft);
|
|
3050
|
-
if (!normalized) {
|
|
3051
|
-
setManualFamilyDraft(value);
|
|
3052
|
-
return;
|
|
3053
|
-
}
|
|
3054
|
-
onChange(normalized);
|
|
3055
|
-
}, [
|
|
3056
|
-
manualFamilyDraft,
|
|
3057
|
-
onChange,
|
|
3058
|
-
value
|
|
3059
|
-
]);
|
|
3060
|
-
const recordsByFamily = useMemo(() => indexFontsByFamily(catalog.fonts), [catalog.fonts]);
|
|
3061
|
-
const selectedFit = evaluateTypographyFontSlot({
|
|
3062
|
-
slot,
|
|
3063
|
-
policy: preset.slotPolicies[slot],
|
|
3064
|
-
capability: capabilityForFamily(selectedFamily, recordsByFamily)
|
|
3065
|
-
});
|
|
3066
|
-
const recommendedFamilies = preset.recommendedFonts[slot];
|
|
3067
|
-
const recommendedOptions = useMemo(() => uniqueFontFamilies(recommendedFamilies), [recommendedFamilies]);
|
|
3068
|
-
const browseOptions = useMemo(() => {
|
|
3069
|
-
const normalizedQuery = query.trim().toLowerCase();
|
|
3070
|
-
return [...normalizedQuery.length > 0 ? catalog.fonts.filter((font) => font.family.toLowerCase().includes(normalizedQuery)) : catalog.fonts].sort((a, b) => sortFontForPresetSlot(a, b, slot, preset, recordsByFamily)).slice(0, normalizedQuery.length > 0 ? MAX_FONT_RESULTS_WHEN_SEARCHING : MAX_FONT_RESULTS_WHEN_BROWSING);
|
|
3071
|
-
}, [
|
|
3072
|
-
catalog.fonts,
|
|
3073
|
-
preset,
|
|
3074
|
-
query,
|
|
3075
|
-
recordsByFamily,
|
|
3076
|
-
slot
|
|
3077
|
-
]);
|
|
3078
|
-
return /* @__PURE__ */ jsxs("section", {
|
|
3079
|
-
className: "space-y-2",
|
|
3080
|
-
"aria-label": label,
|
|
3517
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3518
|
+
className: "space-y-3",
|
|
3081
3519
|
children: [
|
|
3082
|
-
/* @__PURE__ */
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
})]
|
|
3093
|
-
}), /* @__PURE__ */ jsx(TypographyFontFitBadge, { fit: selectedFit })]
|
|
3520
|
+
state.warnings.length > 0 ? /* @__PURE__ */ jsx(WarningNotice, {
|
|
3521
|
+
warnings: state.warnings,
|
|
3522
|
+
onDismiss: handleDismissWarnings
|
|
3523
|
+
}) : null,
|
|
3524
|
+
/* @__PURE__ */ jsx(SiteStyleRow, {
|
|
3525
|
+
expanded: state.expandedRow === "style",
|
|
3526
|
+
onToggle: () => handleToggleRow("style"),
|
|
3527
|
+
current: currentSiteStyle,
|
|
3528
|
+
onPreview: handlePreviewSiteStyle,
|
|
3529
|
+
disabled: aggregateMutationControlsDisabled
|
|
3094
3530
|
}),
|
|
3095
|
-
/* @__PURE__ */
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
}
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3531
|
+
/* @__PURE__ */ jsx(SiteChromeLookRow, {
|
|
3532
|
+
label: "Header layout",
|
|
3533
|
+
ariaLabel: "Header layout",
|
|
3534
|
+
defaultDescription: "Choose the header structure.",
|
|
3535
|
+
expanded: state.expandedRow === "header-layout",
|
|
3536
|
+
onToggle: () => handleToggleRow("header-layout"),
|
|
3537
|
+
currentId: state.previewed.headerLayoutId,
|
|
3538
|
+
currentLabel: currentHeaderLayout?.label ?? state.previewed.headerLayoutId,
|
|
3539
|
+
scopeDescription: "Changes the header structure on every page.",
|
|
3540
|
+
options: chromeLookModels.headerLayout.options,
|
|
3541
|
+
diagnostics: [],
|
|
3542
|
+
onCycle: (direction) => {
|
|
3543
|
+
const next = cycleSiteChromeLookId(chromeLookModels.headerLayout.options, state.previewed.headerLayoutId, direction);
|
|
3544
|
+
if (next !== void 0) handlePreviewHeaderLayout(next);
|
|
3545
|
+
},
|
|
3546
|
+
onPreview: handlePreviewHeaderLayout,
|
|
3547
|
+
disabled: aggregateMutationControlsDisabled
|
|
3548
|
+
}),
|
|
3549
|
+
/* @__PURE__ */ jsx(SiteChromeLookRow, {
|
|
3550
|
+
label: "Header look",
|
|
3551
|
+
ariaLabel: "Header look",
|
|
3552
|
+
defaultDescription: "Choose the header visual style.",
|
|
3553
|
+
expanded: state.expandedRow === "header-style",
|
|
3554
|
+
onToggle: () => handleToggleRow("header-style"),
|
|
3555
|
+
currentId: state.previewed.headerStyleId,
|
|
3556
|
+
currentLabel: currentHeaderStyle?.label ?? state.previewed.headerStyleId,
|
|
3557
|
+
scopeDescription: "Changes the header surface and link style.",
|
|
3558
|
+
options: chromeLookModels.headerStyle.options,
|
|
3559
|
+
diagnostics: [],
|
|
3560
|
+
onCycle: (direction) => {
|
|
3561
|
+
const next = cycleSiteChromeLookId(chromeLookModels.headerStyle.options, state.previewed.headerStyleId, direction);
|
|
3562
|
+
if (next !== void 0) handlePreviewHeaderStyle(next);
|
|
3563
|
+
},
|
|
3564
|
+
onPreview: handlePreviewHeaderStyle,
|
|
3565
|
+
disabled: aggregateMutationControlsDisabled,
|
|
3566
|
+
extraControls: isHeaderMenuSurfaceState(headerSurfaceState) ? /* @__PURE__ */ jsx(HeaderMenuControls, {
|
|
3567
|
+
state: headerSurfaceState,
|
|
3568
|
+
disabled: saving,
|
|
3569
|
+
onMenuFontChange: siteChromeCustomize?.setHeaderMenuFont,
|
|
3570
|
+
onMenuFontSizeChange: siteChromeCustomize?.setHeaderMenuFontSize
|
|
3571
|
+
}) : null
|
|
3572
|
+
}),
|
|
3573
|
+
/* @__PURE__ */ jsx(SiteChromeLookRow, {
|
|
3574
|
+
label: "Footer layout",
|
|
3575
|
+
ariaLabel: "Footer layout",
|
|
3576
|
+
defaultDescription: "Choose the footer structure.",
|
|
3577
|
+
expanded: state.expandedRow === "footer-layout",
|
|
3578
|
+
onToggle: () => handleToggleRow("footer-layout"),
|
|
3579
|
+
currentId: chromeLookModels.footerLayout.renderedLayoutId,
|
|
3580
|
+
currentLabel: currentFooterLayout?.label ?? chromeLookModels.footerLayout.renderedLayoutId,
|
|
3581
|
+
scopeDescription: "Changes the footer structure on every page.",
|
|
3582
|
+
options: chromeLookModels.footerLayout.options,
|
|
3583
|
+
diagnostics: [],
|
|
3584
|
+
onCycle: (direction) => {
|
|
3585
|
+
const next = cycleSiteChromeLookId(chromeLookModels.footerLayout.options, chromeLookModels.footerLayout.renderedLayoutId, direction);
|
|
3586
|
+
if (next !== void 0) handlePreviewFooterLayout(next);
|
|
3587
|
+
},
|
|
3588
|
+
onPreview: handlePreviewFooterLayout,
|
|
3589
|
+
disabled: aggregateMutationControlsDisabled
|
|
3590
|
+
}),
|
|
3591
|
+
/* @__PURE__ */ jsx(SiteChromeLookRow, {
|
|
3592
|
+
label: "Footer look",
|
|
3593
|
+
ariaLabel: "Footer look",
|
|
3594
|
+
defaultDescription: "Use the footer look chosen for this site style.",
|
|
3595
|
+
expanded: state.expandedRow === "footer",
|
|
3596
|
+
onToggle: () => handleToggleRow("footer"),
|
|
3597
|
+
currentId: state.previewed.footerLookId,
|
|
3598
|
+
currentLabel: state.previewed.footerLookId ? currentFooterLook?.label ?? "Unknown footer Look" : `${currentFooterLook?.label ?? "Site style"} (default)`,
|
|
3599
|
+
scopeDescription: "Changes the footer on every page.",
|
|
3600
|
+
options: chromeLookModels.footer.options,
|
|
3601
|
+
diagnostics: chromeLookModels.footer.diagnostics,
|
|
3602
|
+
onCycle: (direction) => {
|
|
3603
|
+
const next = cycleSiteChromeLookId(chromeLookModels.footer.options, state.previewed.footerLookId, direction);
|
|
3604
|
+
if (next !== void 0) handlePreviewFooterLook(next);
|
|
3605
|
+
},
|
|
3606
|
+
onPreview: handlePreviewFooterLook,
|
|
3607
|
+
disabled: aggregateMutationControlsDisabled
|
|
3608
|
+
}),
|
|
3609
|
+
/* @__PURE__ */ jsx(PersonalityRow, {
|
|
3610
|
+
expanded: state.expandedRow === "buttons",
|
|
3611
|
+
onToggle: () => handleToggleRow("buttons"),
|
|
3612
|
+
siteStyle: currentSiteStyle,
|
|
3613
|
+
currentId: state.previewed.buttonPersonalityId,
|
|
3614
|
+
currentLabel: currentPersonality?.name ?? state.previewed.buttonPersonalityId,
|
|
3615
|
+
onPreview: handlePreviewPersonality,
|
|
3616
|
+
disabled: aggregateMutationControlsDisabled
|
|
3617
|
+
}),
|
|
3618
|
+
/* @__PURE__ */ jsx(TypographyRow, {
|
|
3619
|
+
expanded: state.expandedRow === "typography",
|
|
3620
|
+
onToggle: () => handleToggleRow("typography"),
|
|
3621
|
+
typography: currentTypography,
|
|
3622
|
+
catalog: fontCatalog,
|
|
3623
|
+
currentLabel: `${primaryFontFamily(currentTypography.headings.default.family)} / ${primaryFontFamily(currentTypography.body.family)}`,
|
|
3624
|
+
onChooseFont: (slot) => setTypographySurface({
|
|
3625
|
+
kind: "font-picker",
|
|
3626
|
+
slot
|
|
3627
|
+
}),
|
|
3628
|
+
onOpenAdvanced: () => setTypographySurface({ kind: "advanced" }),
|
|
3629
|
+
onReset: handleResetTypography,
|
|
3630
|
+
disabled: aggregateMutationControlsDisabled
|
|
3120
3631
|
}),
|
|
3121
|
-
/* @__PURE__ */
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
children: catalog.message
|
|
3139
|
-
}) : null,
|
|
3140
|
-
browseOptions.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
3141
|
-
className: "max-h-56 space-y-1 overflow-y-auto pr-1",
|
|
3142
|
-
children: browseOptions.map((font) => /* @__PURE__ */ jsx(FontFamilyOption, {
|
|
3143
|
-
family: font.family,
|
|
3144
|
-
selected: selectedFamily === font.family,
|
|
3145
|
-
fit: evaluateTypographyFontSlot({
|
|
3146
|
-
slot,
|
|
3147
|
-
policy: preset.slotPolicies[slot],
|
|
3148
|
-
capability: capabilityFromFontRecord(font)
|
|
3149
|
-
}),
|
|
3150
|
-
onSelect: () => onChange(font.family),
|
|
3151
|
-
disabled
|
|
3152
|
-
}, font.family))
|
|
3153
|
-
}) : catalog.kind === "loaded" ? /* @__PURE__ */ jsx("p", {
|
|
3154
|
-
className: "text-xs text-muted-foreground",
|
|
3155
|
-
children: "No matching Google Fonts."
|
|
3156
|
-
}) : null
|
|
3157
|
-
]
|
|
3632
|
+
/* @__PURE__ */ jsx(PaletteRow, {
|
|
3633
|
+
expanded: state.expandedRow === "palette",
|
|
3634
|
+
onToggle: () => handleToggleRow("palette"),
|
|
3635
|
+
apiClient,
|
|
3636
|
+
siteId,
|
|
3637
|
+
siteStyle: currentSiteStyle,
|
|
3638
|
+
palette: currentPalette,
|
|
3639
|
+
committedSelection: committedPaletteForSnapshot(state.base.palette)?.selection ?? null,
|
|
3640
|
+
onPreview: handlePreviewPaletteItem,
|
|
3641
|
+
onCreate: handleCreatePalette,
|
|
3642
|
+
onLibraryLoaded: handlePaletteLibraryLoaded,
|
|
3643
|
+
isCustom: paletteIsCustom,
|
|
3644
|
+
onTokenChange: handleTokenOverride,
|
|
3645
|
+
onReset: handleResetOverrides,
|
|
3646
|
+
mutationCapability: paletteMutation,
|
|
3647
|
+
disabled: saving || !applyAllowed,
|
|
3648
|
+
mutationDisabled: paletteControlsDisabled || !applyAllowed
|
|
3158
3649
|
}),
|
|
3159
|
-
/* @__PURE__ */
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
onBlur: commitManualFamilyDraft,
|
|
3170
|
-
onKeyDown: (event) => {
|
|
3171
|
-
if (event.key !== "Enter") return;
|
|
3172
|
-
event.currentTarget.blur();
|
|
3173
|
-
},
|
|
3174
|
-
disabled,
|
|
3175
|
-
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"
|
|
3176
|
-
})]
|
|
3650
|
+
/* @__PURE__ */ jsx(StyleConfiguratorSaveControls, {
|
|
3651
|
+
previewingChange,
|
|
3652
|
+
applyAllowed,
|
|
3653
|
+
saving,
|
|
3654
|
+
canCancel: stagedCapabilities.canCancelStaged,
|
|
3655
|
+
canApply: stagedCapabilities.canApplyStaged,
|
|
3656
|
+
saveStatus: state.saveStatus,
|
|
3657
|
+
onCancel: handleCancel,
|
|
3658
|
+
onApply: () => void handleApply(),
|
|
3659
|
+
onRetry: () => void handleApply(true)
|
|
3177
3660
|
})
|
|
3178
3661
|
]
|
|
3179
3662
|
});
|
|
3180
3663
|
}
|
|
3181
|
-
function
|
|
3182
|
-
return /* @__PURE__ */ jsxs(
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3664
|
+
function StyleConfiguratorSaveControls({ previewingChange, applyAllowed, saving, canCancel, canApply, saveStatus, onCancel, onApply, onRetry }) {
|
|
3665
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3666
|
+
previewingChange ? /* @__PURE__ */ jsxs("div", {
|
|
3667
|
+
className: "flex items-center gap-2 pt-2",
|
|
3668
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
3669
|
+
type: "button",
|
|
3670
|
+
size: "sm",
|
|
3671
|
+
variant: "outline",
|
|
3672
|
+
onClick: onCancel,
|
|
3673
|
+
disabled: !canCancel || saving,
|
|
3674
|
+
children: "Cancel"
|
|
3675
|
+
}), applyAllowed ? /* @__PURE__ */ jsx(Button, {
|
|
3676
|
+
type: "button",
|
|
3677
|
+
size: "sm",
|
|
3678
|
+
onClick: onApply,
|
|
3679
|
+
disabled: !canApply || saving,
|
|
3680
|
+
children: saving ? "Applying…" : "Apply"
|
|
3681
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
3682
|
+
className: "text-xs text-muted-foreground",
|
|
3683
|
+
children: "Preview only — ask an admin to apply."
|
|
3684
|
+
})]
|
|
3685
|
+
}) : null,
|
|
3686
|
+
saveStatus.kind === "saved" ? /* @__PURE__ */ jsx("p", {
|
|
3687
|
+
className: "text-xs text-success",
|
|
3688
|
+
children: "Saved."
|
|
3689
|
+
}) : null,
|
|
3690
|
+
saveStatus.kind === "failed" ? /* @__PURE__ */ jsxs("div", {
|
|
3691
|
+
role: "status",
|
|
3692
|
+
className: "flex items-center gap-2 text-xs text-destructive",
|
|
3693
|
+
children: [/* @__PURE__ */ jsx("span", { children: saveStatus.message }), saveStatus.failureKind === "stale" && previewingChange && applyAllowed ? /* @__PURE__ */ jsx(Button, {
|
|
3694
|
+
type: "button",
|
|
3695
|
+
size: "sm",
|
|
3696
|
+
variant: "outline",
|
|
3697
|
+
onClick: onRetry,
|
|
3698
|
+
disabled: saving,
|
|
3699
|
+
children: "Retry"
|
|
3700
|
+
}) : null]
|
|
3701
|
+
}) : null
|
|
3702
|
+
] });
|
|
3192
3703
|
}
|
|
3193
|
-
function
|
|
3194
|
-
return /* @__PURE__ */ jsx(
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
children:
|
|
3704
|
+
function StyleRowFrame({ label, currentLabel, swatch, expanded, onToggle, children }) {
|
|
3705
|
+
return /* @__PURE__ */ jsx(Collapsible, {
|
|
3706
|
+
open: expanded,
|
|
3707
|
+
onOpenChange: onToggle,
|
|
3708
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3709
|
+
className: "rounded-md border bg-background",
|
|
3710
|
+
children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
3711
|
+
asChild: true,
|
|
3712
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
3713
|
+
type: "button",
|
|
3714
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-accent/30",
|
|
3715
|
+
"aria-expanded": expanded,
|
|
3716
|
+
children: [
|
|
3717
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: cn("h-4 w-4 transition", expanded && "rotate-90") }),
|
|
3718
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3719
|
+
className: "flex-1 min-w-0",
|
|
3720
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3721
|
+
className: "text-xs uppercase tracking-wide text-muted-foreground",
|
|
3722
|
+
children: label
|
|
3723
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
3724
|
+
className: "truncate text-sm font-medium",
|
|
3725
|
+
children: currentLabel
|
|
3726
|
+
})]
|
|
3727
|
+
}),
|
|
3728
|
+
swatch ? /* @__PURE__ */ jsx("span", {
|
|
3729
|
+
className: "h-5 w-5 shrink-0 rounded-full border border-black/10",
|
|
3730
|
+
style: { backgroundColor: swatch },
|
|
3731
|
+
"aria-hidden": "true"
|
|
3732
|
+
}) : null
|
|
3733
|
+
]
|
|
3734
|
+
})
|
|
3735
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", {
|
|
3736
|
+
className: "border-t px-3 py-3",
|
|
3737
|
+
children
|
|
3738
|
+
}) })]
|
|
3739
|
+
})
|
|
3198
3740
|
});
|
|
3199
3741
|
}
|
|
3200
|
-
function
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3742
|
+
function SiteStyleRow({ expanded, onToggle, current, onPreview, disabled }) {
|
|
3743
|
+
return /* @__PURE__ */ jsx(StyleRowFrame, {
|
|
3744
|
+
label: "Site style",
|
|
3745
|
+
currentLabel: current.name,
|
|
3746
|
+
expanded,
|
|
3747
|
+
onToggle,
|
|
3748
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
3749
|
+
role: "radiogroup",
|
|
3750
|
+
"aria-label": "Site style",
|
|
3751
|
+
className: "list-none space-y-1 p-0",
|
|
3752
|
+
children: curatedSiteStyles.map((style) => /* @__PURE__ */ jsx(PickerOption, {
|
|
3753
|
+
selected: style.id === current.id,
|
|
3754
|
+
label: style.name,
|
|
3755
|
+
description: style.description,
|
|
3756
|
+
onSelect: () => onPreview(style.id),
|
|
3757
|
+
disabled
|
|
3758
|
+
}, style.id))
|
|
3759
|
+
})
|
|
3204
3760
|
});
|
|
3205
|
-
const requestedClientRef = useRef(null);
|
|
3206
|
-
useEffect(() => {
|
|
3207
|
-
if (!enabled) return;
|
|
3208
|
-
if (requestedClientRef.current === apiClient) return;
|
|
3209
|
-
requestedClientRef.current = apiClient;
|
|
3210
|
-
let cancelled = false;
|
|
3211
|
-
setCatalog({
|
|
3212
|
-
kind: "loading",
|
|
3213
|
-
fonts: []
|
|
3214
|
-
});
|
|
3215
|
-
async function loadFonts() {
|
|
3216
|
-
try {
|
|
3217
|
-
const fonts = unwrapResponse(await apiClient({ endpoint: "listFonts" }));
|
|
3218
|
-
if (!cancelled) setCatalog({
|
|
3219
|
-
kind: "loaded",
|
|
3220
|
-
fonts: Array.isArray(fonts) ? fonts : []
|
|
3221
|
-
});
|
|
3222
|
-
} catch (error) {
|
|
3223
|
-
if (!cancelled) setCatalog({
|
|
3224
|
-
kind: "failed",
|
|
3225
|
-
fonts: [],
|
|
3226
|
-
message: error instanceof Error ? error.message : "Unable to load the font catalog."
|
|
3227
|
-
});
|
|
3228
|
-
}
|
|
3229
|
-
}
|
|
3230
|
-
loadFonts();
|
|
3231
|
-
return () => {
|
|
3232
|
-
cancelled = true;
|
|
3233
|
-
};
|
|
3234
|
-
}, [apiClient, enabled]);
|
|
3235
|
-
return catalog;
|
|
3236
|
-
}
|
|
3237
|
-
function indexFontsByFamily(fonts) {
|
|
3238
|
-
return new Map(fonts.map((font) => [font.family.toLowerCase(), font]));
|
|
3239
|
-
}
|
|
3240
|
-
function capabilityForFamily(family, recordsByFamily) {
|
|
3241
|
-
const record = recordsByFamily.get(family.toLowerCase());
|
|
3242
|
-
if (record) return capabilityFromFontRecord(record);
|
|
3243
|
-
return {
|
|
3244
|
-
source: "unknown",
|
|
3245
|
-
family,
|
|
3246
|
-
category: "unknown",
|
|
3247
|
-
variants: []
|
|
3248
|
-
};
|
|
3249
|
-
}
|
|
3250
|
-
function capabilityFromFontRecord(font) {
|
|
3251
|
-
return {
|
|
3252
|
-
source: "google",
|
|
3253
|
-
family: font.family,
|
|
3254
|
-
category: normalizeGoogleFontCategory(font.category),
|
|
3255
|
-
variants: font.variants
|
|
3256
|
-
};
|
|
3257
|
-
}
|
|
3258
|
-
function normalizeGoogleFontCategory(category) {
|
|
3259
|
-
switch (category) {
|
|
3260
|
-
case "serif":
|
|
3261
|
-
case "sans-serif":
|
|
3262
|
-
case "display":
|
|
3263
|
-
case "handwriting":
|
|
3264
|
-
case "monospace": return category;
|
|
3265
|
-
default: return "unknown";
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
function sortFontForPresetSlot(a, b, slot, preset, recordsByFamily) {
|
|
3269
|
-
const aFit = evaluateTypographyFontSlot({
|
|
3270
|
-
slot,
|
|
3271
|
-
policy: preset.slotPolicies[slot],
|
|
3272
|
-
capability: capabilityForFamily(a.family, recordsByFamily)
|
|
3273
|
-
});
|
|
3274
|
-
const bFit = evaluateTypographyFontSlot({
|
|
3275
|
-
slot,
|
|
3276
|
-
policy: preset.slotPolicies[slot],
|
|
3277
|
-
capability: capabilityForFamily(b.family, recordsByFamily)
|
|
3278
|
-
});
|
|
3279
|
-
const fitDelta = typographyFontFitRank(aFit.kind) - typographyFontFitRank(bFit.kind);
|
|
3280
|
-
if (fitDelta !== 0) return fitDelta;
|
|
3281
|
-
const popularityDelta = (a.popularity ?? Infinity) - (b.popularity ?? Infinity);
|
|
3282
|
-
if (popularityDelta !== 0) return popularityDelta;
|
|
3283
|
-
return a.family.localeCompare(b.family);
|
|
3284
|
-
}
|
|
3285
|
-
function typographyFontFitRank(kind) {
|
|
3286
|
-
switch (kind) {
|
|
3287
|
-
case "recommended": return 0;
|
|
3288
|
-
case "compatible": return 1;
|
|
3289
|
-
case "limited": return 2;
|
|
3290
|
-
case "risky": return 3;
|
|
3291
|
-
case "unknown": return 4;
|
|
3292
|
-
default: return kind;
|
|
3293
|
-
}
|
|
3294
|
-
}
|
|
3295
|
-
function typographyFontFitLabel(kind) {
|
|
3296
|
-
switch (kind) {
|
|
3297
|
-
case "recommended": return "Recommended";
|
|
3298
|
-
case "compatible": return "Compatible";
|
|
3299
|
-
case "limited": return "Limited";
|
|
3300
|
-
case "risky": return "Risky";
|
|
3301
|
-
case "unknown": return "Unknown";
|
|
3302
|
-
default: return kind;
|
|
3303
|
-
}
|
|
3304
|
-
}
|
|
3305
|
-
function primaryFontFamily(cssFamily) {
|
|
3306
|
-
return cssFamily.split(",")[0]?.trim().replace(/^["']|["']$/gu, "") || cssFamily;
|
|
3307
3761
|
}
|
|
3308
|
-
function
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3762
|
+
function PersonalityRow({ expanded, onToggle, siteStyle, currentId, currentLabel, onPreview, disabled }) {
|
|
3763
|
+
return /* @__PURE__ */ jsx(StyleRowFrame, {
|
|
3764
|
+
label: "Button style",
|
|
3765
|
+
currentLabel,
|
|
3766
|
+
expanded,
|
|
3767
|
+
onToggle,
|
|
3768
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
3769
|
+
role: "radiogroup",
|
|
3770
|
+
"aria-label": "Button style",
|
|
3771
|
+
className: "list-none space-y-1 p-0",
|
|
3772
|
+
children: useMemo(() => requireEntriesForCuratedChoices(buttonPersonalities, siteStyle.buttonPersonalityChoices), [siteStyle.buttonPersonalityChoices]).map((personality) => /* @__PURE__ */ jsx(PickerOption, {
|
|
3773
|
+
selected: personality.id === currentId,
|
|
3774
|
+
label: personality.name,
|
|
3775
|
+
description: personality.description,
|
|
3776
|
+
onSelect: () => onPreview(personality.id),
|
|
3777
|
+
disabled
|
|
3778
|
+
}, personality.id))
|
|
3779
|
+
})
|
|
3780
|
+
});
|
|
3319
3781
|
}
|
|
3320
|
-
function
|
|
3321
|
-
|
|
3322
|
-
|
|
3782
|
+
function TypographyRow({ expanded, onToggle, typography, catalog, currentLabel, onChooseFont, onOpenAdvanced, onReset, disabled }) {
|
|
3783
|
+
return /* @__PURE__ */ jsx(StyleRowFrame, {
|
|
3784
|
+
label: "Typography",
|
|
3785
|
+
currentLabel,
|
|
3786
|
+
expanded,
|
|
3787
|
+
onToggle,
|
|
3788
|
+
children: /* @__PURE__ */ jsx(TypographyOverviewContent, {
|
|
3789
|
+
typography,
|
|
3790
|
+
catalog,
|
|
3791
|
+
onChooseFont,
|
|
3792
|
+
onOpenAdvanced,
|
|
3793
|
+
onReset,
|
|
3794
|
+
disabled
|
|
3795
|
+
})
|
|
3796
|
+
});
|
|
3323
3797
|
}
|
|
3324
3798
|
function SiteChromeLookRow({ label, ariaLabel, defaultDescription, catalog, options = [{
|
|
3325
3799
|
id: null,
|
|
@@ -3417,93 +3891,254 @@ function HeaderMenuControls({ state, disabled, onMenuFontChange, onMenuFontSizeC
|
|
|
3417
3891
|
})]
|
|
3418
3892
|
});
|
|
3419
3893
|
}
|
|
3420
|
-
function PaletteRow({ expanded, onToggle,
|
|
3421
|
-
const
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3894
|
+
function PaletteRow({ expanded, onToggle, apiClient, siteId, siteStyle, palette, committedSelection, onPreview, onCreate, onLibraryLoaded, isCustom, onTokenChange, onReset, mutationCapability, disabled, mutationDisabled }) {
|
|
3895
|
+
const [library, setLibrary] = useState({
|
|
3896
|
+
kind: "idle",
|
|
3897
|
+
palettes: []
|
|
3898
|
+
});
|
|
3899
|
+
const optionRefs = useRef([]);
|
|
3900
|
+
const activeSelection = selectionForPaletteSnapshot(palette) ?? committedSelection;
|
|
3901
|
+
const libraryModel = useMemo(() => buildPaletteLibraryReadModel({
|
|
3902
|
+
active: activeSelection ? {
|
|
3903
|
+
kind: "available",
|
|
3904
|
+
selection: activeSelection
|
|
3905
|
+
} : { kind: "invalid" },
|
|
3906
|
+
sitePalettes: library.palettes,
|
|
3907
|
+
curatedPalettes,
|
|
3908
|
+
recommendations: siteStyle.paletteRecommendations.map((recommendation) => recommendation.id)
|
|
3909
|
+
}), [
|
|
3910
|
+
activeSelection,
|
|
3911
|
+
library.palettes,
|
|
3912
|
+
siteStyle.paletteRecommendations
|
|
3913
|
+
]);
|
|
3914
|
+
useEffect(() => {
|
|
3915
|
+
if (!expanded || library.kind !== "idle") return;
|
|
3916
|
+
setLibrary((current) => ({
|
|
3917
|
+
kind: "loading",
|
|
3918
|
+
palettes: current.palettes
|
|
3919
|
+
}));
|
|
3920
|
+
}, [expanded, library.kind]);
|
|
3921
|
+
useEffect(() => {
|
|
3922
|
+
if (library.kind !== "loading") return;
|
|
3923
|
+
let cancelled = false;
|
|
3924
|
+
apiClient({
|
|
3925
|
+
endpoint: "listSiteThemePalettes",
|
|
3926
|
+
params: { siteId }
|
|
3927
|
+
}).then(unwrapResponse).then((response) => {
|
|
3928
|
+
if (cancelled) return;
|
|
3929
|
+
setLibrary({
|
|
3930
|
+
kind: "loaded",
|
|
3931
|
+
palettes: response.palettes
|
|
3932
|
+
});
|
|
3933
|
+
onLibraryLoaded(response);
|
|
3934
|
+
}).catch((error) => {
|
|
3935
|
+
if (cancelled) return;
|
|
3936
|
+
setLibrary((current) => ({
|
|
3937
|
+
kind: "failed",
|
|
3938
|
+
palettes: current.palettes,
|
|
3939
|
+
message: error instanceof Error ? error.message : "Unable to load palettes."
|
|
3940
|
+
}));
|
|
3941
|
+
});
|
|
3942
|
+
return () => {
|
|
3943
|
+
cancelled = true;
|
|
3944
|
+
};
|
|
3945
|
+
}, [
|
|
3946
|
+
apiClient,
|
|
3947
|
+
library.kind,
|
|
3948
|
+
onLibraryLoaded,
|
|
3949
|
+
siteId
|
|
3950
|
+
]);
|
|
3951
|
+
const items = libraryModel?.ok ? [
|
|
3952
|
+
...libraryModel.model.yours,
|
|
3953
|
+
...libraryModel.model.suggested,
|
|
3954
|
+
...libraryModel.model.more
|
|
3955
|
+
] : [];
|
|
3956
|
+
const currentLabel = palette.kind === "new-site" ? "New palette" : "Selected palette";
|
|
3957
|
+
const onOptionKeyDown = (event, index) => {
|
|
3958
|
+
if (items.length === 0) return;
|
|
3959
|
+
const direction = event.key === "ArrowDown" || event.key === "ArrowRight" ? 1 : event.key === "ArrowUp" || event.key === "ArrowLeft" ? -1 : 0;
|
|
3960
|
+
if (direction === 0) return;
|
|
3961
|
+
event.preventDefault();
|
|
3962
|
+
const nextIndex = (index + direction + items.length) % items.length;
|
|
3963
|
+
const next = items[nextIndex];
|
|
3964
|
+
if (!next) return;
|
|
3965
|
+
onPreview(next);
|
|
3966
|
+
optionRefs.current[nextIndex]?.focus();
|
|
3967
|
+
};
|
|
3427
3968
|
return /* @__PURE__ */ jsxs(StyleRowFrame, {
|
|
3428
3969
|
label: "Palette",
|
|
3429
3970
|
currentLabel,
|
|
3430
|
-
swatch:
|
|
3971
|
+
swatch: palette.kind === "invalid" ? null : palette.colors.primary,
|
|
3431
3972
|
expanded,
|
|
3432
3973
|
onToggle,
|
|
3433
3974
|
children: [
|
|
3434
|
-
/* @__PURE__ */ jsx("p", {
|
|
3435
|
-
className: "mb-3 text-xs text-muted-foreground",
|
|
3436
|
-
children: "These palette bases are recommended for the current Site Style. Choose a base here, then edit exact colours in Palette colours."
|
|
3437
|
-
}),
|
|
3438
3975
|
mutationCapability.kind === "blocked" && mutationCapability.reason === "invalid-palette" ? /* @__PURE__ */ jsx("div", {
|
|
3439
3976
|
role: "status",
|
|
3440
3977
|
className: "mb-3 flex items-center justify-between gap-3 rounded-md border border-muted px-3 py-2 text-xs text-muted-foreground",
|
|
3441
3978
|
children: /* @__PURE__ */ jsx("span", { children: mutationCapability.message })
|
|
3442
3979
|
}) : null,
|
|
3443
|
-
/* @__PURE__ */ jsx("
|
|
3980
|
+
library.kind === "loading" ? /* @__PURE__ */ jsx("p", {
|
|
3981
|
+
className: "text-xs text-muted-foreground",
|
|
3982
|
+
children: "Loading palettes..."
|
|
3983
|
+
}) : null,
|
|
3984
|
+
library.kind === "failed" ? /* @__PURE__ */ jsxs("div", {
|
|
3985
|
+
role: "status",
|
|
3986
|
+
className: "space-y-2 text-xs text-muted-foreground",
|
|
3987
|
+
children: [/* @__PURE__ */ jsx("p", { children: library.message }), /* @__PURE__ */ jsx(Button, {
|
|
3988
|
+
type: "button",
|
|
3989
|
+
size: "sm",
|
|
3990
|
+
variant: "outline",
|
|
3991
|
+
onClick: () => setLibrary({
|
|
3992
|
+
kind: "idle",
|
|
3993
|
+
palettes: library.palettes
|
|
3994
|
+
}),
|
|
3995
|
+
children: "Retry loading palettes"
|
|
3996
|
+
})]
|
|
3997
|
+
}) : null,
|
|
3998
|
+
libraryModel.ok ? /* @__PURE__ */ jsxs("div", {
|
|
3444
3999
|
role: "radiogroup",
|
|
3445
|
-
"aria-label": "Palette",
|
|
3446
|
-
className: "
|
|
3447
|
-
children:
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
4000
|
+
"aria-label": "Palette library",
|
|
4001
|
+
className: "space-y-3",
|
|
4002
|
+
children: [
|
|
4003
|
+
/* @__PURE__ */ jsx(PaletteLibraryGroup, {
|
|
4004
|
+
label: "Your palettes",
|
|
4005
|
+
items: libraryModel.model.yours,
|
|
4006
|
+
offset: 0,
|
|
4007
|
+
optionRefs,
|
|
4008
|
+
onPreview,
|
|
4009
|
+
onOptionKeyDown,
|
|
3455
4010
|
disabled
|
|
3456
|
-
},
|
|
3457
|
-
|
|
3458
|
-
|
|
4011
|
+
}),
|
|
4012
|
+
/* @__PURE__ */ jsx(PaletteLibraryGroup, {
|
|
4013
|
+
label: "Suggested for this style",
|
|
4014
|
+
items: libraryModel.model.suggested,
|
|
4015
|
+
offset: libraryModel.model.yours.length,
|
|
4016
|
+
optionRefs,
|
|
4017
|
+
onPreview,
|
|
4018
|
+
onOptionKeyDown,
|
|
4019
|
+
disabled
|
|
4020
|
+
}),
|
|
4021
|
+
/* @__PURE__ */ jsx(PaletteLibraryGroup, {
|
|
4022
|
+
label: "More palettes",
|
|
4023
|
+
items: libraryModel.model.more,
|
|
4024
|
+
offset: libraryModel.model.yours.length + libraryModel.model.suggested.length,
|
|
4025
|
+
optionRefs,
|
|
4026
|
+
onPreview,
|
|
4027
|
+
onOptionKeyDown,
|
|
4028
|
+
disabled
|
|
4029
|
+
})
|
|
4030
|
+
]
|
|
4031
|
+
}) : /* @__PURE__ */ jsx("p", {
|
|
4032
|
+
role: "status",
|
|
4033
|
+
className: "text-xs text-muted-foreground",
|
|
4034
|
+
children: "Palette details are unavailable."
|
|
4035
|
+
}),
|
|
4036
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
4037
|
+
type: "button",
|
|
4038
|
+
size: "sm",
|
|
4039
|
+
variant: "outline",
|
|
4040
|
+
className: "mt-3",
|
|
4041
|
+
onClick: onCreate,
|
|
4042
|
+
disabled: mutationDisabled,
|
|
4043
|
+
children: [/* @__PURE__ */ jsx(Plus, {
|
|
4044
|
+
"aria-hidden": "true",
|
|
4045
|
+
className: "size-3.5"
|
|
4046
|
+
}), "Create palette"]
|
|
4047
|
+
}),
|
|
4048
|
+
palette.kind !== "invalid" ? /* @__PURE__ */ jsx(PaletteTokenControls, {
|
|
4049
|
+
palette: palette.colors,
|
|
4050
|
+
isCustom,
|
|
4051
|
+
onTokenChange,
|
|
4052
|
+
onReset,
|
|
4053
|
+
disabled: mutationDisabled
|
|
4054
|
+
}) : null
|
|
3459
4055
|
]
|
|
3460
4056
|
});
|
|
3461
4057
|
}
|
|
3462
|
-
function
|
|
3463
|
-
|
|
3464
|
-
return /* @__PURE__ */
|
|
3465
|
-
label:
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
className: "
|
|
3471
|
-
children:
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
})
|
|
3493
|
-
}),
|
|
3494
|
-
isCustom ? /* @__PURE__ */ jsx("div", {
|
|
3495
|
-
className: "flex justify-end",
|
|
3496
|
-
children: /* @__PURE__ */ jsx(Button, {
|
|
3497
|
-
type: "button",
|
|
3498
|
-
variant: "outline",
|
|
3499
|
-
size: "sm",
|
|
3500
|
-
onClick: onReset,
|
|
3501
|
-
disabled,
|
|
3502
|
-
children: "Reset to variant"
|
|
4058
|
+
function PaletteLibraryGroup({ label, items, offset, optionRefs, onPreview, onOptionKeyDown, disabled }) {
|
|
4059
|
+
if (items.length === 0) return null;
|
|
4060
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
4061
|
+
"aria-label": label,
|
|
4062
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
4063
|
+
className: "mb-1.5 text-xs font-medium text-muted-foreground",
|
|
4064
|
+
children: label
|
|
4065
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
4066
|
+
className: "grid grid-cols-4 gap-2",
|
|
4067
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxs("button", {
|
|
4068
|
+
ref: (element) => {
|
|
4069
|
+
optionRefs.current[offset + index] = element;
|
|
4070
|
+
},
|
|
4071
|
+
type: "button",
|
|
4072
|
+
role: "radio",
|
|
4073
|
+
"aria-label": item.accessibleLabel,
|
|
4074
|
+
"aria-checked": item.selected,
|
|
4075
|
+
disabled,
|
|
4076
|
+
onClick: () => onPreview(item),
|
|
4077
|
+
onKeyDown: (event) => onOptionKeyDown(event, offset + index),
|
|
4078
|
+
className: cn("relative h-10 overflow-hidden rounded-md border p-0.5 outline-none transition focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", item.selected ? "border-foreground ring-1 ring-foreground" : "border-border hover:border-foreground/60"),
|
|
4079
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4080
|
+
className: "grid h-full grid-cols-5 overflow-hidden rounded-[3px]",
|
|
4081
|
+
"aria-hidden": "true",
|
|
4082
|
+
children: item.swatch.map((color, swatchIndex) => /* @__PURE__ */ jsx("span", { style: { backgroundColor: color } }, `${paletteLibraryItemKey(item)}:${swatchIndex}`))
|
|
4083
|
+
}), item.selected ? /* @__PURE__ */ jsx("span", {
|
|
4084
|
+
className: "absolute right-1 top-1 grid size-4 place-items-center rounded-full bg-foreground text-background",
|
|
4085
|
+
children: /* @__PURE__ */ jsx(Check, {
|
|
4086
|
+
"aria-hidden": "true",
|
|
4087
|
+
className: "size-3"
|
|
3503
4088
|
})
|
|
3504
|
-
}) : null
|
|
3505
|
-
|
|
3506
|
-
})
|
|
4089
|
+
}) : null]
|
|
4090
|
+
}, paletteLibraryItemKey(item)))
|
|
4091
|
+
})]
|
|
4092
|
+
});
|
|
4093
|
+
}
|
|
4094
|
+
function paletteLibraryItemKey(item) {
|
|
4095
|
+
return item.kind === "curated" ? `curated:${item.valueKey}` : `site:${item.paletteId}`;
|
|
4096
|
+
}
|
|
4097
|
+
function selectionForPaletteSnapshot(palette) {
|
|
4098
|
+
switch (palette.kind) {
|
|
4099
|
+
case "curated": return {
|
|
4100
|
+
kind: "curated",
|
|
4101
|
+
valueKey: palette.valueKey
|
|
4102
|
+
};
|
|
4103
|
+
case "curated-fork": return {
|
|
4104
|
+
kind: "curated",
|
|
4105
|
+
valueKey: palette.sourceValueKey
|
|
4106
|
+
};
|
|
4107
|
+
case "site": return {
|
|
4108
|
+
kind: "site",
|
|
4109
|
+
paletteId: palette.paletteId
|
|
4110
|
+
};
|
|
4111
|
+
case "new-site":
|
|
4112
|
+
case "invalid": return null;
|
|
4113
|
+
default: return assertNever$1(palette);
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
function PaletteTokenControls({ palette, isCustom, onTokenChange, onReset, disabled }) {
|
|
4117
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4118
|
+
className: "mt-4 space-y-3 border-t pt-4",
|
|
4119
|
+
children: [/* @__PURE__ */ jsx("fieldset", {
|
|
4120
|
+
disabled,
|
|
4121
|
+
className: "min-w-0 border-0 p-0",
|
|
4122
|
+
children: /* @__PURE__ */ jsx(PaletteTokenEditor, {
|
|
4123
|
+
palette: useMemo(() => paletteColorEntries(palette), [palette]),
|
|
4124
|
+
onChange: onTokenChange,
|
|
4125
|
+
brandRoles: PALETTE_BRAND_ROLES,
|
|
4126
|
+
feedbackRoles: PALETTE_FEEDBACK_ROLES,
|
|
4127
|
+
surfaceRoles: PALETTE_SURFACE_ROLES,
|
|
4128
|
+
showContrastChecks: false,
|
|
4129
|
+
disabled
|
|
4130
|
+
})
|
|
4131
|
+
}), isCustom ? /* @__PURE__ */ jsx("div", {
|
|
4132
|
+
className: "flex justify-end",
|
|
4133
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
4134
|
+
type: "button",
|
|
4135
|
+
variant: "outline",
|
|
4136
|
+
size: "sm",
|
|
4137
|
+
onClick: onReset,
|
|
4138
|
+
disabled,
|
|
4139
|
+
children: "Reset to variant"
|
|
4140
|
+
})
|
|
4141
|
+
}) : null]
|
|
3507
4142
|
});
|
|
3508
4143
|
}
|
|
3509
4144
|
function PickerOption({ selected, label, description, swatch, onSelect, disabled }) {
|
|
@@ -3544,6 +4179,10 @@ function classifyStyleApplyError(error) {
|
|
|
3544
4179
|
if (isRecord(error)) {
|
|
3545
4180
|
const status = error.status;
|
|
3546
4181
|
const code = error.code;
|
|
4182
|
+
if (code === "PALETTE_CAP_REACHED") return {
|
|
4183
|
+
kind: "palette-cap",
|
|
4184
|
+
message: "This site has reached its palette limit. Your palette draft is still here."
|
|
4185
|
+
};
|
|
3547
4186
|
if (status === 409 || code === "resource:conflict") return {
|
|
3548
4187
|
kind: "stale",
|
|
3549
4188
|
message: "This design changed elsewhere. Refreshing the latest version now."
|
|
@@ -3583,16 +4222,11 @@ function WarningNotice({ warnings, onDismiss }) {
|
|
|
3583
4222
|
});
|
|
3584
4223
|
}
|
|
3585
4224
|
function describeWarning(warning) {
|
|
3586
|
-
|
|
3587
|
-
case "rejected-personality": return `Button style changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
3588
|
-
case "rejected-palette": return `Palette changed to ${warning.fellBackTo} because ${warning.requested} is not available.`;
|
|
3589
|
-
case "rejected-typography-preset": return `Typography changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
3590
|
-
default: return warning;
|
|
3591
|
-
}
|
|
4225
|
+
return `Button style changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
3592
4226
|
}
|
|
3593
4227
|
//#endregion
|
|
3594
4228
|
//#region ../preview-next/src/client/preview/PreviewEditorSidebar.tsx
|
|
3595
|
-
function PreviewEditorSidebar({ surfaceId, siteId, dashboardBaseUrl = null, pageId, entryData, contentTypeSchema, referenceContentTypeKeys = [], draftContent, currentTemplate, theme, themeId = null, themeSelectionId = null, themeSelectionVersion = null, themeSelectionUpdatedAt = null, themeSelectionButtonPersonalityId = null, runtimePaletteState
|
|
4229
|
+
function PreviewEditorSidebar({ surfaceId, siteId, dashboardBaseUrl = null, pageId, entryData, contentTypeSchema, referenceContentTypeKeys = [], draftContent, currentTemplate, theme, themeId = null, themeSelectionId = null, themeSelectionVersion = null, themeSelectionUpdatedAt = null, themeSelectionButtonPersonalityId = null, runtimePaletteState, themeSelectionHeaderLayoutId = null, themeSelectionHeaderStyleId = null, themeSelectionHeaderLookId = null, themeSelectionFooterLookId = null, themeSelectionHeaderContext, themeSelectionFooterContext, designRowRequest = null, apiClient, bearerToken, supabaseUrl, entrySubrouteContext, assistantPanel, sdkConfig, mediaAssets, bookingOfferingPresets, siteStyleAccess = { kind: "hidden" }, activeTab, onTabChange, onClose, viewportMode, viewportWidth, zoom, onViewportModeChange, onViewportWidthChange, onZoomChange }) {
|
|
3596
4230
|
const controller = useEntryController();
|
|
3597
4231
|
const controllerBlocks = controller.blocks;
|
|
3598
4232
|
const uiStore = useEditorUiStoreInstance();
|
|
@@ -3603,6 +4237,7 @@ function PreviewEditorSidebar({ surfaceId, siteId, dashboardBaseUrl = null, page
|
|
|
3603
4237
|
const focusRequest = useUISelector(uiStore, (s) => s.focusRequest);
|
|
3604
4238
|
const activeLinkedEntrySnapshot = useUISelector(uiStore, (s) => s.linkedEntries.getSelectedSnapshot());
|
|
3605
4239
|
const previewInspection = useUISelector(uiStore, (s) => s.previewInspection);
|
|
4240
|
+
const [designTakeoverActive, setDesignTakeoverActive] = useState(false);
|
|
3606
4241
|
const { canEdit } = usePreviewAuth();
|
|
3607
4242
|
const dashboardSetupHandoff = useMemo(() => resolvePreviewDashboardSetupHandoff(), []);
|
|
3608
4243
|
const dashboardContinueUrl = useMemo(() => buildPreviewDashboardSetupUrl(dashboardBaseUrl, dashboardSetupHandoff), [dashboardBaseUrl, dashboardSetupHandoff]);
|
|
@@ -3719,6 +4354,7 @@ function PreviewEditorSidebar({ surfaceId, siteId, dashboardBaseUrl = null, page
|
|
|
3719
4354
|
onBlocksChange: handleBlocksChange,
|
|
3720
4355
|
metadataPanel: metadataSectionContent,
|
|
3721
4356
|
designOpenRequestId: designRowRequest?.id ?? null,
|
|
4357
|
+
designTakeoverActive,
|
|
3722
4358
|
designPanel: canInspectSiteStyle(siteStyleAccess) ? /* @__PURE__ */ jsx(StyleConfigurator, {
|
|
3723
4359
|
siteId,
|
|
3724
4360
|
apiClient,
|
|
@@ -3732,19 +4368,15 @@ function PreviewEditorSidebar({ surfaceId, siteId, dashboardBaseUrl = null, page
|
|
|
3732
4368
|
selectionUpdatedAt: themeSelectionUpdatedAt,
|
|
3733
4369
|
buttonPersonalityId: themeSelectionButtonPersonalityId,
|
|
3734
4370
|
runtimePaletteState,
|
|
3735
|
-
paletteVariantId: themeSelectionPaletteVariantId,
|
|
3736
|
-
paletteOverrides: themeSelectionPaletteOverrides,
|
|
3737
4371
|
headerLayoutId: themeSelectionHeaderLayoutId,
|
|
3738
4372
|
headerStyleId: themeSelectionHeaderStyleId,
|
|
3739
|
-
typographyPresetId: themeSelectionTypographyPresetId,
|
|
3740
|
-
typographyBodyFontOverride: themeSelectionTypographyBodyFontOverride,
|
|
3741
|
-
typographyHeadingFontOverride: themeSelectionTypographyHeadingFontOverride,
|
|
3742
4373
|
headerLookId: themeSelectionHeaderLookId,
|
|
3743
4374
|
footerLookId: themeSelectionFooterLookId
|
|
3744
4375
|
},
|
|
3745
4376
|
headerSelectionContext: themeSelectionHeaderContext,
|
|
3746
4377
|
footerSelectionContext: themeSelectionFooterContext,
|
|
3747
4378
|
expandedRowRequest: designRowRequest,
|
|
4379
|
+
onFocusedSurfaceChange: setDesignTakeoverActive,
|
|
3748
4380
|
siteStyleAccess
|
|
3749
4381
|
}) : null,
|
|
3750
4382
|
sdkConfig: sdkConfig ?? null,
|