@riverbankcms/sdk 0.76.0 → 0.77.1
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/dist/{PreviewEditorSidebar-X2HWXFOL.mjs → PreviewEditorSidebar-DVUG7GK4.mjs} +1019 -442
- package/dist/{PreviewEditorUI-AQXIXPOH.mjs → PreviewEditorUI-P7RN4CDS.mjs} +2 -2
- package/dist/SdkPreviewModeRuntime-KLPX47SE.mjs +8 -0
- package/dist/_dts/ai/src/contracts/proposals.d.ts +538 -20
- package/dist/_dts/api/src/contentRuntime.d.ts +5 -0
- package/dist/_dts/api/src/siteAssets.d.ts +1 -0
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +26 -2
- package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +28 -0
- package/dist/_dts/block-form/src/client/index.d.ts +2 -2
- package/dist/_dts/block-form/src/index.d.ts +2 -1
- package/dist/_dts/block-form/src/widgets/DateField/dateFieldSchema.d.ts +1 -1
- package/dist/_dts/block-form/src/widgets/DateTimeField/dateTimeFieldSchema.d.ts +1 -1
- package/dist/_dts/block-form/src/widgets/TimeField/timeFieldSchema.d.ts +1 -1
- package/dist/_dts/blocks/src/PageRenderer.d.ts +10 -10
- package/dist/_dts/blocks/src/client/site-chrome.d.ts +22 -0
- package/dist/_dts/blocks/src/customBlockRegistry.d.ts +57 -0
- package/dist/_dts/blocks/src/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/faq.d.ts +20 -2
- package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +25 -0
- package/dist/_dts/blocks/src/system/blocks/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/intro.d.ts +24 -0
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +3 -34
- package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +2 -2
- package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
- package/dist/_dts/blocks/src/system/fields/aspectRatio.d.ts +30 -0
- package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +4 -1
- package/dist/_dts/blocks/src/system/fields/ctas.d.ts +7 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +16 -2
- package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/components/multi-step/runtimeFormValidation.d.ts +28 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/accordion.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/accordion.server.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/accordionIconTreatment.d.ts +5 -0
- package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +5 -4
- package/dist/_dts/blocks/src/system/transforms/typed.d.ts +2 -1
- package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -0
- package/dist/_dts/content-editor/src/hooks/blockDraftLifecycle.d.ts +48 -0
- package/dist/_dts/content-editor/src/hooks/invalidBlockSelectors.d.ts +4 -0
- package/dist/_dts/content-editor/src/hooks/publishability.d.ts +47 -0
- package/dist/_dts/content-editor/src/index.d.ts +1 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +20 -0
- package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +2 -1
- package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +2 -1
- package/dist/_dts/editor-blocks/src/block-editor/customBlockRegistry.d.ts +2 -0
- package/dist/_dts/editor-blocks/src/block-editor/sdkBlockMerger.d.ts +9 -37
- package/dist/_dts/editor-blocks/src/index.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/index.d.ts +3 -0
- package/dist/_dts/preview-next/src/client/layout/PreviewLayoutContext.d.ts +5 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewDesignCoordinatorContext.d.ts +20 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +7 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +7 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +7 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewThemedSiteDocument.d.ts +18 -0
- package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +20 -3
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +6 -1
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +14 -4
- package/dist/_dts/preview-next/src/client/preview/previewDesignCoordinator.d.ts +73 -0
- package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +12 -4
- package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +46 -0
- package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +6 -1
- package/dist/_dts/preview-next/src/client/preview/typographySelectionInput.d.ts +14 -0
- package/dist/_dts/preview-next/src/client/sdk/SdkPreviewModeRuntime.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/commands/style.d.ts +8 -0
- package/dist/_dts/sdk/src/client/management/types.d.ts +6 -1
- package/dist/_dts/sdk/src/client/types.d.ts +9 -0
- package/dist/_dts/sdk/src/client.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +35 -0
- package/dist/_dts/sdk/src/contracts/theme.d.ts +1 -1
- package/dist/_dts/sdk/src/index.d.ts +2 -1
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -0
- package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -2
- 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/commands.d.ts +15 -0
- package/dist/_dts/theme-core/src/buttons/personalities/earth-pill.d.ts +16 -0
- package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
- package/dist/_dts/theme-core/src/fonts/types.d.ts +1 -1
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +72 -27
- package/dist/_dts/theme-core/src/palette/variants/index.d.ts +15 -0
- package/dist/_dts/theme-core/src/palette/variants/warm-neutral.d.ts +16 -0
- package/dist/_dts/theme-core/src/schema.d.ts +306 -30
- package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +81 -0
- package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +6 -4
- package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +81 -0
- package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +119 -3
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +13 -0
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
- package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +402 -13
- package/dist/_dts/theme-core/src/site-styles/headerOpeningSection.d.ts +6 -0
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +2 -0
- package/dist/_dts/theme-core/src/site-styles/persistedIdParseResult.d.ts +9 -0
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +20 -4
- package/dist/_dts/theme-core/src/site-styles/types.d.ts +74 -2
- package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +189 -0
- package/dist/{chunk-Q4OLG66B.mjs → chunk-2SPENC5M.mjs} +476 -153
- package/dist/{chunk-Z7JLNTJR.mjs → chunk-6SMUFTXD.mjs} +2 -1
- package/dist/{chunk-TW2Y4RR5.mjs → chunk-IENWFSLO.mjs} +365 -52
- package/dist/{chunk-LYI7TEMH.mjs → chunk-KWJPDZH2.mjs} +4682 -1463
- package/dist/{chunk-V5VORNEJ.mjs → chunk-ZYEJLCTN.mjs} +1 -1
- package/dist/cli/index.mjs +2314 -267
- package/dist/client/{accordion-2YHIBOZH.mjs → accordion-RZMQSYLR.mjs} +1 -1
- package/dist/client/{bookingForm-35IBDWAS.mjs → bookingForm-NF4ASVNV.mjs} +2 -2
- package/dist/client/bookings.mjs +92 -0
- package/dist/client/{carousel-K6XG7NZQ.mjs → carousel-LDX47ZIK.mjs} +1 -1
- package/dist/client/{cart-HCFYUTTU.mjs → cart-RGXDS5F4.mjs} +3 -3
- package/dist/client/{checkout-J3U4XR7K.mjs → checkout-P7WWSNNY.mjs} +3 -3
- package/dist/client/{chunk-BOIHIU7E.mjs → chunk-E2TDNXCL.mjs} +1 -1
- package/dist/client/{chunk-PFBX3IQL.mjs → chunk-GMVTOKYG.mjs} +2 -2
- package/dist/client/{chunk-FGUIVT2B.mjs → chunk-JNC7CGHX.mjs} +1 -1
- package/dist/client/{chunk-SNSWVZEP.mjs → chunk-L3DNHIJX.mjs} +3 -3
- package/dist/client/{chunk-7UOSCYY4.mjs → chunk-R56FQ3RR.mjs} +92 -0
- package/dist/client/{chunk-J227A3CQ.mjs → chunk-UFSWADAO.mjs} +1 -1
- package/dist/client/client.mjs +3579 -1351
- package/dist/client/{courseRegistration-ZBXS7VGI.mjs → courseRegistration-7F65K5ZR.mjs} +2 -2
- package/dist/client/{eventCalendar-EQQZHJBA.mjs → eventCalendar-GLSC5KTL.mjs} +4 -4
- package/dist/client/{eventCombined-JCFTGBFQ.mjs → eventCombined-ZHK4WKUR.mjs} +4 -4
- package/dist/client/{eventDetails-HLUTQSYY.mjs → eventDetails-E3PJYBIN.mjs} +4 -4
- package/dist/client/{eventListing-FG4MICVB.mjs → eventListing-EMS3WC3E.mjs} +4 -4
- package/dist/client/{eventRegistration-GUEB7LBT.mjs → eventRegistration-NZOTVNPI.mjs} +4 -4
- package/dist/client/{form-YQEW4YIT.mjs → form-ETFZFATW.mjs} +1 -1
- package/dist/client/{headerSection-GTR3TTRM.mjs → headerSection-4LBP7ULT.mjs} +2 -2
- package/dist/client/hooks.mjs +2226 -402
- package/dist/client/{locationMap-SPC7VGUH.mjs → locationMap-5M655YSJ.mjs} +1 -1
- package/dist/client/{newsletterForm-4IW5BLID.mjs → newsletterForm-QOUYW44O.mjs} +1 -1
- package/dist/client/{productDetail-KP5H2WJO.mjs → productDetail-O4DOCWQG.mjs} +3 -3
- package/dist/client/{productList-3M3M72XZ.mjs → productList-A5RO5WIS.mjs} +3 -3
- package/dist/client/rendering/client.mjs +198 -32
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +3573 -1355
- package/dist/client/{shop-ACQKVGOM.mjs → shop-L4MZH4I2.mjs} +3 -3
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/{sdk-runtime-K7HNB4U2.mjs → sdk-runtime-6UT2S7KZ.mjs} +5 -5
- package/dist/server/components.mjs +3497 -1333
- package/dist/server/config-validation.mjs +2229 -402
- package/dist/server/config.mjs +2229 -402
- package/dist/server/data.mjs +2226 -402
- package/dist/server/index.mjs +31 -2
- package/dist/server/next.mjs +3503 -1329
- package/dist/server/page-converter.mjs +2213 -403
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +3497 -1333
- package/dist/server/rendering.mjs +3497 -1333
- package/dist/server/routing.mjs +2250 -363
- package/dist/server/server.mjs +2243 -400
- package/dist/server/theme-bridge.mjs +1313 -1035
- package/dist/server/theme.mjs +237 -12
- package/dist/styles/index.css +1081 -1028
- package/package.json +1 -1
- package/dist/SdkPreviewModeRuntime-ZQNDCASH.mjs +0 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { resolvePreviewDashboardSetupHandoff, buildPreviewDashboardSetupUrl, resolvePreviewSidebarChromeModel, resolvePreviewEditorGuidanceModel, canInspectSiteStyle,
|
|
3
|
-
import { KeyboardCode, getBlockDefinition, CSS, useSdkConfig, listBlockDescriptors, useSensor, PointerSensor, useSensors, deleteBlock, createEditorRemoveBlockCommand, asEditorBlockId, DndContext, closestCenter, Button, Plus, useDroppable, useDraggable, useCombinedRefs, isKeyboardEvent,
|
|
2
|
+
import { resolvePreviewDashboardSetupHandoff, buildPreviewDashboardSetupUrl, resolvePreviewSidebarChromeModel, resolvePreviewEditorGuidanceModel, canInspectSiteStyle, usePreviewDesignCoordinator, resolveStyleConfiguratorInitialSnapshot, createStyleConfiguratorState, createOptimisticActionRunner, syncStyleConfiguratorState, isPreviewingChange, planSiteStylePreviewChange, openRow, previewSiteStyle, applyResolvedSelections, previewButtonPersonality, previewHeaderLayout, previewHeaderStyle, planSiteChromeLookSelection, previewFooterLook, previewPaletteVariant, previewTypographyPreset, setTypographyBodyFontOverride, setTypographyHeadingFontOverride, clearTypographyFontOverrides, setPaletteOverrides, toggleRow, cancelPreview, dismissWarnings, dismissNotices, markApplyFailed, markApplySaved, markApplySaving, canApplySiteStyle, buildSiteChromeLookModels, cycleSiteChromeLookId, cycleableSiteChromeOptions } from './chunk-IENWFSLO.mjs';
|
|
3
|
+
import { KeyboardCode, getBlockDefinition, CSS, useSdkConfig, listBlockDescriptors, useSensor, PointerSensor, useSensors, deleteBlock, createEditorRemoveBlockCommand, asEditorBlockId, DndContext, closestCenter, Button, Plus, useDroppable, useDraggable, useCombinedRefs, isKeyboardEvent, createCustomBlockRegistry, Card, cn, Collapsible, CollapsibleContent, listContentTypes, mergeBlockDescriptorsWithRegistry, createBlock, createEditorReorderBlocksCommand, reorderBlocks, mutateBlockContent, useDndContext, useUniqueId, useIsomorphicLayoutEffect, EmptyState, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Search, getClientRect, resolveBlockTitle, CardHeader, GripVertical, ChevronRight, CardTitle, ArrowUp, ArrowDown, DropdownMenu, DropdownMenuTrigger, EllipsisVertical, DropdownMenuContent, DropdownMenuItem, Settings, DropdownMenuSeparator, Copy, Trash2, DialogFooter, DialogClose, CardContent, createEditorInsertBlockCommand, LoaderCircle, ChevronDown, normalEditorCuratedPromotedFieldPaths, resolveVisiblePromotedFieldPathsForEditorBlock, createStoreBackend, validateBlockManifestIssues, Callout, CalloutTitle, unfinishedBlockCopy, CalloutDescription, recoveryConflictCopy, ManifestForm, asEditorBlockValues, Box, createManifestFormAdapter, getModalConfig, isNonEmptyValue, ScrollableDialogContent, FormRenderer, Tabs, TabsList, TabsTrigger, TabsContent, mergeManifestWithSdkOptions, augmentManifestWithStyleGroups, lucide_react_exports, isThemeV2NormalEditorRawStylePath, getFieldIntent, isHeaderField, isThemeV2NormalEditorRawStyleFieldName, unwrapResponse, useEntryController, useEditorUiStoreInstance, useUISelector, resolvePreviewSidebarTab, BackgroundGradientField, BackgroundColorField, X, omitRouteTitleFieldFromManifest, getRouteMetadataManifestForType, createManifestValidation, previewAssistantEnabled, useField, FieldFrame, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, isCtaIconName, Combobox, CTA_ICON_OPTIONS, getCtaIconComponent, useBackendWatch, useAsyncPickerOptions, shouldShowPickerSearch, normalizePickerSearchThreshold, Badge, resolvePickerSelectionLabel, useMediaEditorOptional, useRichTextEditor, RichTextEditorSurface, ThemeScope, useBlockContext, resolveMediaSlotContract, asRecord, parseAspectRatioValue, MediaEditor, PUBLIC_FILE_FIELD_KINDS, CollapsibleTrigger, ContentFieldsForm, getCuratedSiteStyle, paletteOverridesSchema, findButtonPersonality, findPaletteVariant, findTypographyPreset, getHeaderLayout, getHeaderStyle, findFooterLook, footerLookCatalog, isObjectRecord, EMPTY_DOC, getRichTextImagePositionFromTarget, insertOrReplaceRichTextImage, Pencil, foldSubroute, SUBROUTE_KINDS, Smartphone, Tablet, Monitor, Maximize2, DropdownMenuLabel, asSiteId, buildThemeRuntime, PaletteProvider, MediaEditorProvider, curatedSiteStyles, ChevronLeft, requireEntriesForCuratedChoices, buttonPersonalities, typographyPresets, paletteVariants, resolveImageUrlWithContext, Root2, List, Trigger, Content, Input, Check, Label, isInternalResolvedLinkValue, evaluateTypographyFontSlot, Separator, toRoutableLinkPayload, useMediaEditor, MediaPickerMini, MediaPickerDialog, Surface, ColorPicker, getDirectImageUrlForMediaAsset, isSvgMimeType } from './chunk-KWJPDZH2.mjs';
|
|
4
4
|
import { usePreviewAuth, getDashboardUrl } from './chunk-VX7B5VAC.mjs';
|
|
5
5
|
import './chunk-XGB3TDIC.mjs';
|
|
6
6
|
import React2, { createContext, memo, useMemo, useState, useRef, useEffect, forwardRef, useCallback, useImperativeHandle, useContext, useSyncExternalStore, useLayoutEffect, useTransition, useId } from 'react';
|
|
@@ -2962,45 +2962,37 @@ function createBlockFormLogger(scope) {
|
|
|
2962
2962
|
}
|
|
2963
2963
|
|
|
2964
2964
|
// ../editor-blocks/src/block-editor/sdkBlockMerger.ts
|
|
2965
|
-
var logger = createBlockFormLogger("
|
|
2966
|
-
function transformToBlockDescriptor(sdkBlock) {
|
|
2967
|
-
return {
|
|
2968
|
-
name: sdkBlock.id,
|
|
2969
|
-
title: sdkBlock.title,
|
|
2970
|
-
description: sdkBlock.description,
|
|
2971
|
-
category: sdkBlock.category,
|
|
2972
|
-
tags: sdkBlock.tags,
|
|
2973
|
-
icon: sdkBlock.icon,
|
|
2974
|
-
definition: transformSdkBlockToDefinition(sdkBlock),
|
|
2975
|
-
source: "sdk"
|
|
2976
|
-
};
|
|
2977
|
-
}
|
|
2965
|
+
var logger = createBlockFormLogger("customBlockRegistry");
|
|
2978
2966
|
function mergeBlockDescriptors(systemBlocks, sdkConfig, dbCustomBlocks) {
|
|
2979
|
-
const
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
}
|
|
2990
|
-
}
|
|
2991
|
-
return result;
|
|
2967
|
+
const registry = createCustomBlockRegistry({
|
|
2968
|
+
sdkConfig,
|
|
2969
|
+
customBlocks: normalizeCustomBlockEntries(dbCustomBlocks),
|
|
2970
|
+
onConflict: (message) => logger.warn(message)
|
|
2971
|
+
});
|
|
2972
|
+
return mergeBlockDescriptorsWithRegistry(
|
|
2973
|
+
systemBlocks,
|
|
2974
|
+
registry,
|
|
2975
|
+
(message) => logger.warn(message)
|
|
2976
|
+
);
|
|
2992
2977
|
}
|
|
2993
2978
|
function getBlockManifestFromSdkConfig(blockKind, sdkConfig, dbCustomBlocks) {
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
2979
|
+
return createCustomBlockRegistry({
|
|
2980
|
+
sdkConfig,
|
|
2981
|
+
customBlocks: normalizeCustomBlockEntries(dbCustomBlocks),
|
|
2982
|
+
onConflict: (message) => logger.warn(message)
|
|
2983
|
+
}).findManifest(blockKind)?.manifest;
|
|
2984
|
+
}
|
|
2985
|
+
function normalizeCustomBlockEntries(customBlocks) {
|
|
2986
|
+
if (!customBlocks) return [];
|
|
2987
|
+
return customBlocks.map((entry) => {
|
|
2988
|
+
if ("manifest" in entry && "source" in entry) {
|
|
2989
|
+
return entry;
|
|
3001
2990
|
}
|
|
3002
|
-
|
|
3003
|
-
|
|
2991
|
+
return {
|
|
2992
|
+
manifest: entry,
|
|
2993
|
+
source: { kind: "managed-database" }
|
|
2994
|
+
};
|
|
2995
|
+
});
|
|
3004
2996
|
}
|
|
3005
2997
|
var AddBlockDivider = ({ onOpen, position }) => /* @__PURE__ */ jsxs("div", { className: "relative flex w-full items-center justify-center h-8 opacity-0 transition-opacity hover:opacity-100", children: [
|
|
3006
2998
|
/* @__PURE__ */ jsx("div", { className: "w-full border-b" }),
|
|
@@ -3092,18 +3084,20 @@ function getCategoryLabel(category) {
|
|
|
3092
3084
|
// ../editor-blocks/src/block-editor/blockDiscovery.ts
|
|
3093
3085
|
var CORE_ESSENTIAL_BLOCKS = [
|
|
3094
3086
|
"block.hero",
|
|
3095
|
-
"block.
|
|
3096
|
-
"block.
|
|
3097
|
-
"block.
|
|
3098
|
-
"block.
|
|
3087
|
+
"block.intro",
|
|
3088
|
+
"block.body-text",
|
|
3089
|
+
"block.media-text",
|
|
3090
|
+
"block.feature-cards",
|
|
3091
|
+
"block.image-gallery",
|
|
3092
|
+
"block.cta-full",
|
|
3099
3093
|
"block.testimonials",
|
|
3100
3094
|
"block.faq",
|
|
3101
3095
|
"block.form"
|
|
3102
3096
|
];
|
|
3103
3097
|
var CONTEXTUAL_ESSENTIAL_GROUPS = [
|
|
3104
|
-
["block.
|
|
3105
|
-
["block.
|
|
3106
|
-
["block.
|
|
3098
|
+
["block.blog-listing"],
|
|
3099
|
+
["block.event-listing", "block.event-calendar"],
|
|
3100
|
+
["block.appointment-booking"],
|
|
3107
3101
|
["block.shop"]
|
|
3108
3102
|
];
|
|
3109
3103
|
function filterBlocksByContentType(blocks, enabledContentTypes) {
|
|
@@ -3194,21 +3188,26 @@ function getRecentBlocks(blocks, recentBlockNames) {
|
|
|
3194
3188
|
}
|
|
3195
3189
|
function suggestBlocks(blocks, existingBlockNames) {
|
|
3196
3190
|
if (existingBlockNames.length === 0) {
|
|
3197
|
-
return blocks.filter((b) => ["block.hero", "block.
|
|
3191
|
+
return blocks.filter((b) => ["block.hero", "block.intro", "block.cta-full"].includes(b.name)).slice(0, 3);
|
|
3198
3192
|
}
|
|
3199
3193
|
const hasHero = existingBlockNames.includes("block.hero");
|
|
3194
|
+
const hasIntro = existingBlockNames.includes("block.intro");
|
|
3200
3195
|
const hasBody = existingBlockNames.includes("block.body-text");
|
|
3196
|
+
const hasFeatureCards = existingBlockNames.includes("block.feature-cards");
|
|
3201
3197
|
const hasCta = existingBlockNames.includes("block.cta-full");
|
|
3202
3198
|
const hasFaq = existingBlockNames.includes("block.faq");
|
|
3203
3199
|
const hasTestimonials = existingBlockNames.includes("block.testimonials");
|
|
3204
3200
|
const suggestions = [];
|
|
3205
|
-
if (hasHero && !hasBody) {
|
|
3206
|
-
suggestions.push("block.body-text");
|
|
3201
|
+
if (hasHero && !hasIntro && !hasBody) {
|
|
3202
|
+
suggestions.push("block.intro", "block.body-text");
|
|
3207
3203
|
}
|
|
3208
|
-
if ((hasHero || hasBody) && !hasCta) {
|
|
3204
|
+
if ((hasHero || hasIntro || hasBody) && !hasCta) {
|
|
3209
3205
|
suggestions.push("block.cta-full");
|
|
3210
3206
|
}
|
|
3211
|
-
if ((
|
|
3207
|
+
if ((hasIntro || hasBody) && !hasFeatureCards) {
|
|
3208
|
+
suggestions.push("block.feature-cards");
|
|
3209
|
+
}
|
|
3210
|
+
if ((hasIntro || hasBody || hasFeatureCards || hasCta) && !hasTestimonials && !hasFaq) {
|
|
3212
3211
|
suggestions.push("block.testimonials", "block.faq");
|
|
3213
3212
|
}
|
|
3214
3213
|
const blockMap = new Map(blocks.map((b) => [b.name, b]));
|
|
@@ -4978,20 +4977,28 @@ var SortableBlockItem = memo(function SortableBlockItem2({
|
|
|
4978
4977
|
widgetOverrides,
|
|
4979
4978
|
uiStore,
|
|
4980
4979
|
sdkConfig,
|
|
4980
|
+
customBlocks = [],
|
|
4981
4981
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
4982
4982
|
pageDesignBlock = null,
|
|
4983
4983
|
reorderControlMode = DEFAULT_REORDER_CONTROL_MODE,
|
|
4984
4984
|
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
4985
4985
|
}) {
|
|
4986
|
-
const sortable = useSortable({
|
|
4986
|
+
const sortable = useSortable({
|
|
4987
|
+
id: block.id,
|
|
4988
|
+
disabled: !isDraggable
|
|
4989
|
+
});
|
|
4987
4990
|
const manifest = useMemo(() => {
|
|
4988
|
-
const sdkManifest = getBlockManifestFromSdkConfig(
|
|
4991
|
+
const sdkManifest = getBlockManifestFromSdkConfig(
|
|
4992
|
+
block.kind,
|
|
4993
|
+
sdkConfig ?? null,
|
|
4994
|
+
customBlocks
|
|
4995
|
+
);
|
|
4989
4996
|
if (sdkManifest) {
|
|
4990
4997
|
return sdkManifest;
|
|
4991
4998
|
}
|
|
4992
4999
|
const blockDefinition = getBlockDefinition(block.kind);
|
|
4993
5000
|
return blockDefinition?.manifest;
|
|
4994
|
-
}, [block.kind, sdkConfig]);
|
|
5001
|
+
}, [block.kind, customBlocks, sdkConfig]);
|
|
4995
5002
|
const [mounted, setMounted] = useState(false);
|
|
4996
5003
|
const blockRef = useRef(null);
|
|
4997
5004
|
useEffect(() => setMounted(true), []);
|
|
@@ -5063,360 +5070,439 @@ var SortableBlockItem = memo(function SortableBlockItem2({
|
|
|
5063
5070
|
}
|
|
5064
5071
|
);
|
|
5065
5072
|
});
|
|
5066
|
-
var BlockEditor = forwardRef(
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
blocks,
|
|
5070
|
-
recoveryConflictBlockIds = [],
|
|
5071
|
-
recoveryConflictReviewRequestId = null,
|
|
5072
|
-
apiClient,
|
|
5073
|
-
uiStore,
|
|
5074
|
-
enableReordering = true,
|
|
5075
|
-
enableCreation = true,
|
|
5076
|
-
onBlockSave,
|
|
5077
|
-
onBlocksChange,
|
|
5078
|
-
theme,
|
|
5079
|
-
widgetOverrides,
|
|
5080
|
-
headerLeftSlot,
|
|
5081
|
-
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
5082
|
-
pageDesignEditorModel = null,
|
|
5083
|
-
enabledContentTypes = [],
|
|
5084
|
-
sdkConfig = null,
|
|
5085
|
-
reorderControlMode = DEFAULT_REORDER_CONTROL_MODE,
|
|
5086
|
-
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
5087
|
-
}, ref) {
|
|
5088
|
-
const [blockList, setBlockList] = useState(() => normalizeBlockListInitial(blocks));
|
|
5089
|
-
const [errorMessage, setErrorMessage] = useState(null);
|
|
5090
|
-
const [highlightedBlockId, setHighlightedBlockId] = useState(null);
|
|
5091
|
-
const blockRefs = useRef(/* @__PURE__ */ new Map());
|
|
5092
|
-
const highlightTimerRef = useRef(null);
|
|
5093
|
-
const { blockFieldExtensions } = useSdkConfig();
|
|
5094
|
-
const activeBlockId = useStoreSelector(uiStore, (state) => state.activeBlockId);
|
|
5095
|
-
const setActiveBlockId = useCallback(
|
|
5096
|
-
(id) => {
|
|
5097
|
-
uiStore.getState().setActiveBlockId(id);
|
|
5098
|
-
},
|
|
5099
|
-
[uiStore]
|
|
5100
|
-
);
|
|
5101
|
-
const [fetchedContentTypes, setFetchedContentTypes] = useState(enabledContentTypes);
|
|
5102
|
-
const [fetchingContentTypes, setFetchingContentTypes] = useState(false);
|
|
5103
|
-
const allowReordering = enableReordering;
|
|
5104
|
-
const allowCreation = enableCreation;
|
|
5105
|
-
const conflictedBlockIdSet = useMemo(
|
|
5106
|
-
() => new Set(recoveryConflictBlockIds),
|
|
5107
|
-
[recoveryConflictBlockIds]
|
|
5108
|
-
);
|
|
5109
|
-
const blockIds = useMemo(
|
|
5110
|
-
() => blockList.map((block) => block.id).filter((blockId) => typeof blockId === "string"),
|
|
5111
|
-
[blockList]
|
|
5112
|
-
);
|
|
5113
|
-
const pageDesignBlockById = useMemo(
|
|
5114
|
-
() => new Map(
|
|
5115
|
-
(pageDesignEditorModel?.blocks ?? []).map((block) => [String(block.blockId), block])
|
|
5116
|
-
),
|
|
5117
|
-
[pageDesignEditorModel]
|
|
5118
|
-
);
|
|
5119
|
-
const { isCollapsed, setCollapsed } = useBlockExpandState({
|
|
5073
|
+
var BlockEditor = forwardRef(
|
|
5074
|
+
function BlockEditor2({
|
|
5075
|
+
siteId,
|
|
5120
5076
|
pageId,
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5077
|
+
blocks,
|
|
5078
|
+
recoveryConflictBlockIds = [],
|
|
5079
|
+
recoveryConflictReviewRequestId = null,
|
|
5080
|
+
apiClient,
|
|
5081
|
+
uiStore,
|
|
5082
|
+
enableReordering = true,
|
|
5083
|
+
enableCreation = true,
|
|
5084
|
+
onBlockSave,
|
|
5085
|
+
onBlocksChange,
|
|
5086
|
+
theme,
|
|
5087
|
+
widgetOverrides,
|
|
5088
|
+
headerLeftSlot,
|
|
5089
|
+
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
5090
|
+
pageDesignEditorModel = null,
|
|
5091
|
+
enabledContentTypes = [],
|
|
5092
|
+
sdkConfig = null,
|
|
5093
|
+
customBlocks = [],
|
|
5094
|
+
reorderControlMode = DEFAULT_REORDER_CONTROL_MODE,
|
|
5095
|
+
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
5096
|
+
}, ref) {
|
|
5097
|
+
const [blockList, setBlockList] = useState(
|
|
5098
|
+
() => normalizeBlockListInitial(blocks)
|
|
5099
|
+
);
|
|
5100
|
+
const [errorMessage, setErrorMessage] = useState(null);
|
|
5101
|
+
const [highlightedBlockId, setHighlightedBlockId] = useState(
|
|
5102
|
+
null
|
|
5103
|
+
);
|
|
5104
|
+
const blockRefs = useRef(/* @__PURE__ */ new Map());
|
|
5105
|
+
const highlightTimerRef = useRef(null);
|
|
5106
|
+
const { blockFieldExtensions } = useSdkConfig();
|
|
5107
|
+
const activeBlockId = useStoreSelector(
|
|
5108
|
+
uiStore,
|
|
5109
|
+
(state) => state.activeBlockId
|
|
5110
|
+
);
|
|
5111
|
+
const setActiveBlockId = useCallback(
|
|
5112
|
+
(id) => {
|
|
5113
|
+
uiStore.getState().setActiveBlockId(id);
|
|
5114
|
+
},
|
|
5115
|
+
[uiStore]
|
|
5116
|
+
);
|
|
5117
|
+
const [fetchedContentTypes, setFetchedContentTypes] = useState(enabledContentTypes);
|
|
5118
|
+
const [fetchingContentTypes, setFetchingContentTypes] = useState(false);
|
|
5119
|
+
const allowReordering = enableReordering;
|
|
5120
|
+
const allowCreation = enableCreation;
|
|
5121
|
+
const conflictedBlockIdSet = useMemo(
|
|
5122
|
+
() => new Set(recoveryConflictBlockIds),
|
|
5123
|
+
[recoveryConflictBlockIds]
|
|
5124
|
+
);
|
|
5125
|
+
const blockIds = useMemo(
|
|
5126
|
+
() => blockList.map((block) => block.id).filter((blockId) => typeof blockId === "string"),
|
|
5127
|
+
[blockList]
|
|
5128
|
+
);
|
|
5129
|
+
const pageDesignBlockById = useMemo(
|
|
5130
|
+
() => new Map(
|
|
5131
|
+
(pageDesignEditorModel?.blocks ?? []).map((block) => [
|
|
5132
|
+
String(block.blockId),
|
|
5133
|
+
block
|
|
5134
|
+
])
|
|
5135
|
+
),
|
|
5136
|
+
[pageDesignEditorModel]
|
|
5137
|
+
);
|
|
5138
|
+
const { isCollapsed, setCollapsed } = useBlockExpandState({
|
|
5139
|
+
pageId,
|
|
5140
|
+
blockIds
|
|
5141
|
+
});
|
|
5142
|
+
useEffect(() => {
|
|
5143
|
+
setBlockList(normalizeBlockListInitial(blocks));
|
|
5144
|
+
}, [blocks]);
|
|
5145
|
+
useEffect(() => {
|
|
5146
|
+
const unsubscribe = uiStore.subscribe(() => {
|
|
5147
|
+
const structureList = uiStore.getState().structure.getList();
|
|
5148
|
+
setBlockList((currentList) => {
|
|
5149
|
+
const nextList = structureList.map((block) => ({ ...block }));
|
|
5150
|
+
const hasChanges = currentList.length !== nextList.length || currentList.some((block, index) => {
|
|
5151
|
+
const nextBlock = nextList[index];
|
|
5152
|
+
return !nextBlock || block.id !== nextBlock.id || block.orderIndex !== nextBlock.orderIndex || block.kind !== nextBlock.kind;
|
|
5153
|
+
});
|
|
5154
|
+
return hasChanges ? nextList : currentList;
|
|
5134
5155
|
});
|
|
5135
|
-
return hasChanges ? nextList : currentList;
|
|
5136
5156
|
});
|
|
5157
|
+
return unsubscribe;
|
|
5158
|
+
}, [uiStore]);
|
|
5159
|
+
useEffect(() => {
|
|
5160
|
+
let cancelled = false;
|
|
5161
|
+
async function fetchContentTypesFromApi() {
|
|
5162
|
+
if (fetchingContentTypes) return;
|
|
5163
|
+
setFetchingContentTypes(true);
|
|
5164
|
+
try {
|
|
5165
|
+
const result = await listContentTypes(apiClient, { siteId });
|
|
5166
|
+
if (!cancelled) {
|
|
5167
|
+
const keys = (result.contentTypes || []).map(
|
|
5168
|
+
(ct) => typeof ct === "string" ? ct : ct.key
|
|
5169
|
+
);
|
|
5170
|
+
setFetchedContentTypes(keys);
|
|
5171
|
+
}
|
|
5172
|
+
} catch (error) {
|
|
5173
|
+
console.error("[block-editor] Failed to fetch content types:", error);
|
|
5174
|
+
if (!cancelled) {
|
|
5175
|
+
setFetchedContentTypes(enabledContentTypes);
|
|
5176
|
+
}
|
|
5177
|
+
} finally {
|
|
5178
|
+
if (!cancelled) {
|
|
5179
|
+
setFetchingContentTypes(false);
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
fetchContentTypesFromApi();
|
|
5184
|
+
return () => {
|
|
5185
|
+
cancelled = true;
|
|
5186
|
+
};
|
|
5187
|
+
}, [siteId, apiClient, enabledContentTypes]);
|
|
5188
|
+
useBlockBaselineSync({
|
|
5189
|
+
enabled: true,
|
|
5190
|
+
blockList,
|
|
5191
|
+
blockFieldExtensions,
|
|
5192
|
+
uiStore
|
|
5137
5193
|
});
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5194
|
+
const focusRequest = useStoreSelector(
|
|
5195
|
+
uiStore,
|
|
5196
|
+
(state) => state.focusRequest
|
|
5197
|
+
);
|
|
5198
|
+
const triggerFocus = useCallback(
|
|
5199
|
+
(target) => {
|
|
5200
|
+
const { blockId, fieldPath, itemIndex } = target;
|
|
5201
|
+
uiStore.getState().requestFocus({ blockId, fieldPath, itemIndex });
|
|
5202
|
+
},
|
|
5203
|
+
[uiStore]
|
|
5204
|
+
);
|
|
5205
|
+
const handleFocusHandled = useCallback(
|
|
5206
|
+
(requestId) => {
|
|
5207
|
+
const current = uiStore.getState().focusRequest;
|
|
5208
|
+
if (current && current.requestId === requestId) {
|
|
5209
|
+
uiStore.getState().clearFocus();
|
|
5152
5210
|
}
|
|
5153
|
-
}
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5211
|
+
},
|
|
5212
|
+
[uiStore]
|
|
5213
|
+
);
|
|
5214
|
+
useImperativeHandle(
|
|
5215
|
+
ref,
|
|
5216
|
+
() => ({
|
|
5217
|
+
focusField: triggerFocus
|
|
5218
|
+
}),
|
|
5219
|
+
[triggerFocus]
|
|
5220
|
+
);
|
|
5221
|
+
const availableBlocks = useMemo(
|
|
5222
|
+
() => mergeBlockDescriptors(listBlockDescriptors(), sdkConfig, customBlocks),
|
|
5223
|
+
[customBlocks, sdkConfig]
|
|
5224
|
+
);
|
|
5225
|
+
const pointerSensor = useSensor(PointerSensor, {
|
|
5226
|
+
activationConstraint: { distance: 5 }
|
|
5227
|
+
});
|
|
5228
|
+
const sensors = useSensors(pointerSensor);
|
|
5229
|
+
const activeSensors = allowReordering ? sensors : [];
|
|
5230
|
+
const {
|
|
5231
|
+
pickerOpen,
|
|
5232
|
+
creatingBlockName,
|
|
5233
|
+
openPicker,
|
|
5234
|
+
closePicker,
|
|
5235
|
+
handleCreateBlock
|
|
5236
|
+
} = useBlockCreation({
|
|
5237
|
+
allowCreation,
|
|
5238
|
+
apiClient,
|
|
5239
|
+
siteId,
|
|
5240
|
+
pageId,
|
|
5241
|
+
blockList,
|
|
5242
|
+
setBlockList,
|
|
5243
|
+
onBlocksChange,
|
|
5244
|
+
triggerFocus,
|
|
5245
|
+
uiStore
|
|
5246
|
+
});
|
|
5247
|
+
const { reorderId, handleMove, onDragEnd } = useBlockReorder({
|
|
5248
|
+
allowReordering,
|
|
5249
|
+
apiClient,
|
|
5250
|
+
siteId,
|
|
5251
|
+
pageId,
|
|
5252
|
+
blockList,
|
|
5253
|
+
setBlockList,
|
|
5254
|
+
onBlocksChange,
|
|
5255
|
+
setErrorMessage,
|
|
5256
|
+
uiStore
|
|
5257
|
+
});
|
|
5258
|
+
const { duplicatingBlockId, duplicateBlock } = useBlockDuplication({
|
|
5259
|
+
allowCreation,
|
|
5260
|
+
apiClient,
|
|
5261
|
+
siteId,
|
|
5262
|
+
pageId,
|
|
5263
|
+
blockList,
|
|
5264
|
+
setBlockList,
|
|
5265
|
+
onBlocksChange,
|
|
5266
|
+
triggerFocus,
|
|
5267
|
+
setErrorMessage,
|
|
5268
|
+
uiStore
|
|
5269
|
+
});
|
|
5270
|
+
const handleDelete = useCallback(
|
|
5271
|
+
async (blockId) => {
|
|
5272
|
+
try {
|
|
5273
|
+
setErrorMessage(null);
|
|
5274
|
+
const removedBlock = blockList.find((block) => block.id === blockId);
|
|
5275
|
+
if (!removedBlock) {
|
|
5276
|
+
return;
|
|
5277
|
+
}
|
|
5278
|
+
await deleteBlock(apiClient, { siteId, pageId, blockId });
|
|
5279
|
+
const updatedList = blockList.filter((b) => b.id !== blockId);
|
|
5280
|
+
setBlockList(updatedList);
|
|
5281
|
+
if (uiStore) {
|
|
5282
|
+
uiStore.getState().history.applyCommand?.({
|
|
5283
|
+
...createEditorRemoveBlockCommand(asEditorBlockId(blockId))
|
|
5284
|
+
});
|
|
5285
|
+
}
|
|
5286
|
+
onBlocksChange?.(updatedList);
|
|
5287
|
+
} catch (error) {
|
|
5288
|
+
console.error("[BlockEditor] Delete failed:", error);
|
|
5289
|
+
const message = error instanceof Error ? error.message : "Failed to delete block";
|
|
5290
|
+
setErrorMessage(message);
|
|
5157
5291
|
}
|
|
5158
|
-
}
|
|
5159
|
-
|
|
5160
|
-
|
|
5292
|
+
},
|
|
5293
|
+
[
|
|
5294
|
+
apiClient,
|
|
5295
|
+
siteId,
|
|
5296
|
+
pageId,
|
|
5297
|
+
blockList,
|
|
5298
|
+
setBlockList,
|
|
5299
|
+
onBlocksChange,
|
|
5300
|
+
uiStore
|
|
5301
|
+
]
|
|
5302
|
+
);
|
|
5303
|
+
useEffect(() => {
|
|
5304
|
+
return () => {
|
|
5305
|
+
if (highlightTimerRef.current !== null) {
|
|
5306
|
+
window.clearTimeout(highlightTimerRef.current);
|
|
5161
5307
|
}
|
|
5162
|
-
}
|
|
5163
|
-
}
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
cancelled = true;
|
|
5167
|
-
};
|
|
5168
|
-
}, [siteId, apiClient, enabledContentTypes]);
|
|
5169
|
-
useBlockBaselineSync({ enabled: true, blockList, blockFieldExtensions, uiStore });
|
|
5170
|
-
const focusRequest = useStoreSelector(uiStore, (state) => state.focusRequest);
|
|
5171
|
-
const triggerFocus = useCallback(
|
|
5172
|
-
(target) => {
|
|
5173
|
-
const { blockId, fieldPath, itemIndex } = target;
|
|
5174
|
-
uiStore.getState().requestFocus({ blockId, fieldPath, itemIndex });
|
|
5175
|
-
},
|
|
5176
|
-
[uiStore]
|
|
5177
|
-
);
|
|
5178
|
-
const handleFocusHandled = useCallback(
|
|
5179
|
-
(requestId) => {
|
|
5180
|
-
const current = uiStore.getState().focusRequest;
|
|
5181
|
-
if (current && current.requestId === requestId) {
|
|
5182
|
-
uiStore.getState().clearFocus();
|
|
5183
|
-
}
|
|
5184
|
-
},
|
|
5185
|
-
[uiStore]
|
|
5186
|
-
);
|
|
5187
|
-
useImperativeHandle(
|
|
5188
|
-
ref,
|
|
5189
|
-
() => ({
|
|
5190
|
-
focusField: triggerFocus
|
|
5191
|
-
}),
|
|
5192
|
-
[triggerFocus]
|
|
5193
|
-
);
|
|
5194
|
-
const availableBlocks = useMemo(
|
|
5195
|
-
() => mergeBlockDescriptors(listBlockDescriptors(), sdkConfig),
|
|
5196
|
-
[sdkConfig]
|
|
5197
|
-
);
|
|
5198
|
-
const pointerSensor = useSensor(PointerSensor, { activationConstraint: { distance: 5 } });
|
|
5199
|
-
const sensors = useSensors(pointerSensor);
|
|
5200
|
-
const activeSensors = allowReordering ? sensors : [];
|
|
5201
|
-
const { pickerOpen, creatingBlockName, openPicker, closePicker, handleCreateBlock } = useBlockCreation({
|
|
5202
|
-
allowCreation,
|
|
5203
|
-
apiClient,
|
|
5204
|
-
siteId,
|
|
5205
|
-
pageId,
|
|
5206
|
-
blockList,
|
|
5207
|
-
setBlockList,
|
|
5208
|
-
onBlocksChange,
|
|
5209
|
-
triggerFocus,
|
|
5210
|
-
uiStore
|
|
5211
|
-
});
|
|
5212
|
-
const { reorderId, handleMove, onDragEnd } = useBlockReorder({
|
|
5213
|
-
allowReordering,
|
|
5214
|
-
apiClient,
|
|
5215
|
-
siteId,
|
|
5216
|
-
pageId,
|
|
5217
|
-
blockList,
|
|
5218
|
-
setBlockList,
|
|
5219
|
-
onBlocksChange,
|
|
5220
|
-
setErrorMessage,
|
|
5221
|
-
uiStore
|
|
5222
|
-
});
|
|
5223
|
-
const { duplicatingBlockId, duplicateBlock } = useBlockDuplication({
|
|
5224
|
-
allowCreation,
|
|
5225
|
-
apiClient,
|
|
5226
|
-
siteId,
|
|
5227
|
-
pageId,
|
|
5228
|
-
blockList,
|
|
5229
|
-
setBlockList,
|
|
5230
|
-
onBlocksChange,
|
|
5231
|
-
triggerFocus,
|
|
5232
|
-
setErrorMessage,
|
|
5233
|
-
uiStore
|
|
5234
|
-
});
|
|
5235
|
-
const handleDelete = useCallback(async (blockId) => {
|
|
5236
|
-
try {
|
|
5237
|
-
setErrorMessage(null);
|
|
5238
|
-
const removedBlock = blockList.find((block) => block.id === blockId);
|
|
5239
|
-
if (!removedBlock) {
|
|
5308
|
+
};
|
|
5309
|
+
}, []);
|
|
5310
|
+
useEffect(() => {
|
|
5311
|
+
if (!focusRequest?.blockId) {
|
|
5240
5312
|
return;
|
|
5241
5313
|
}
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5314
|
+
const focusedBlockId = String(focusRequest.blockId);
|
|
5315
|
+
setCollapsed(focusedBlockId, false);
|
|
5316
|
+
uiStore.getState().setActiveBlockId(focusRequest.blockId);
|
|
5317
|
+
setHighlightedBlockId(focusedBlockId);
|
|
5318
|
+
window.setTimeout(() => {
|
|
5319
|
+
blockRefs.current.get(focusedBlockId)?.scrollIntoView({
|
|
5320
|
+
behavior: "smooth",
|
|
5321
|
+
block: "center"
|
|
5248
5322
|
});
|
|
5249
|
-
}
|
|
5250
|
-
onBlocksChange?.(updatedList);
|
|
5251
|
-
} catch (error) {
|
|
5252
|
-
console.error("[BlockEditor] Delete failed:", error);
|
|
5253
|
-
const message = error instanceof Error ? error.message : "Failed to delete block";
|
|
5254
|
-
setErrorMessage(message);
|
|
5255
|
-
}
|
|
5256
|
-
}, [apiClient, siteId, pageId, blockList, setBlockList, onBlocksChange, uiStore]);
|
|
5257
|
-
useEffect(() => {
|
|
5258
|
-
return () => {
|
|
5323
|
+
}, 100);
|
|
5259
5324
|
if (highlightTimerRef.current !== null) {
|
|
5260
5325
|
window.clearTimeout(highlightTimerRef.current);
|
|
5261
5326
|
}
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
uiStore.getState().setActiveBlockId(null);
|
|
5308
|
-
}
|
|
5309
|
-
}, [activeBlockId, blockList, uiStore]);
|
|
5310
|
-
const hasBlocks = blockList.length > 0;
|
|
5311
|
-
const contextValue = useMemo(
|
|
5312
|
-
() => ({
|
|
5313
|
-
blockList,
|
|
5314
|
-
setBlockList,
|
|
5315
|
-
reorderId,
|
|
5316
|
-
focusRequest,
|
|
5317
|
-
triggerFocus,
|
|
5318
|
-
handleMove,
|
|
5319
|
-
onDragEnd,
|
|
5320
|
-
activeBlockId,
|
|
5321
|
-
setActiveBlockId,
|
|
5322
|
-
theme
|
|
5323
|
-
}),
|
|
5324
|
-
[blockList, reorderId, focusRequest, triggerFocus, handleMove, onDragEnd, activeBlockId, setActiveBlockId, theme]
|
|
5325
|
-
);
|
|
5326
|
-
return /* @__PURE__ */ jsx(BlockListProvider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3 touch-pan-y", children: [
|
|
5327
|
-
/* @__PURE__ */ jsx(HeaderActions, { headerLeftSlot }),
|
|
5328
|
-
errorMessage ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive", children: errorMessage }) : null,
|
|
5329
|
-
hasBlocks ? /* @__PURE__ */ jsx(
|
|
5330
|
-
DndContext,
|
|
5331
|
-
{
|
|
5332
|
-
sensors: activeSensors,
|
|
5333
|
-
collisionDetection: closestCenter,
|
|
5327
|
+
highlightTimerRef.current = window.setTimeout(() => {
|
|
5328
|
+
setHighlightedBlockId(
|
|
5329
|
+
(current) => current === focusedBlockId ? null : current
|
|
5330
|
+
);
|
|
5331
|
+
highlightTimerRef.current = null;
|
|
5332
|
+
}, 1500);
|
|
5333
|
+
}, [focusRequest?.requestId, focusRequest?.blockId, setCollapsed, uiStore]);
|
|
5334
|
+
useEffect(() => {
|
|
5335
|
+
if (recoveryConflictReviewRequestId === null || recoveryConflictBlockIds.length === 0) {
|
|
5336
|
+
return;
|
|
5337
|
+
}
|
|
5338
|
+
for (const blockId of recoveryConflictBlockIds) {
|
|
5339
|
+
setCollapsed(blockId, false);
|
|
5340
|
+
}
|
|
5341
|
+
const firstRecoveryBlockId = recoveryConflictBlockIds[0];
|
|
5342
|
+
if (!firstRecoveryBlockId) {
|
|
5343
|
+
return;
|
|
5344
|
+
}
|
|
5345
|
+
uiStore.getState().requestFocus({ blockId: asEditorBlockId(firstRecoveryBlockId) });
|
|
5346
|
+
}, [
|
|
5347
|
+
recoveryConflictBlockIds,
|
|
5348
|
+
recoveryConflictReviewRequestId,
|
|
5349
|
+
setCollapsed,
|
|
5350
|
+
uiStore
|
|
5351
|
+
]);
|
|
5352
|
+
useEffect(() => {
|
|
5353
|
+
if (!activeBlockId) {
|
|
5354
|
+
return;
|
|
5355
|
+
}
|
|
5356
|
+
const stillExists = blockList.some(
|
|
5357
|
+
(block) => typeof block.id === "string" && asEditorBlockId(block.id) === activeBlockId
|
|
5358
|
+
);
|
|
5359
|
+
if (!stillExists) {
|
|
5360
|
+
uiStore.getState().setActiveBlockId(null);
|
|
5361
|
+
}
|
|
5362
|
+
}, [activeBlockId, blockList, uiStore]);
|
|
5363
|
+
const hasBlocks = blockList.length > 0;
|
|
5364
|
+
const contextValue = useMemo(
|
|
5365
|
+
() => ({
|
|
5366
|
+
blockList,
|
|
5367
|
+
setBlockList,
|
|
5368
|
+
reorderId,
|
|
5369
|
+
focusRequest,
|
|
5370
|
+
triggerFocus,
|
|
5371
|
+
handleMove,
|
|
5334
5372
|
onDragEnd,
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5373
|
+
activeBlockId,
|
|
5374
|
+
setActiveBlockId,
|
|
5375
|
+
theme
|
|
5376
|
+
}),
|
|
5377
|
+
[
|
|
5378
|
+
blockList,
|
|
5379
|
+
reorderId,
|
|
5380
|
+
focusRequest,
|
|
5381
|
+
triggerFocus,
|
|
5382
|
+
handleMove,
|
|
5383
|
+
onDragEnd,
|
|
5384
|
+
activeBlockId,
|
|
5385
|
+
setActiveBlockId,
|
|
5386
|
+
theme
|
|
5387
|
+
]
|
|
5388
|
+
);
|
|
5389
|
+
return /* @__PURE__ */ jsx(BlockListProvider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3 touch-pan-y", children: [
|
|
5390
|
+
/* @__PURE__ */ jsx(HeaderActions, { headerLeftSlot }),
|
|
5391
|
+
errorMessage ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive", children: errorMessage }) : null,
|
|
5392
|
+
hasBlocks ? /* @__PURE__ */ jsx(
|
|
5393
|
+
DndContext,
|
|
5394
|
+
{
|
|
5395
|
+
sensors: activeSensors,
|
|
5396
|
+
collisionDetection: closestCenter,
|
|
5397
|
+
onDragEnd,
|
|
5398
|
+
children: /* @__PURE__ */ jsx(
|
|
5399
|
+
SortableContext,
|
|
5400
|
+
{
|
|
5401
|
+
items: blockList.map((b) => b.id),
|
|
5402
|
+
strategy: verticalListSortingStrategy,
|
|
5403
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-0", children: [
|
|
5404
|
+
allowCreation ? /* @__PURE__ */ jsx(AddBlockDivider, { onOpen: openPicker, position: 0 }) : null,
|
|
5405
|
+
blockList.map((block, index) => {
|
|
5406
|
+
const focusSignal = focusRequest && block.id && focusRequest.blockId === asEditorBlockId(block.id) ? focusRequest : null;
|
|
5407
|
+
const collapsed = isCollapsed(block.id);
|
|
5408
|
+
return /* @__PURE__ */ jsxs(
|
|
5409
|
+
"div",
|
|
5355
5410
|
{
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
onMove: handleMove,
|
|
5359
|
-
onDuplicate: duplicateBlock,
|
|
5360
|
-
onDelete: handleDelete,
|
|
5361
|
-
isFirst: index === 0,
|
|
5362
|
-
isLast: index === blockList.length - 1,
|
|
5363
|
-
isMoving: reorderId === block.id || duplicatingBlockId === block.id,
|
|
5364
|
-
isDraggable: allowReordering,
|
|
5365
|
-
collapsed,
|
|
5366
|
-
onCollapsedChange: (nextCollapsed) => {
|
|
5411
|
+
className: "group",
|
|
5412
|
+
ref: (node) => {
|
|
5367
5413
|
if (!block.id) return;
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
}
|
|
5373
|
-
return;
|
|
5414
|
+
if (node) {
|
|
5415
|
+
blockRefs.current.set(block.id, node);
|
|
5416
|
+
} else {
|
|
5417
|
+
blockRefs.current.delete(block.id);
|
|
5374
5418
|
}
|
|
5375
|
-
uiStore.getState().setActiveBlockId(asEditorBlockId(block.id));
|
|
5376
5419
|
},
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
+
children: [
|
|
5421
|
+
/* @__PURE__ */ jsx(
|
|
5422
|
+
SortableBlockItem,
|
|
5423
|
+
{
|
|
5424
|
+
siteId,
|
|
5425
|
+
block,
|
|
5426
|
+
onMove: handleMove,
|
|
5427
|
+
onDuplicate: duplicateBlock,
|
|
5428
|
+
onDelete: handleDelete,
|
|
5429
|
+
isFirst: index === 0,
|
|
5430
|
+
isLast: index === blockList.length - 1,
|
|
5431
|
+
isMoving: reorderId === block.id || duplicatingBlockId === block.id,
|
|
5432
|
+
isDraggable: allowReordering,
|
|
5433
|
+
collapsed,
|
|
5434
|
+
onCollapsedChange: (nextCollapsed) => {
|
|
5435
|
+
if (!block.id) return;
|
|
5436
|
+
setCollapsed(block.id, nextCollapsed);
|
|
5437
|
+
if (nextCollapsed) {
|
|
5438
|
+
if (activeBlockId === asEditorBlockId(block.id)) {
|
|
5439
|
+
uiStore.getState().setActiveBlockId(null);
|
|
5440
|
+
}
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5443
|
+
uiStore.getState().setActiveBlockId(asEditorBlockId(block.id));
|
|
5444
|
+
},
|
|
5445
|
+
highlighted: highlightedBlockId === block.id,
|
|
5446
|
+
hasRecoveryConflict: typeof block.id === "string" && conflictedBlockIdSet.has(block.id),
|
|
5447
|
+
focusSignal,
|
|
5448
|
+
onFocusHandled: handleFocusHandled,
|
|
5449
|
+
onBlockSave,
|
|
5450
|
+
theme,
|
|
5451
|
+
widgetOverrides,
|
|
5452
|
+
uiStore,
|
|
5453
|
+
sdkConfig,
|
|
5454
|
+
customBlocks,
|
|
5455
|
+
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
5456
|
+
pageDesignBlock: block.id ? pageDesignBlockById.get(block.id) ?? null : null,
|
|
5457
|
+
reorderControlMode,
|
|
5458
|
+
actionControlMode
|
|
5459
|
+
}
|
|
5460
|
+
),
|
|
5461
|
+
allowCreation && index < blockList.length - 1 ? /* @__PURE__ */ jsx(
|
|
5462
|
+
AddBlockDivider,
|
|
5463
|
+
{
|
|
5464
|
+
onOpen: openPicker,
|
|
5465
|
+
position: index + 1
|
|
5466
|
+
}
|
|
5467
|
+
) : null
|
|
5468
|
+
]
|
|
5469
|
+
},
|
|
5470
|
+
block.id ?? index
|
|
5471
|
+
);
|
|
5472
|
+
})
|
|
5473
|
+
] })
|
|
5474
|
+
}
|
|
5475
|
+
)
|
|
5476
|
+
}
|
|
5477
|
+
) : hasBlocks ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed px-4 py-6 text-center text-sm text-muted-foreground", children: "Loading block editor..." }) : allowCreation ? /* @__PURE__ */ jsx(EmptyState2, { onAdd: () => openPicker(0) }) : /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed px-4 py-6 text-center text-sm text-muted-foreground", children: "No blocks available for this page." }),
|
|
5478
|
+
allowCreation && hasBlocks ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs(
|
|
5479
|
+
Button,
|
|
5480
|
+
{
|
|
5481
|
+
type: "button",
|
|
5482
|
+
variant: "secondary",
|
|
5483
|
+
onClick: () => openPicker(blockList.length),
|
|
5484
|
+
children: [
|
|
5485
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-2 h-4 w-4" }),
|
|
5486
|
+
"Add block"
|
|
5487
|
+
]
|
|
5488
|
+
}
|
|
5489
|
+
) }) : null,
|
|
5490
|
+
allowCreation ? /* @__PURE__ */ jsx(
|
|
5491
|
+
EnhancedBlockPickerDialog,
|
|
5492
|
+
{
|
|
5493
|
+
open: pickerOpen,
|
|
5494
|
+
onOpenChange: (open) => open ? openPicker(blockList.length) : closePicker(),
|
|
5495
|
+
creatingBlockName,
|
|
5496
|
+
descriptors: availableBlocks,
|
|
5497
|
+
siteId,
|
|
5498
|
+
existingBlockNames: blockList.map((b) => b.kind).filter(Boolean),
|
|
5499
|
+
enabledContentTypes: fetchedContentTypes,
|
|
5500
|
+
onSelect: (descriptor) => void handleCreateBlock(descriptor)
|
|
5501
|
+
}
|
|
5502
|
+
) : null
|
|
5503
|
+
] }) });
|
|
5504
|
+
}
|
|
5505
|
+
);
|
|
5420
5506
|
function PageBlockEditorPanel({
|
|
5421
5507
|
siteId,
|
|
5422
5508
|
pageId,
|
|
@@ -5743,12 +5829,19 @@ function buildApplySiteStyleSelectionBody(input) {
|
|
|
5743
5829
|
buttonPersonalityId: input.previewed.buttonPersonalityId,
|
|
5744
5830
|
paletteVariantId: input.previewed.paletteVariantId,
|
|
5745
5831
|
paletteOverrides: input.previewed.paletteOverrides,
|
|
5832
|
+
typographyPresetId: input.previewed.typographyPresetId,
|
|
5833
|
+
typographyBodyFontOverride: input.previewed.typographyBodyFontOverride,
|
|
5834
|
+
typographyHeadingFontOverride: input.previewed.typographyHeadingFontOverride,
|
|
5746
5835
|
headerLookId: input.previewed.headerLookId,
|
|
5836
|
+
headerLayoutId: input.previewed.headerLayoutId,
|
|
5837
|
+
headerStyleId: input.previewed.headerStyleId,
|
|
5747
5838
|
footerLookId: input.previewed.footerLookId,
|
|
5748
5839
|
baseSelectionVersion: input.base.selectionVersion,
|
|
5749
5840
|
selectionId: input.selectionId ?? null
|
|
5750
5841
|
};
|
|
5751
5842
|
}
|
|
5843
|
+
var MAX_FONT_RESULTS_WHEN_SEARCHING = 12;
|
|
5844
|
+
var MAX_FONT_RESULTS_WHEN_BROWSING = 8;
|
|
5752
5845
|
function StyleConfigurator({
|
|
5753
5846
|
siteId,
|
|
5754
5847
|
apiClient,
|
|
@@ -5763,7 +5856,14 @@ function StyleConfigurator({
|
|
|
5763
5856
|
siteStyleAccess
|
|
5764
5857
|
}) {
|
|
5765
5858
|
const router = useRouter();
|
|
5766
|
-
const
|
|
5859
|
+
const previewDesign = usePreviewDesignCoordinator();
|
|
5860
|
+
const {
|
|
5861
|
+
applyFailed,
|
|
5862
|
+
applyStarted,
|
|
5863
|
+
applySucceeded,
|
|
5864
|
+
clearPreview,
|
|
5865
|
+
previewTheme
|
|
5866
|
+
} = previewDesign;
|
|
5767
5867
|
const [isRefreshPending, startRefreshTransition] = useTransition();
|
|
5768
5868
|
const baseSnapshot = useMemo(
|
|
5769
5869
|
() => resolveStyleConfiguratorInitialSnapshot({
|
|
@@ -5783,50 +5883,47 @@ function StyleConfigurator({
|
|
|
5783
5883
|
);
|
|
5784
5884
|
const hasLoadedState = state !== null;
|
|
5785
5885
|
const stateRef = useRef(state);
|
|
5786
|
-
const
|
|
5886
|
+
const clearPreviewRef = useRef(clearPreview);
|
|
5787
5887
|
const runnerRef = useRef(createOptimisticActionRunner());
|
|
5788
5888
|
const appliedExpandedRowRequestIdRef = useRef(null);
|
|
5789
5889
|
useEffect(() => {
|
|
5790
5890
|
stateRef.current = state;
|
|
5791
5891
|
}, [state]);
|
|
5792
5892
|
useEffect(() => {
|
|
5793
|
-
|
|
5794
|
-
}, [
|
|
5893
|
+
clearPreviewRef.current = clearPreview;
|
|
5894
|
+
}, [clearPreview]);
|
|
5795
5895
|
useEffect(() => {
|
|
5796
5896
|
if (!baseSnapshot) return;
|
|
5797
5897
|
setState((current) => current ? syncStyleConfiguratorState(current, baseSnapshot) : createStyleConfiguratorState(baseSnapshot));
|
|
5798
5898
|
}, [baseSnapshot]);
|
|
5799
5899
|
useEffect(() => {
|
|
5800
5900
|
if (!state || !baseSnapshot) {
|
|
5801
|
-
|
|
5901
|
+
clearPreview("style-configurator");
|
|
5802
5902
|
return;
|
|
5803
5903
|
}
|
|
5804
5904
|
if (!isPreviewingChange(state)) {
|
|
5805
|
-
|
|
5905
|
+
clearPreview("style-configurator");
|
|
5806
5906
|
return;
|
|
5807
5907
|
}
|
|
5808
5908
|
const siteStyle = getCuratedSiteStyle(state.previewed.siteStyleId);
|
|
5809
5909
|
if (!siteStyle) {
|
|
5810
|
-
|
|
5910
|
+
clearPreview("style-configurator");
|
|
5811
5911
|
return;
|
|
5812
5912
|
}
|
|
5813
|
-
const result =
|
|
5913
|
+
const result = planSiteStylePreviewChange({
|
|
5814
5914
|
siteStyle,
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
paletteOverrides: state.previewed.paletteOverrides,
|
|
5818
|
-
headerLookId: state.previewed.headerLookId,
|
|
5819
|
-
footerLookId: state.previewed.footerLookId,
|
|
5915
|
+
selection: state.previewed,
|
|
5916
|
+
baseTheme: theme,
|
|
5820
5917
|
headerSelectionContext,
|
|
5821
5918
|
footerSelectionContext
|
|
5822
5919
|
});
|
|
5823
|
-
|
|
5824
|
-
}, [state, baseSnapshot,
|
|
5920
|
+
previewTheme("style-configurator", result.themeOverlay, "site-style");
|
|
5921
|
+
}, [state, baseSnapshot, clearPreview, previewTheme, headerSelectionContext, footerSelectionContext, theme]);
|
|
5825
5922
|
useEffect(() => {
|
|
5826
5923
|
const runner = runnerRef.current;
|
|
5827
5924
|
return () => {
|
|
5828
5925
|
runner.invalidate();
|
|
5829
|
-
|
|
5926
|
+
clearPreviewRef.current("style-configurator");
|
|
5830
5927
|
};
|
|
5831
5928
|
}, []);
|
|
5832
5929
|
useEffect(() => {
|
|
@@ -5835,7 +5932,7 @@ function StyleConfigurator({
|
|
|
5835
5932
|
setState((current) => {
|
|
5836
5933
|
if (!current) return current;
|
|
5837
5934
|
appliedExpandedRowRequestIdRef.current = expandedRowRequest.id;
|
|
5838
|
-
return openRow(current, expandedRowRequest.row);
|
|
5935
|
+
return openRow(current, expandedRowRequest.row === "header" ? "header-layout" : expandedRowRequest.row);
|
|
5839
5936
|
});
|
|
5840
5937
|
}, [expandedRowRequest, hasLoadedState]);
|
|
5841
5938
|
const handlePreviewSiteStyle = useCallback((siteStyleId) => {
|
|
@@ -5844,13 +5941,10 @@ function StyleConfigurator({
|
|
|
5844
5941
|
const next = previewSiteStyle(current, siteStyleId);
|
|
5845
5942
|
const siteStyle = getCuratedSiteStyle(siteStyleId);
|
|
5846
5943
|
if (!siteStyle) return next;
|
|
5847
|
-
const result =
|
|
5944
|
+
const result = planSiteStylePreviewChange({
|
|
5848
5945
|
siteStyle,
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
paletteOverrides: next.previewed.paletteOverrides,
|
|
5852
|
-
headerLookId: next.previewed.headerLookId,
|
|
5853
|
-
footerLookId: next.previewed.footerLookId,
|
|
5946
|
+
selection: next.previewed,
|
|
5947
|
+
baseTheme: theme,
|
|
5854
5948
|
headerSelectionContext,
|
|
5855
5949
|
footerSelectionContext
|
|
5856
5950
|
});
|
|
@@ -5859,14 +5953,17 @@ function StyleConfigurator({
|
|
|
5859
5953
|
warnings: result.warnings
|
|
5860
5954
|
});
|
|
5861
5955
|
});
|
|
5862
|
-
}, [footerSelectionContext, headerSelectionContext]);
|
|
5956
|
+
}, [footerSelectionContext, headerSelectionContext, theme]);
|
|
5863
5957
|
const handlePreviewPersonality = useCallback((id) => {
|
|
5864
5958
|
setState((current) => current ? previewButtonPersonality(current, id) : current);
|
|
5865
5959
|
}, []);
|
|
5866
|
-
const
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5960
|
+
const handlePreviewHeaderLayout = useCallback((id) => {
|
|
5961
|
+
if (!id) return;
|
|
5962
|
+
setState((current) => current ? previewHeaderLayout(current, id) : current);
|
|
5963
|
+
}, []);
|
|
5964
|
+
const handlePreviewHeaderStyle = useCallback((id) => {
|
|
5965
|
+
if (!id) return;
|
|
5966
|
+
setState((current) => current ? previewHeaderStyle(current, id) : current);
|
|
5870
5967
|
}, []);
|
|
5871
5968
|
const handlePreviewFooterLook = useCallback((id) => {
|
|
5872
5969
|
const plan = planSiteChromeLookSelection({ surface: "footer", lookId: id });
|
|
@@ -5876,6 +5973,18 @@ function StyleConfigurator({
|
|
|
5876
5973
|
const handlePreviewPalette = useCallback((id) => {
|
|
5877
5974
|
setState((current) => current ? previewPaletteVariant(current, id) : current);
|
|
5878
5975
|
}, []);
|
|
5976
|
+
const handlePreviewTypographyPreset = useCallback((id) => {
|
|
5977
|
+
setState((current) => current ? previewTypographyPreset(current, id) : current);
|
|
5978
|
+
}, []);
|
|
5979
|
+
const handleBodyFontOverride = useCallback((fontFamily) => {
|
|
5980
|
+
setState((current) => current ? setTypographyBodyFontOverride(current, fontFamily) : current);
|
|
5981
|
+
}, []);
|
|
5982
|
+
const handleHeadingFontOverride = useCallback((fontFamily) => {
|
|
5983
|
+
setState((current) => current ? setTypographyHeadingFontOverride(current, fontFamily) : current);
|
|
5984
|
+
}, []);
|
|
5985
|
+
const handleClearTypographyOverrides = useCallback(() => {
|
|
5986
|
+
setState((current) => current ? clearTypographyFontOverrides(current) : current);
|
|
5987
|
+
}, []);
|
|
5879
5988
|
const handleTokenOverride = useCallback((role, hex) => {
|
|
5880
5989
|
setState((current) => {
|
|
5881
5990
|
if (!current) return current;
|
|
@@ -5906,13 +6015,10 @@ function StyleConfigurator({
|
|
|
5906
6015
|
const previewed = live.previewed;
|
|
5907
6016
|
const siteStyle = getCuratedSiteStyle(previewed.siteStyleId);
|
|
5908
6017
|
if (!siteStyle) return;
|
|
5909
|
-
const compiled =
|
|
6018
|
+
const compiled = planSiteStylePreviewChange({
|
|
5910
6019
|
siteStyle,
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
paletteOverrides: previewed.paletteOverrides,
|
|
5914
|
-
headerLookId: previewed.headerLookId,
|
|
5915
|
-
footerLookId: previewed.footerLookId,
|
|
6020
|
+
selection: previewed,
|
|
6021
|
+
baseTheme: theme,
|
|
5916
6022
|
headerSelectionContext,
|
|
5917
6023
|
footerSelectionContext
|
|
5918
6024
|
});
|
|
@@ -5921,12 +6027,19 @@ function StyleConfigurator({
|
|
|
5921
6027
|
previewed: {
|
|
5922
6028
|
...previewed,
|
|
5923
6029
|
buttonPersonalityId: compiled.resolvedSelections.buttonPersonalityId,
|
|
5924
|
-
paletteVariantId: compiled.resolvedSelections.paletteVariantId
|
|
6030
|
+
paletteVariantId: compiled.resolvedSelections.paletteVariantId,
|
|
6031
|
+
headerLayoutId: compiled.resolvedSelections.headerLayoutId,
|
|
6032
|
+
headerStyleId: compiled.resolvedSelections.headerStyleId,
|
|
6033
|
+
headerLookId: compiled.resolvedSelections.headerLookId,
|
|
6034
|
+
typographyPresetId: compiled.resolvedSelections.typographyPresetId,
|
|
6035
|
+
typographyBodyFontOverride: compiled.resolvedSelections.typographyBodyFontOverride,
|
|
6036
|
+
typographyHeadingFontOverride: compiled.resolvedSelections.typographyHeadingFontOverride
|
|
5925
6037
|
},
|
|
5926
6038
|
selectionId
|
|
5927
6039
|
});
|
|
5928
6040
|
await runnerRef.current.run({
|
|
5929
6041
|
optimistic: () => {
|
|
6042
|
+
applyStarted("style-configurator");
|
|
5930
6043
|
setState((current) => current ? markApplySaving(current) : current);
|
|
5931
6044
|
},
|
|
5932
6045
|
network: async () => {
|
|
@@ -5946,15 +6059,22 @@ function StyleConfigurator({
|
|
|
5946
6059
|
buttonPersonalityId: saved.buttonPersonalityId,
|
|
5947
6060
|
paletteVariantId: saved.paletteVariantId,
|
|
5948
6061
|
paletteOverrides: saved.paletteOverrides ?? null,
|
|
6062
|
+
typographyPresetId: saved.typographyPresetId,
|
|
6063
|
+
typographyBodyFontOverride: saved.typographyBodyFontOverride,
|
|
6064
|
+
typographyHeadingFontOverride: saved.typographyHeadingFontOverride,
|
|
5949
6065
|
headerLookId: saved.headerLookId,
|
|
6066
|
+
headerLayoutId: saved.headerLayoutId,
|
|
6067
|
+
headerStyleId: saved.headerStyleId,
|
|
5950
6068
|
footerLookId: saved.footerLookId
|
|
5951
6069
|
}) : current
|
|
5952
6070
|
);
|
|
6071
|
+
applySucceeded("style-configurator");
|
|
5953
6072
|
startRefreshTransition(() => {
|
|
5954
6073
|
router.refresh();
|
|
5955
6074
|
});
|
|
5956
6075
|
},
|
|
5957
6076
|
onError: (error) => {
|
|
6077
|
+
applyFailed("style-configurator");
|
|
5958
6078
|
const applyError = classifyStyleApplyError(error);
|
|
5959
6079
|
if (applyError.kind === "stale") {
|
|
5960
6080
|
startRefreshTransition(() => {
|
|
@@ -5969,10 +6089,14 @@ function StyleConfigurator({
|
|
|
5969
6089
|
apiClient,
|
|
5970
6090
|
footerSelectionContext,
|
|
5971
6091
|
headerSelectionContext,
|
|
6092
|
+
applyFailed,
|
|
6093
|
+
applyStarted,
|
|
6094
|
+
applySucceeded,
|
|
5972
6095
|
router,
|
|
5973
6096
|
selectionId,
|
|
5974
6097
|
siteId,
|
|
5975
|
-
startRefreshTransition
|
|
6098
|
+
startRefreshTransition,
|
|
6099
|
+
theme
|
|
5976
6100
|
]);
|
|
5977
6101
|
if (!state || !baseSnapshot) {
|
|
5978
6102
|
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading design controls..." });
|
|
@@ -5986,13 +6110,15 @@ function StyleConfigurator({
|
|
|
5986
6110
|
}
|
|
5987
6111
|
const currentPersonality = findButtonPersonality(state.previewed.buttonPersonalityId);
|
|
5988
6112
|
const currentPaletteVariant = findPaletteVariant(state.previewed.paletteVariantId);
|
|
6113
|
+
const currentTypographyPreset = state.previewed.typographyPresetId ? findTypographyPreset(state.previewed.typographyPresetId) : null;
|
|
5989
6114
|
const chromeLookModels = buildSiteChromeLookModels({
|
|
5990
6115
|
state,
|
|
5991
6116
|
siteStyle: currentSiteStyle,
|
|
5992
6117
|
headerSelectionContext,
|
|
5993
6118
|
footerSelectionContext
|
|
5994
6119
|
});
|
|
5995
|
-
const
|
|
6120
|
+
const currentHeaderLayout = getHeaderLayout(state.previewed.headerLayoutId);
|
|
6121
|
+
const currentHeaderStyle = getHeaderStyle(state.previewed.headerStyleId);
|
|
5996
6122
|
const currentFooterLook = state.previewed.footerLookId ? findFooterLook(state.previewed.footerLookId) : findFooterLook(chromeLookModels.footer.renderedLookId);
|
|
5997
6123
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
5998
6124
|
state.warnings.length > 0 ? /* @__PURE__ */ jsx(WarningNotice, { warnings: state.warnings, onDismiss: handleDismissWarnings }) : null,
|
|
@@ -6010,22 +6136,42 @@ function StyleConfigurator({
|
|
|
6010
6136
|
/* @__PURE__ */ jsx(
|
|
6011
6137
|
SiteChromeLookRow,
|
|
6012
6138
|
{
|
|
6013
|
-
label: "Header",
|
|
6014
|
-
ariaLabel: "Header",
|
|
6015
|
-
defaultDescription: "
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6139
|
+
label: "Header layout",
|
|
6140
|
+
ariaLabel: "Header layout",
|
|
6141
|
+
defaultDescription: "Choose the header structure.",
|
|
6142
|
+
expanded: state.expandedRow === "header-layout",
|
|
6143
|
+
onToggle: () => handleToggleRow("header-layout"),
|
|
6144
|
+
currentId: state.previewed.headerLayoutId,
|
|
6145
|
+
currentLabel: currentHeaderLayout?.label ?? state.previewed.headerLayoutId,
|
|
6146
|
+
scopeDescription: "Changes the header structure on every page.",
|
|
6147
|
+
options: chromeLookModels.headerLayout.options,
|
|
6148
|
+
diagnostics: [],
|
|
6149
|
+
onCycle: (direction) => {
|
|
6150
|
+
const next = cycleSiteChromeLookId(chromeLookModels.headerLayout.options, state.previewed.headerLayoutId, direction);
|
|
6151
|
+
if (next !== void 0) handlePreviewHeaderLayout(next);
|
|
6152
|
+
},
|
|
6153
|
+
onPreview: handlePreviewHeaderLayout,
|
|
6154
|
+
disabled: saving
|
|
6155
|
+
}
|
|
6156
|
+
),
|
|
6157
|
+
/* @__PURE__ */ jsx(
|
|
6158
|
+
SiteChromeLookRow,
|
|
6159
|
+
{
|
|
6160
|
+
label: "Header look",
|
|
6161
|
+
ariaLabel: "Header look",
|
|
6162
|
+
defaultDescription: "Choose the header visual style.",
|
|
6163
|
+
expanded: state.expandedRow === "header-style",
|
|
6164
|
+
onToggle: () => handleToggleRow("header-style"),
|
|
6165
|
+
currentId: state.previewed.headerStyleId,
|
|
6166
|
+
currentLabel: currentHeaderStyle?.label ?? state.previewed.headerStyleId,
|
|
6167
|
+
scopeDescription: "Changes the header surface and link style.",
|
|
6168
|
+
options: chromeLookModels.headerStyle.options,
|
|
6169
|
+
diagnostics: [],
|
|
6024
6170
|
onCycle: (direction) => {
|
|
6025
|
-
const next = cycleSiteChromeLookId(chromeLookModels.
|
|
6026
|
-
if (next !== void 0)
|
|
6171
|
+
const next = cycleSiteChromeLookId(chromeLookModels.headerStyle.options, state.previewed.headerStyleId, direction);
|
|
6172
|
+
if (next !== void 0) handlePreviewHeaderStyle(next);
|
|
6027
6173
|
},
|
|
6028
|
-
onPreview:
|
|
6174
|
+
onPreview: handlePreviewHeaderStyle,
|
|
6029
6175
|
disabled: saving
|
|
6030
6176
|
}
|
|
6031
6177
|
),
|
|
@@ -6063,6 +6209,24 @@ function StyleConfigurator({
|
|
|
6063
6209
|
disabled: saving
|
|
6064
6210
|
}
|
|
6065
6211
|
),
|
|
6212
|
+
/* @__PURE__ */ jsx(
|
|
6213
|
+
TypographyRow,
|
|
6214
|
+
{
|
|
6215
|
+
expanded: state.expandedRow === "typography",
|
|
6216
|
+
onToggle: () => handleToggleRow("typography"),
|
|
6217
|
+
apiClient,
|
|
6218
|
+
siteStyle: currentSiteStyle,
|
|
6219
|
+
currentPresetId: state.previewed.typographyPresetId,
|
|
6220
|
+
currentLabel: currentTypographyPreset?.name ?? "Custom typography",
|
|
6221
|
+
bodyFontOverride: state.previewed.typographyBodyFontOverride,
|
|
6222
|
+
headingFontOverride: state.previewed.typographyHeadingFontOverride,
|
|
6223
|
+
onPreviewPreset: handlePreviewTypographyPreset,
|
|
6224
|
+
onBodyFontOverride: handleBodyFontOverride,
|
|
6225
|
+
onHeadingFontOverride: handleHeadingFontOverride,
|
|
6226
|
+
onClearOverrides: handleClearTypographyOverrides,
|
|
6227
|
+
disabled: saving
|
|
6228
|
+
}
|
|
6229
|
+
),
|
|
6066
6230
|
/* @__PURE__ */ jsx(
|
|
6067
6231
|
PaletteRow,
|
|
6068
6232
|
{
|
|
@@ -6154,6 +6318,407 @@ function PersonalityRow({ expanded, onToggle, siteStyle, currentId, currentLabel
|
|
|
6154
6318
|
personality.id
|
|
6155
6319
|
)) }) });
|
|
6156
6320
|
}
|
|
6321
|
+
function TypographyRow({
|
|
6322
|
+
expanded,
|
|
6323
|
+
onToggle,
|
|
6324
|
+
apiClient,
|
|
6325
|
+
siteStyle,
|
|
6326
|
+
currentPresetId,
|
|
6327
|
+
currentLabel,
|
|
6328
|
+
bodyFontOverride,
|
|
6329
|
+
headingFontOverride,
|
|
6330
|
+
onPreviewPreset,
|
|
6331
|
+
onBodyFontOverride,
|
|
6332
|
+
onHeadingFontOverride,
|
|
6333
|
+
onClearOverrides,
|
|
6334
|
+
disabled
|
|
6335
|
+
}) {
|
|
6336
|
+
const options = useMemo(
|
|
6337
|
+
() => requireEntriesForCuratedChoices(typographyPresets, siteStyle.typographyPresetChoices),
|
|
6338
|
+
[siteStyle.typographyPresetChoices]
|
|
6339
|
+
);
|
|
6340
|
+
const fontCatalog = useFontCatalog(apiClient, expanded);
|
|
6341
|
+
const selectedPreset = currentPresetId ? findTypographyPreset(currentPresetId) : null;
|
|
6342
|
+
return /* @__PURE__ */ jsxs(StyleRowFrame, { label: "Typography", currentLabel, expanded, onToggle, children: [
|
|
6343
|
+
currentPresetId === null ? /* @__PURE__ */ jsx("div", { className: "mb-3 rounded-md border border-muted-foreground/20 bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "Current custom setup" }) : null,
|
|
6344
|
+
/* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": "Typography preset", className: "space-y-1", children: options.map((preset) => /* @__PURE__ */ jsx(
|
|
6345
|
+
TypographyPresetOption,
|
|
6346
|
+
{
|
|
6347
|
+
preset,
|
|
6348
|
+
selected: preset.id === currentPresetId,
|
|
6349
|
+
onSelect: () => onPreviewPreset(preset.id),
|
|
6350
|
+
disabled
|
|
6351
|
+
},
|
|
6352
|
+
preset.id
|
|
6353
|
+
)) }),
|
|
6354
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-3 border-t pt-3", children: [
|
|
6355
|
+
selectedPreset ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6356
|
+
/* @__PURE__ */ jsx(
|
|
6357
|
+
TypographyFontSlotPicker,
|
|
6358
|
+
{
|
|
6359
|
+
label: "Body font",
|
|
6360
|
+
slot: "body",
|
|
6361
|
+
preset: selectedPreset,
|
|
6362
|
+
catalog: fontCatalog,
|
|
6363
|
+
value: bodyFontOverride,
|
|
6364
|
+
onChange: onBodyFontOverride,
|
|
6365
|
+
disabled
|
|
6366
|
+
}
|
|
6367
|
+
),
|
|
6368
|
+
/* @__PURE__ */ jsx(
|
|
6369
|
+
TypographyFontSlotPicker,
|
|
6370
|
+
{
|
|
6371
|
+
label: "Heading font",
|
|
6372
|
+
slot: "heading",
|
|
6373
|
+
preset: selectedPreset,
|
|
6374
|
+
catalog: fontCatalog,
|
|
6375
|
+
value: headingFontOverride,
|
|
6376
|
+
onChange: onHeadingFontOverride,
|
|
6377
|
+
disabled
|
|
6378
|
+
}
|
|
6379
|
+
)
|
|
6380
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Choose a typography preset to use curated font overrides." }),
|
|
6381
|
+
/* @__PURE__ */ jsx(
|
|
6382
|
+
Button,
|
|
6383
|
+
{
|
|
6384
|
+
type: "button",
|
|
6385
|
+
size: "sm",
|
|
6386
|
+
variant: "outline",
|
|
6387
|
+
onClick: onClearOverrides,
|
|
6388
|
+
disabled: disabled || !bodyFontOverride && !headingFontOverride,
|
|
6389
|
+
children: "Use preset fonts"
|
|
6390
|
+
}
|
|
6391
|
+
)
|
|
6392
|
+
] })
|
|
6393
|
+
] });
|
|
6394
|
+
}
|
|
6395
|
+
function TypographyPresetOption({
|
|
6396
|
+
preset,
|
|
6397
|
+
selected,
|
|
6398
|
+
onSelect,
|
|
6399
|
+
disabled
|
|
6400
|
+
}) {
|
|
6401
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
6402
|
+
"button",
|
|
6403
|
+
{
|
|
6404
|
+
type: "button",
|
|
6405
|
+
role: "radio",
|
|
6406
|
+
"aria-checked": selected,
|
|
6407
|
+
onClick: onSelect,
|
|
6408
|
+
disabled,
|
|
6409
|
+
className: cn(
|
|
6410
|
+
"w-full rounded-md border px-3 py-2 text-left transition disabled:cursor-not-allowed disabled:opacity-50",
|
|
6411
|
+
selected ? "border-primary bg-primary/5" : "border-border hover:bg-muted/60"
|
|
6412
|
+
),
|
|
6413
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
6414
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
6415
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: preset.name }),
|
|
6416
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: preset.description })
|
|
6417
|
+
] }),
|
|
6418
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 text-right", children: [
|
|
6419
|
+
/* @__PURE__ */ jsx("div", { className: "text-[11px] font-semibold uppercase tracking-wide", children: preset.defaultFonts.heading.split(",")[0] }),
|
|
6420
|
+
/* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground", children: preset.defaultFonts.body.split(",")[0] })
|
|
6421
|
+
] })
|
|
6422
|
+
] })
|
|
6423
|
+
}
|
|
6424
|
+
) });
|
|
6425
|
+
}
|
|
6426
|
+
function TypographyFontSlotPicker({
|
|
6427
|
+
label,
|
|
6428
|
+
slot,
|
|
6429
|
+
preset,
|
|
6430
|
+
catalog,
|
|
6431
|
+
value,
|
|
6432
|
+
onChange,
|
|
6433
|
+
disabled
|
|
6434
|
+
}) {
|
|
6435
|
+
const [query, setQuery] = useState("");
|
|
6436
|
+
const defaultFont = primaryFontFamily(preset.defaultFonts[slot]);
|
|
6437
|
+
const selectedFamily = value ?? defaultFont;
|
|
6438
|
+
const recordsByFamily = useMemo(() => indexFontsByFamily(catalog.fonts), [catalog.fonts]);
|
|
6439
|
+
const selectedFit = evaluateTypographyFontSlot({
|
|
6440
|
+
slot,
|
|
6441
|
+
policy: preset.slotPolicies[slot],
|
|
6442
|
+
capability: capabilityForFamily(selectedFamily, recordsByFamily)
|
|
6443
|
+
});
|
|
6444
|
+
const recommendedFamilies = preset.recommendedFonts[slot];
|
|
6445
|
+
const recommendedOptions = useMemo(
|
|
6446
|
+
() => uniqueFontFamilies(recommendedFamilies),
|
|
6447
|
+
[recommendedFamilies]
|
|
6448
|
+
);
|
|
6449
|
+
const browseOptions = useMemo(() => {
|
|
6450
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
6451
|
+
const source = normalizedQuery.length > 0 ? catalog.fonts.filter((font) => font.family.toLowerCase().includes(normalizedQuery)) : catalog.fonts;
|
|
6452
|
+
return [...source].sort((a, b) => sortFontForPresetSlot(a, b, slot, preset, recordsByFamily)).slice(0, normalizedQuery.length > 0 ? MAX_FONT_RESULTS_WHEN_SEARCHING : MAX_FONT_RESULTS_WHEN_BROWSING);
|
|
6453
|
+
}, [catalog.fonts, preset, query, recordsByFamily, slot]);
|
|
6454
|
+
return /* @__PURE__ */ jsxs("section", { className: "space-y-2", "aria-label": label, children: [
|
|
6455
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
6456
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
6457
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-muted-foreground", children: label }),
|
|
6458
|
+
/* @__PURE__ */ jsx("div", { className: "truncate text-sm", children: value ? selectedFamily : `${defaultFont} (preset)` })
|
|
6459
|
+
] }),
|
|
6460
|
+
/* @__PURE__ */ jsx(TypographyFontFitBadge, { fit: selectedFit })
|
|
6461
|
+
] }),
|
|
6462
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-1", children: [
|
|
6463
|
+
/* @__PURE__ */ jsxs(
|
|
6464
|
+
"button",
|
|
6465
|
+
{
|
|
6466
|
+
type: "button",
|
|
6467
|
+
className: cn(
|
|
6468
|
+
"rounded-md border px-3 py-2 text-left text-sm transition disabled:cursor-not-allowed disabled:opacity-50",
|
|
6469
|
+
value === null ? "border-foreground bg-accent/40" : "border-transparent hover:border-foreground/40 hover:bg-accent/20"
|
|
6470
|
+
),
|
|
6471
|
+
onClick: () => onChange(null),
|
|
6472
|
+
disabled,
|
|
6473
|
+
children: [
|
|
6474
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Use preset font" }),
|
|
6475
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: defaultFont })
|
|
6476
|
+
]
|
|
6477
|
+
}
|
|
6478
|
+
),
|
|
6479
|
+
recommendedOptions.map((family) => /* @__PURE__ */ jsx(
|
|
6480
|
+
FontFamilyOption,
|
|
6481
|
+
{
|
|
6482
|
+
family,
|
|
6483
|
+
selected: value === family,
|
|
6484
|
+
fit: evaluateTypographyFontSlot({
|
|
6485
|
+
slot,
|
|
6486
|
+
policy: preset.slotPolicies[slot],
|
|
6487
|
+
capability: capabilityForFamily(family, recordsByFamily)
|
|
6488
|
+
}),
|
|
6489
|
+
onSelect: () => onChange(family),
|
|
6490
|
+
disabled
|
|
6491
|
+
},
|
|
6492
|
+
family
|
|
6493
|
+
))
|
|
6494
|
+
] }),
|
|
6495
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border bg-muted/20 p-2", children: [
|
|
6496
|
+
/* @__PURE__ */ jsx(
|
|
6497
|
+
"input",
|
|
6498
|
+
{
|
|
6499
|
+
type: "search",
|
|
6500
|
+
value: query,
|
|
6501
|
+
placeholder: `Search ${slot} fonts`,
|
|
6502
|
+
onChange: (event) => setQuery(event.currentTarget.value),
|
|
6503
|
+
disabled: disabled || catalog.kind === "loading",
|
|
6504
|
+
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"
|
|
6505
|
+
}
|
|
6506
|
+
),
|
|
6507
|
+
catalog.kind === "loading" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading font catalog..." }) : catalog.kind === "failed" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: catalog.message }) : null,
|
|
6508
|
+
browseOptions.length > 0 ? /* @__PURE__ */ jsx("div", { className: "max-h-56 space-y-1 overflow-y-auto pr-1", children: browseOptions.map((font) => /* @__PURE__ */ jsx(
|
|
6509
|
+
FontFamilyOption,
|
|
6510
|
+
{
|
|
6511
|
+
family: font.family,
|
|
6512
|
+
selected: value === font.family,
|
|
6513
|
+
fit: evaluateTypographyFontSlot({
|
|
6514
|
+
slot,
|
|
6515
|
+
policy: preset.slotPolicies[slot],
|
|
6516
|
+
capability: capabilityFromFontRecord(font)
|
|
6517
|
+
}),
|
|
6518
|
+
onSelect: () => onChange(font.family),
|
|
6519
|
+
disabled
|
|
6520
|
+
},
|
|
6521
|
+
font.family
|
|
6522
|
+
)) }) : catalog.kind === "loaded" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No matching Google Fonts." }) : null
|
|
6523
|
+
] }),
|
|
6524
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1", children: [
|
|
6525
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Brand or uploaded font name" }),
|
|
6526
|
+
/* @__PURE__ */ jsx(
|
|
6527
|
+
"input",
|
|
6528
|
+
{
|
|
6529
|
+
type: "text",
|
|
6530
|
+
value: value ?? "",
|
|
6531
|
+
placeholder: "Enter any font family",
|
|
6532
|
+
onChange: (event) => onChange(normalizeFontFamilyOverride(event.currentTarget.value)),
|
|
6533
|
+
disabled,
|
|
6534
|
+
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"
|
|
6535
|
+
}
|
|
6536
|
+
)
|
|
6537
|
+
] })
|
|
6538
|
+
] });
|
|
6539
|
+
}
|
|
6540
|
+
function FontFamilyOption({
|
|
6541
|
+
family,
|
|
6542
|
+
selected,
|
|
6543
|
+
fit,
|
|
6544
|
+
onSelect,
|
|
6545
|
+
disabled
|
|
6546
|
+
}) {
|
|
6547
|
+
return /* @__PURE__ */ jsxs(
|
|
6548
|
+
"button",
|
|
6549
|
+
{
|
|
6550
|
+
type: "button",
|
|
6551
|
+
className: cn(
|
|
6552
|
+
"flex w-full items-center justify-between gap-3 rounded-md border px-3 py-2 text-left text-sm transition disabled:cursor-not-allowed disabled:opacity-50",
|
|
6553
|
+
selected ? "border-foreground bg-accent/40" : "border-transparent bg-background hover:border-foreground/40 hover:bg-accent/20"
|
|
6554
|
+
),
|
|
6555
|
+
onClick: onSelect,
|
|
6556
|
+
disabled,
|
|
6557
|
+
children: [
|
|
6558
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: family }),
|
|
6559
|
+
/* @__PURE__ */ jsx(TypographyFontFitBadge, { fit })
|
|
6560
|
+
]
|
|
6561
|
+
}
|
|
6562
|
+
);
|
|
6563
|
+
}
|
|
6564
|
+
function TypographyFontFitBadge({ fit }) {
|
|
6565
|
+
return /* @__PURE__ */ jsx(
|
|
6566
|
+
"span",
|
|
6567
|
+
{
|
|
6568
|
+
className: cn(
|
|
6569
|
+
"shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium",
|
|
6570
|
+
fit.kind === "recommended" && "bg-emerald-100 text-emerald-800",
|
|
6571
|
+
fit.kind === "compatible" && "bg-sky-100 text-sky-800",
|
|
6572
|
+
fit.kind === "limited" && "bg-amber-100 text-amber-900",
|
|
6573
|
+
fit.kind === "risky" && "bg-rose-100 text-rose-800",
|
|
6574
|
+
fit.kind === "unknown" && "bg-muted text-muted-foreground"
|
|
6575
|
+
),
|
|
6576
|
+
title: fit.reason,
|
|
6577
|
+
children: typographyFontFitLabel(fit.kind)
|
|
6578
|
+
}
|
|
6579
|
+
);
|
|
6580
|
+
}
|
|
6581
|
+
function useFontCatalog(apiClient, enabled) {
|
|
6582
|
+
const [catalog, setCatalog] = useState({ kind: "idle", fonts: [] });
|
|
6583
|
+
const requestedClientRef = useRef(null);
|
|
6584
|
+
useEffect(() => {
|
|
6585
|
+
if (!enabled) return;
|
|
6586
|
+
if (requestedClientRef.current === apiClient) return;
|
|
6587
|
+
requestedClientRef.current = apiClient;
|
|
6588
|
+
let cancelled = false;
|
|
6589
|
+
setCatalog({ kind: "loading", fonts: [] });
|
|
6590
|
+
async function loadFonts() {
|
|
6591
|
+
try {
|
|
6592
|
+
const response = await apiClient({ endpoint: "listFonts" });
|
|
6593
|
+
const fonts = unwrapResponse(response);
|
|
6594
|
+
if (!cancelled) {
|
|
6595
|
+
setCatalog({
|
|
6596
|
+
kind: "loaded",
|
|
6597
|
+
fonts: Array.isArray(fonts) ? fonts : []
|
|
6598
|
+
});
|
|
6599
|
+
}
|
|
6600
|
+
} catch (error) {
|
|
6601
|
+
if (!cancelled) {
|
|
6602
|
+
setCatalog({
|
|
6603
|
+
kind: "failed",
|
|
6604
|
+
fonts: [],
|
|
6605
|
+
message: error instanceof Error ? error.message : "Unable to load the font catalog."
|
|
6606
|
+
});
|
|
6607
|
+
}
|
|
6608
|
+
}
|
|
6609
|
+
}
|
|
6610
|
+
void loadFonts();
|
|
6611
|
+
return () => {
|
|
6612
|
+
cancelled = true;
|
|
6613
|
+
};
|
|
6614
|
+
}, [apiClient, enabled]);
|
|
6615
|
+
return catalog;
|
|
6616
|
+
}
|
|
6617
|
+
function indexFontsByFamily(fonts) {
|
|
6618
|
+
return new Map(fonts.map((font) => [font.family.toLowerCase(), font]));
|
|
6619
|
+
}
|
|
6620
|
+
function capabilityForFamily(family, recordsByFamily) {
|
|
6621
|
+
const record = recordsByFamily.get(family.toLowerCase());
|
|
6622
|
+
if (record) return capabilityFromFontRecord(record);
|
|
6623
|
+
return {
|
|
6624
|
+
source: "unknown",
|
|
6625
|
+
family,
|
|
6626
|
+
category: "unknown",
|
|
6627
|
+
variants: []
|
|
6628
|
+
};
|
|
6629
|
+
}
|
|
6630
|
+
function capabilityFromFontRecord(font) {
|
|
6631
|
+
return {
|
|
6632
|
+
source: "google",
|
|
6633
|
+
family: font.family,
|
|
6634
|
+
category: normalizeGoogleFontCategory(font.category),
|
|
6635
|
+
variants: font.variants
|
|
6636
|
+
};
|
|
6637
|
+
}
|
|
6638
|
+
function normalizeGoogleFontCategory(category) {
|
|
6639
|
+
switch (category) {
|
|
6640
|
+
case "serif":
|
|
6641
|
+
case "sans-serif":
|
|
6642
|
+
case "display":
|
|
6643
|
+
case "handwriting":
|
|
6644
|
+
case "monospace":
|
|
6645
|
+
return category;
|
|
6646
|
+
default:
|
|
6647
|
+
return "unknown";
|
|
6648
|
+
}
|
|
6649
|
+
}
|
|
6650
|
+
function sortFontForPresetSlot(a, b, slot, preset, recordsByFamily) {
|
|
6651
|
+
const aFit = evaluateTypographyFontSlot({
|
|
6652
|
+
slot,
|
|
6653
|
+
policy: preset.slotPolicies[slot],
|
|
6654
|
+
capability: capabilityForFamily(a.family, recordsByFamily)
|
|
6655
|
+
});
|
|
6656
|
+
const bFit = evaluateTypographyFontSlot({
|
|
6657
|
+
slot,
|
|
6658
|
+
policy: preset.slotPolicies[slot],
|
|
6659
|
+
capability: capabilityForFamily(b.family, recordsByFamily)
|
|
6660
|
+
});
|
|
6661
|
+
const fitDelta = typographyFontFitRank(aFit.kind) - typographyFontFitRank(bFit.kind);
|
|
6662
|
+
if (fitDelta !== 0) return fitDelta;
|
|
6663
|
+
const popularityDelta = (a.popularity ?? Infinity) - (b.popularity ?? Infinity);
|
|
6664
|
+
if (popularityDelta !== 0) return popularityDelta;
|
|
6665
|
+
return a.family.localeCompare(b.family);
|
|
6666
|
+
}
|
|
6667
|
+
function typographyFontFitRank(kind) {
|
|
6668
|
+
switch (kind) {
|
|
6669
|
+
case "recommended":
|
|
6670
|
+
return 0;
|
|
6671
|
+
case "compatible":
|
|
6672
|
+
return 1;
|
|
6673
|
+
case "limited":
|
|
6674
|
+
return 2;
|
|
6675
|
+
case "risky":
|
|
6676
|
+
return 3;
|
|
6677
|
+
case "unknown":
|
|
6678
|
+
return 4;
|
|
6679
|
+
default: {
|
|
6680
|
+
const exhaustive = kind;
|
|
6681
|
+
return exhaustive;
|
|
6682
|
+
}
|
|
6683
|
+
}
|
|
6684
|
+
}
|
|
6685
|
+
function typographyFontFitLabel(kind) {
|
|
6686
|
+
switch (kind) {
|
|
6687
|
+
case "recommended":
|
|
6688
|
+
return "Recommended";
|
|
6689
|
+
case "compatible":
|
|
6690
|
+
return "Compatible";
|
|
6691
|
+
case "limited":
|
|
6692
|
+
return "Limited";
|
|
6693
|
+
case "risky":
|
|
6694
|
+
return "Risky";
|
|
6695
|
+
case "unknown":
|
|
6696
|
+
return "Unknown";
|
|
6697
|
+
default: {
|
|
6698
|
+
const exhaustive = kind;
|
|
6699
|
+
return exhaustive;
|
|
6700
|
+
}
|
|
6701
|
+
}
|
|
6702
|
+
}
|
|
6703
|
+
function primaryFontFamily(cssFamily) {
|
|
6704
|
+
return cssFamily.split(",")[0]?.trim().replace(/^["']|["']$/gu, "") || cssFamily;
|
|
6705
|
+
}
|
|
6706
|
+
function uniqueFontFamilies(families) {
|
|
6707
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6708
|
+
const result = [];
|
|
6709
|
+
for (const family of families) {
|
|
6710
|
+
const normalized = primaryFontFamily(family);
|
|
6711
|
+
const key = normalized.toLowerCase();
|
|
6712
|
+
if (seen.has(key)) continue;
|
|
6713
|
+
seen.add(key);
|
|
6714
|
+
result.push(normalized);
|
|
6715
|
+
}
|
|
6716
|
+
return result;
|
|
6717
|
+
}
|
|
6718
|
+
function normalizeFontFamilyOverride(value) {
|
|
6719
|
+
const trimmed = value.trim();
|
|
6720
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
6721
|
+
}
|
|
6157
6722
|
function SiteChromeLookRow({
|
|
6158
6723
|
label,
|
|
6159
6724
|
ariaLabel,
|
|
@@ -6166,7 +6731,7 @@ function SiteChromeLookRow({
|
|
|
6166
6731
|
description: defaultDescription,
|
|
6167
6732
|
available: true
|
|
6168
6733
|
},
|
|
6169
|
-
...catalog.map((look) => ({ ...look, available: true }))
|
|
6734
|
+
...(catalog ?? []).map((look) => ({ ...look, available: true }))
|
|
6170
6735
|
],
|
|
6171
6736
|
diagnostics,
|
|
6172
6737
|
scopeDescription,
|
|
@@ -6188,7 +6753,7 @@ function SiteChromeLookRow({
|
|
|
6188
6753
|
type: "button",
|
|
6189
6754
|
onClick: () => onCycle("prev"),
|
|
6190
6755
|
className: "grid h-8 w-8 place-items-center hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
6191
|
-
"aria-label": `Previous ${label.toLowerCase()}
|
|
6756
|
+
"aria-label": `Previous ${label.toLowerCase()}`,
|
|
6192
6757
|
disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
|
|
6193
6758
|
children: /* @__PURE__ */ jsx(ChevronLeft, { size: 14 })
|
|
6194
6759
|
}
|
|
@@ -6199,7 +6764,7 @@ function SiteChromeLookRow({
|
|
|
6199
6764
|
type: "button",
|
|
6200
6765
|
onClick: () => onCycle("next"),
|
|
6201
6766
|
className: "grid h-8 w-8 place-items-center border-l hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
6202
|
-
"aria-label": `Next ${label.toLowerCase()}
|
|
6767
|
+
"aria-label": `Next ${label.toLowerCase()}`,
|
|
6203
6768
|
disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
|
|
6204
6769
|
children: /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
|
|
6205
6770
|
}
|
|
@@ -6369,6 +6934,8 @@ function describeWarning(warning) {
|
|
|
6369
6934
|
return `Button style changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
6370
6935
|
case "rejected-palette":
|
|
6371
6936
|
return `Palette changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
6937
|
+
case "rejected-typography-preset":
|
|
6938
|
+
return `Typography changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
6372
6939
|
default: {
|
|
6373
6940
|
const exhaustive = warning;
|
|
6374
6941
|
return exhaustive;
|
|
@@ -6393,6 +6960,11 @@ function PreviewEditorSidebar({
|
|
|
6393
6960
|
themeSelectionButtonPersonalityId = null,
|
|
6394
6961
|
themeSelectionPaletteVariantId = null,
|
|
6395
6962
|
themeSelectionPaletteOverrides = null,
|
|
6963
|
+
themeSelectionHeaderLayoutId = null,
|
|
6964
|
+
themeSelectionHeaderStyleId = null,
|
|
6965
|
+
themeSelectionTypographyPresetId = null,
|
|
6966
|
+
themeSelectionTypographyBodyFontOverride = null,
|
|
6967
|
+
themeSelectionTypographyHeadingFontOverride = null,
|
|
6396
6968
|
themeSelectionHeaderLookId = null,
|
|
6397
6969
|
themeSelectionFooterLookId = null,
|
|
6398
6970
|
themeSelectionHeaderContext,
|
|
@@ -6552,6 +7124,11 @@ function PreviewEditorSidebar({
|
|
|
6552
7124
|
buttonPersonalityId: themeSelectionButtonPersonalityId,
|
|
6553
7125
|
paletteVariantId: themeSelectionPaletteVariantId,
|
|
6554
7126
|
paletteOverrides: themeSelectionPaletteOverrides,
|
|
7127
|
+
headerLayoutId: themeSelectionHeaderLayoutId,
|
|
7128
|
+
headerStyleId: themeSelectionHeaderStyleId,
|
|
7129
|
+
typographyPresetId: themeSelectionTypographyPresetId,
|
|
7130
|
+
typographyBodyFontOverride: themeSelectionTypographyBodyFontOverride,
|
|
7131
|
+
typographyHeadingFontOverride: themeSelectionTypographyHeadingFontOverride,
|
|
6555
7132
|
headerLookId: themeSelectionHeaderLookId,
|
|
6556
7133
|
footerLookId: themeSelectionFooterLookId
|
|
6557
7134
|
},
|