@riverbankcms/sdk 0.78.2 → 0.79.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 +80 -0
- package/dist/{PreviewEditorSidebar-4DXLYX2V.mjs → PreviewEditorSidebar-56NMJMIK.mjs} +724 -47
- package/dist/{PreviewEditorUI-CS5P4N3P.mjs → PreviewEditorUI-27KJVEET.mjs} +3 -3
- package/dist/SdkPreviewModeRuntime-H4BSP6E7.mjs +8 -0
- package/dist/_dts/ai/src/contracts/proposals.d.ts +36 -0
- package/dist/_dts/api/src/endpoints.d.ts +55 -0
- package/dist/_dts/api/src/index.d.ts +5 -3
- package/dist/_dts/api/src/media.d.ts +8 -1
- package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
- package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +8 -8
- package/dist/_dts/api/src/navigation/identity.d.ts +59 -0
- package/dist/_dts/api/src/navigation.d.ts +2 -0
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +4 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +1 -0
- package/dist/_dts/api/src/siteIcons.d.ts +128 -0
- package/dist/_dts/api/src/siteManagementEndpoints.d.ts +16 -0
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +7 -0
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
- package/dist/_dts/api/src/types.d.ts +1 -1
- package/dist/_dts/api/src/webhooks.d.ts +239 -0
- package/dist/_dts/blocks/src/index.d.ts +4 -0
- package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/cart.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/collection.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/faq.d.ts +294 -289
- package/dist/_dts/blocks/src/system/blocks/feature-card-icons.d.ts +57 -0
- package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +4 -0
- package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +22 -22
- package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/shop.d.ts +288 -288
- package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +7 -1
- package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +170 -0
- package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +5 -0
- package/dist/_dts/blocks/src/system/helpers/resolveBackground.d.ts +3 -1
- package/dist/_dts/blocks/src/system/icons/ids.d.ts +13 -0
- package/dist/_dts/blocks/src/system/icons/index.d.ts +6 -0
- package/dist/_dts/blocks/src/system/icons/presets.d.ts +4 -0
- package/dist/_dts/blocks/src/system/icons/registry.d.ts +18 -0
- package/dist/_dts/blocks/src/system/icons/semantic.d.ts +239 -0
- package/dist/_dts/blocks/src/system/icons/value.d.ts +94 -0
- package/dist/_dts/blocks/src/system/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +4 -1
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +23 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/feature-card-icon.d.ts +13 -0
- package/dist/_dts/content-model/src/contentManifest.d.ts +3 -1
- package/dist/_dts/core/src/branded.d.ts +6 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +191 -0
- package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +12 -1
- package/dist/_dts/editor-blocks/src/block-editor/BlockCardBody.d.ts +12 -1
- package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +12 -2
- package/dist/_dts/editor-blocks/src/block-editor/FeatureCardIconsPanel.d.ts +21 -0
- package/dist/_dts/editor-blocks/src/block-editor/GeneratedIconSetDialog.d.ts +40 -0
- package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +11 -1
- package/dist/_dts/editor-blocks/src/block-editor/featureCardIconActions.d.ts +82 -0
- package/dist/_dts/editor-blocks/src/widgets/icon-picker/IconPickerField.d.ts +1 -1
- package/dist/_dts/media-core/src/fileDomain.d.ts +8 -1
- package/dist/_dts/media-editor/src/MediaEditor.d.ts +3 -2
- package/dist/_dts/media-react/src/components/MediaLibrary.d.ts +2 -1
- package/dist/_dts/media-react/src/components/MediaPickerMini.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/blocks/previewCustomizeActions.d.ts +17 -0
- package/dist/_dts/preview-next/src/client/preview/PageDesignEditorStateContext.d.ts +4 -0
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/previewCustomizeHistory.d.ts +6 -0
- package/dist/_dts/sdk/src/cli/navigationIdentity.d.ts +11 -0
- package/dist/_dts/sdk/src/cli/site-commands/navigationCommands.d.ts +4 -0
- package/dist/_dts/sdk/src/cli/site-commands/oneOffCommands.d.ts +1 -0
- package/dist/_dts/sdk/src/cli/sync/diff.d.ts +9 -0
- package/dist/_dts/sdk/src/client/management/types.d.ts +2 -0
- package/dist/_dts/sdk/src/config/field-definitions.d.ts +3 -1
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +19 -2
- package/dist/_dts/sdk/src/next/index.d.ts +1 -1
- package/dist/_dts/sdk/src/next/revalidate.d.ts +26 -5
- package/dist/_dts/sdk/src/next/static-params.d.ts +28 -3
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -1
- package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/sdk/src/webhooks/index.d.ts +1 -1
- package/dist/_dts/sdk/src/webhooks/verify.d.ts +6 -102
- package/dist/_dts/site-commands/src/commands.d.ts +3 -0
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +3 -3
- package/dist/_dts/theme-core/src/schema.d.ts +5 -5
- package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +25 -2
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +5 -5
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +4 -4
- package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -0
- package/dist/_dts/ui/src/combobox.d.ts +1 -0
- package/dist/{chunk-RGTOD4AJ.mjs → chunk-4HCW7FHJ.mjs} +491 -56
- package/dist/{chunk-OKMBEAXY.mjs → chunk-A3HHFKVT.mjs} +1 -1
- package/dist/{chunk-6HYXHRAI.mjs → chunk-GP555I66.mjs} +177 -7
- package/dist/{chunk-CR5HKAGU.mjs → chunk-K2IIF34C.mjs} +55 -0
- package/dist/{chunk-4QEGTLK6.mjs → chunk-LCY32PXF.mjs} +1 -1
- package/dist/{chunk-MCRQMPET.mjs → chunk-V47ZU33I.mjs} +1745 -157
- package/dist/cli/index.mjs +1169 -171
- package/dist/cli/init-docs/content/workflow-editor-workflows.md +2 -0
- package/dist/cli/init-docs/content/workflow-isr-revalidation.md +138 -0
- package/dist/client/{accordion-PLYNJIIM.mjs → accordion-QLA7KBYO.mjs} +1 -1
- package/dist/client/{bookingForm-BXAP6AO7.mjs → bookingForm-PYZIPA5G.mjs} +3 -3
- package/dist/client/bookings.mjs +110 -2
- package/dist/client/{carousel-TRBXDHGF.mjs → carousel-5EIULWBI.mjs} +2 -2
- package/dist/client/{cart-Z7H3HJRS.mjs → cart-DOP3FNI4.mjs} +5 -5
- package/dist/client/{checkout-WAFCUBIX.mjs → checkout-BVMF6FBV.mjs} +5 -5
- package/dist/client/{chunk-JRDUHZCT.mjs → chunk-44K2U3QI.mjs} +4 -4
- package/dist/client/{chunk-UVQEJJTN.mjs → chunk-CCNTDRCF.mjs} +1 -1
- package/dist/client/{chunk-ZI3LLBPZ.mjs → chunk-GG4M2NP6.mjs} +1 -1
- package/dist/client/{chunk-JGXPTEI2.mjs → chunk-R5ESWNKX.mjs} +6 -3
- package/dist/client/{chunk-CWGTG37I.mjs → chunk-TYONZMST.mjs} +1 -1
- package/dist/client/{chunk-75OUS5MT.mjs → chunk-UDS3NTWA.mjs} +1 -1
- package/dist/client/{chunk-DNRGY432.mjs → chunk-V6M5FCR5.mjs} +1 -1
- package/dist/client/{chunk-FUXW6VW2.mjs → chunk-YLDYVRZL.mjs} +4 -4
- package/dist/client/client.mjs +21329 -19729
- package/dist/client/{courseRegistration-AHFQHWIJ.mjs → courseRegistration-E6EAA6NL.mjs} +3 -3
- package/dist/client/{eventCalendar-LDXTV5R7.mjs → eventCalendar-HBG3HAK6.mjs} +5 -5
- package/dist/client/{eventCombined-A4JGTNJO.mjs → eventCombined-6K5ZZWAK.mjs} +5 -5
- package/dist/client/{eventDetails-4YXTZ7EG.mjs → eventDetails-Q75ICXLT.mjs} +5 -5
- package/dist/client/{eventListing-P72TPFFM.mjs → eventListing-27P5F7DZ.mjs} +5 -5
- package/dist/client/{eventRegistration-LSYJHGMT.mjs → eventRegistration-IQ7AMASR.mjs} +5 -5
- package/dist/client/{form-AOPYOKOW.mjs → form-JRTD65FN.mjs} +1 -1
- package/dist/client/{headerSection-5TFYDFVQ.mjs → headerSection-7FPSSZHS.mjs} +2 -2
- package/dist/client/hooks.mjs +350 -35
- package/dist/client/{locationMap-QSZ3ZVAZ.mjs → locationMap-7NGFNYBH.mjs} +1 -1
- package/dist/client/{newsletterForm-KTRHZY52.mjs → newsletterForm-F3BADCI2.mjs} +1 -1
- package/dist/client/{productDetail-N4E775RG.mjs → productDetail-V3HP7ITJ.mjs} +5 -5
- package/dist/client/{productList-UGUQ2S45.mjs → productList-L3EGJUF2.mjs} +5 -5
- package/dist/client/rendering/client.mjs +2713 -1382
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +2014 -414
- package/dist/client/{shop-VHSZEEQ2.mjs → shop-DQUB5E2C.mjs} +5 -5
- package/dist/preview-next/before-render.mjs +55 -0
- package/dist/preview-next/client/runtime.mjs +5 -5
- package/dist/preview-next/middleware.mjs +55 -0
- package/dist/{sdk-runtime-WHPJEF5G.mjs → sdk-runtime-AF6KXJU4.mjs} +6 -6
- package/dist/server/components.mjs +2169 -781
- package/dist/server/config-validation.mjs +350 -35
- package/dist/server/config.mjs +350 -35
- package/dist/server/data.mjs +350 -35
- package/dist/server/index.mjs +64 -1
- package/dist/server/next/revalidate.mjs +229 -34
- package/dist/server/next.mjs +2307 -818
- package/dist/server/page-converter.mjs +275 -34
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +2174 -786
- package/dist/server/rendering.mjs +2187 -799
- package/dist/server/routing.mjs +767 -50
- package/dist/server/server.mjs +351 -36
- package/dist/server/theme-bridge.mjs +164 -2
- package/dist/server/theme.mjs +2 -2
- package/dist/server/webhooks.mjs +129 -25
- package/dist/styles/index.css +55 -0
- package/package.json +2 -1
- package/dist/SdkPreviewModeRuntime-IJDHTW4W.mjs +0 -8
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
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-
|
|
3
|
-
import { KeyboardCode, getBlockDefinition, CSS, useSdkConfig, listBlockDescriptors, useSensor, PointerSensor, useSensors, deleteBlock, createEditorRemoveBlockCommand, unsafeAsEditorBlockId, 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,
|
|
4
|
-
import { usePreviewAuth, getDashboardUrl } from './chunk-
|
|
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-LCY32PXF.mjs';
|
|
3
|
+
import { KeyboardCode, getBlockDefinition, CSS, useSdkConfig, unwrapResponse, parseSiteIconStyleGuideVersionId, parseBlockIconValue, listBlockDescriptors, useSensor, PointerSensor, useSensors, deleteBlock, createEditorRemoveBlockCommand, unsafeAsEditorBlockId, 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, Sparkles, RotateCcw, ImagePlus, Copy, Trash2, DialogFooter, DialogClose, CardContent, createEditorInsertBlockCommand, LoaderCircle, ChevronDown, getFeatureCardIconCompletion, toFeatureCardIconSuggestionInputs, getBlockIconSemanticFallbackId, suggestSemanticIconForFeatureCard, getGeneratedBlockIconStyleState, assertNever, suggestFeatureCardSemanticIcons, applyFeatureCardIconSuggestions, createFeatureCardIconKey, Textarea, Callout, CalloutDescription, normalEditorCuratedPromotedFieldPaths, resolveVisiblePromotedFieldPathsForEditorBlock, createStoreBackend, validateBlockManifestIssues, CalloutTitle, unfinishedBlockCopy, recoveryConflictCopy, ManifestForm, unsafeAsEditorBlockValues, Box, createManifestFormAdapter, getModalConfig, isNonEmptyValue, ScrollableDialogContent, FormRenderer, Tabs, TabsList, TabsTrigger, TabsContent, mergeManifestWithSdkOptions, augmentManifestWithStyleGroups, lucide_react_exports, isThemeV2NormalEditorRawStylePath, getFieldIntent, isHeaderField, isThemeV2NormalEditorRawStyleFieldName, useEntryController, useEditorUiStoreInstance, useUISelector, resolvePreviewSidebarTab, BackgroundGradientField, BackgroundColorField, X, omitRouteTitleFieldFromManifest, getRouteMetadataManifestForType, createManifestValidation, previewAssistantEnabled, useField, FieldFrame, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, resolveIconPickerPreset, isIconPickerPreset, getIconPickerOptionsForPreset, isKnownIconName, Combobox, getIconComponent, 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, resolveVideoSelectionIntentForMediaField, emitMediaCropDebug, Pencil, foldSubroute, SUBROUTE_KINDS, Smartphone, Tablet, Monitor, Maximize2, DropdownMenuLabel, expectParsedBrandedId, parseSiteId, buildThemeRuntime, PaletteProvider, MediaEditorProvider, curatedSiteStyles, ChevronLeft, requireEntriesForCuratedChoices, buttonPersonalities, typographyPresets, paletteVariants, resolveImageUrlWithContext, Root2, List, Trigger, Content, Input, Check, Label, isInternalResolvedLinkValue, evaluateTypographyFontSlot, Separator, classifyKnownMimeType, toRoutableLinkPayload, useMediaEditor, MediaPickerMini, MediaPickerDialog, Surface, ColorPicker, getDirectImageUrlForMediaAsset, isSvgMimeType } from './chunk-V47ZU33I.mjs';
|
|
4
|
+
import { usePreviewAuth, getDashboardUrl } from './chunk-K2IIF34C.mjs';
|
|
5
5
|
import './chunk-R7POPVJR.mjs';
|
|
6
|
-
import React, { createContext, memo, useMemo, useState, useRef, useEffect, forwardRef, useCallback, useImperativeHandle, useContext, useSyncExternalStore, useLayoutEffect, useTransition, useId } from 'react';
|
|
6
|
+
import React, { createContext, memo, useMemo, useState, useRef, useEffect, forwardRef, useCallback, useImperativeHandle, useContext, useSyncExternalStore, useLayoutEffect, useReducer, useTransition, useId } from 'react';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import { useRouter } from 'next/navigation';
|
|
9
9
|
|
|
@@ -47,7 +47,7 @@ function parseReferenceKind(referenceKind) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// ../content-model/src/contentManifest.ts
|
|
50
|
-
function
|
|
50
|
+
function assertNever2(value) {
|
|
51
51
|
throw new Error(`Unhandled content field mapping decision: ${JSON.stringify(value)}`);
|
|
52
52
|
}
|
|
53
53
|
function resolveContentReferenceKind(field) {
|
|
@@ -178,7 +178,7 @@ function toFieldDefinition(field, context = {}) {
|
|
|
178
178
|
valueFrom: mapping.valueFrom
|
|
179
179
|
};
|
|
180
180
|
default:
|
|
181
|
-
return
|
|
181
|
+
return assertNever2(mapping);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
case "link":
|
|
@@ -2301,6 +2301,451 @@ function blockSaveabilityEqual(left, right) {
|
|
|
2301
2301
|
return nextIssue?.fieldPath === issue.fieldPath && nextIssue.message === issue.message;
|
|
2302
2302
|
});
|
|
2303
2303
|
}
|
|
2304
|
+
|
|
2305
|
+
// ../editor-blocks/src/block-editor/featureCardIconActions.ts
|
|
2306
|
+
function getFeatureCards(content) {
|
|
2307
|
+
const cards = content?.cards;
|
|
2308
|
+
return Array.isArray(cards) ? cards : [];
|
|
2309
|
+
}
|
|
2310
|
+
function getFeatureCardIconStatus(content) {
|
|
2311
|
+
return getFeatureCardIconCompletion(getFeatureCards(content));
|
|
2312
|
+
}
|
|
2313
|
+
function getFeatureCardIconDialogCards(content) {
|
|
2314
|
+
return toFeatureCardIconSuggestionInputs(getFeatureCards(content)).map((card, index) => {
|
|
2315
|
+
const semanticFallback = getBlockIconSemanticFallbackId(card.icon) ?? suggestSemanticIconForFeatureCard(card);
|
|
2316
|
+
return {
|
|
2317
|
+
cardKey: card.key,
|
|
2318
|
+
title: card.title.trim().length > 0 ? card.title.trim() : `Card ${index + 1}`,
|
|
2319
|
+
bodyText: card.bodyText.slice(0, 160),
|
|
2320
|
+
semanticIconId: semanticFallback
|
|
2321
|
+
};
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
function getFeatureCardGeneratedIconStyleSummary(content, currentStyleGuideVersionId) {
|
|
2325
|
+
if (!currentStyleGuideVersionId) return { kind: "unavailable" };
|
|
2326
|
+
let generatedCount = 0;
|
|
2327
|
+
let staleCount = 0;
|
|
2328
|
+
let invalidGeneratedCount = 0;
|
|
2329
|
+
for (const card of getFeatureCards(content)) {
|
|
2330
|
+
const state = getGeneratedBlockIconStyleState(card.icon, currentStyleGuideVersionId);
|
|
2331
|
+
switch (state.kind) {
|
|
2332
|
+
case "not_generated":
|
|
2333
|
+
break;
|
|
2334
|
+
case "current":
|
|
2335
|
+
generatedCount += 1;
|
|
2336
|
+
break;
|
|
2337
|
+
case "stale":
|
|
2338
|
+
generatedCount += 1;
|
|
2339
|
+
staleCount += 1;
|
|
2340
|
+
break;
|
|
2341
|
+
case "invalid_generated":
|
|
2342
|
+
invalidGeneratedCount += 1;
|
|
2343
|
+
break;
|
|
2344
|
+
default:
|
|
2345
|
+
assertNever(state);
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
return {
|
|
2349
|
+
kind: "available",
|
|
2350
|
+
generatedCount,
|
|
2351
|
+
staleCount,
|
|
2352
|
+
invalidGeneratedCount
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
function applyCuratedFeatureCardIconSuggestions({
|
|
2356
|
+
blockId,
|
|
2357
|
+
content,
|
|
2358
|
+
drafts
|
|
2359
|
+
}) {
|
|
2360
|
+
const cards = getFeatureCards(content);
|
|
2361
|
+
if (cards.length === 0) return { kind: "no_cards" };
|
|
2362
|
+
const suggestions = suggestFeatureCardSemanticIcons(cards);
|
|
2363
|
+
if (suggestions.length === 0) return { kind: "complete" };
|
|
2364
|
+
const plan = applyFeatureCardIconSuggestions(cards, suggestions);
|
|
2365
|
+
switch (plan.kind) {
|
|
2366
|
+
case "applied":
|
|
2367
|
+
break;
|
|
2368
|
+
case "duplicate_card_key":
|
|
2369
|
+
case "duplicate_suggestion_card_key":
|
|
2370
|
+
case "missing_suggestion_card_key":
|
|
2371
|
+
case "unknown_card_key":
|
|
2372
|
+
return { kind: "plan_failed", reason: plan.kind, cardKey: plan.cardKey };
|
|
2373
|
+
case "invalid_semantic_icon":
|
|
2374
|
+
return { kind: "plan_failed", reason: plan.kind, iconId: plan.iconId };
|
|
2375
|
+
default:
|
|
2376
|
+
assertNever(plan);
|
|
2377
|
+
}
|
|
2378
|
+
for (const suggestion of plan.appliedSuggestions) {
|
|
2379
|
+
const cardIndex = cards.findIndex((card, index) => createFeatureCardIconKey(card, index) === suggestion.cardKey);
|
|
2380
|
+
if (cardIndex >= 0) {
|
|
2381
|
+
drafts.setAtPath(blockId, `cards.${cardIndex}.icon`, { kind: "semantic", iconId: suggestion.iconId });
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
return { kind: "applied", appliedCount: plan.appliedSuggestions.length };
|
|
2385
|
+
}
|
|
2386
|
+
function planGeneratedFeatureCardIconSetApply(cards, assets) {
|
|
2387
|
+
const cardKeys = cards.map(createFeatureCardIconKey);
|
|
2388
|
+
const cardKeySet = new Set(cardKeys);
|
|
2389
|
+
const iconByCardKey = /* @__PURE__ */ new Map();
|
|
2390
|
+
for (const asset of assets) {
|
|
2391
|
+
if (iconByCardKey.has(asset.cardKey)) {
|
|
2392
|
+
return { kind: "duplicate_asset_card_key", cardKey: asset.cardKey };
|
|
2393
|
+
}
|
|
2394
|
+
if (!cardKeySet.has(asset.cardKey)) {
|
|
2395
|
+
return { kind: "unknown_card_key", cardKey: asset.cardKey };
|
|
2396
|
+
}
|
|
2397
|
+
const iconValue = parseBlockIconValue(asset.iconValue);
|
|
2398
|
+
if (iconValue.kind !== "generated") {
|
|
2399
|
+
return { kind: "invalid_generated_icon", cardKey: asset.cardKey };
|
|
2400
|
+
}
|
|
2401
|
+
iconByCardKey.set(asset.cardKey, iconValue);
|
|
2402
|
+
}
|
|
2403
|
+
const appliedIcons = [];
|
|
2404
|
+
for (const [cardIndex, cardKey] of cardKeys.entries()) {
|
|
2405
|
+
const iconValue = iconByCardKey.get(cardKey);
|
|
2406
|
+
if (!iconValue) {
|
|
2407
|
+
return { kind: "missing_asset_card_key", cardKey };
|
|
2408
|
+
}
|
|
2409
|
+
appliedIcons.push({ cardIndex, cardKey, iconValue });
|
|
2410
|
+
}
|
|
2411
|
+
return {
|
|
2412
|
+
kind: "applied",
|
|
2413
|
+
appliedIcons
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
function applyGeneratedFeatureCardIconSet({
|
|
2417
|
+
blockId,
|
|
2418
|
+
content,
|
|
2419
|
+
drafts,
|
|
2420
|
+
assets
|
|
2421
|
+
}) {
|
|
2422
|
+
const cards = getFeatureCards(content);
|
|
2423
|
+
if (cards.length === 0) return { kind: "no_cards" };
|
|
2424
|
+
const plan = planGeneratedFeatureCardIconSetApply(cards, assets);
|
|
2425
|
+
switch (plan.kind) {
|
|
2426
|
+
case "applied":
|
|
2427
|
+
break;
|
|
2428
|
+
case "duplicate_asset_card_key":
|
|
2429
|
+
case "missing_asset_card_key":
|
|
2430
|
+
case "unknown_card_key":
|
|
2431
|
+
case "invalid_generated_icon":
|
|
2432
|
+
return { kind: "plan_failed", reason: plan.kind, cardKey: plan.cardKey };
|
|
2433
|
+
default:
|
|
2434
|
+
assertNever(plan);
|
|
2435
|
+
}
|
|
2436
|
+
for (const appliedIcon of plan.appliedIcons) {
|
|
2437
|
+
drafts.setAtPath(blockId, `cards.${appliedIcon.cardIndex}.icon`, appliedIcon.iconValue);
|
|
2438
|
+
}
|
|
2439
|
+
return { kind: "applied", appliedCount: plan.appliedIcons.length };
|
|
2440
|
+
}
|
|
2441
|
+
function reducer(state, action) {
|
|
2442
|
+
switch (action.type) {
|
|
2443
|
+
case "reset":
|
|
2444
|
+
return { kind: "idle" };
|
|
2445
|
+
case "generating":
|
|
2446
|
+
return { kind: "generating" };
|
|
2447
|
+
case "applying":
|
|
2448
|
+
return { kind: "applying", preview: action.preview };
|
|
2449
|
+
case "preview_ready":
|
|
2450
|
+
return { kind: "preview_ready", preview: action.preview };
|
|
2451
|
+
case "failed":
|
|
2452
|
+
return { kind: "failed", message: action.message };
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
function getGenerationErrorMessage(error) {
|
|
2456
|
+
return error instanceof Error && error.message.length > 0 ? error.message : "Failed to generate icon set";
|
|
2457
|
+
}
|
|
2458
|
+
function validateGeneratedIconSetPreview(preview, cards) {
|
|
2459
|
+
const cardKeys = new Set(cards.map((card) => card.cardKey));
|
|
2460
|
+
if (cardKeys.size !== cards.length) {
|
|
2461
|
+
return { kind: "invalid", message: "Generated icon set could not match every card" };
|
|
2462
|
+
}
|
|
2463
|
+
const assetKeys = new Set(preview.assets.map((asset) => asset.cardKey));
|
|
2464
|
+
if (assetKeys.size !== preview.assets.length || assetKeys.size !== cardKeys.size) {
|
|
2465
|
+
return { kind: "invalid", message: "Generated icon set was incomplete" };
|
|
2466
|
+
}
|
|
2467
|
+
for (const asset of preview.assets) {
|
|
2468
|
+
if (!cardKeys.has(asset.cardKey)) {
|
|
2469
|
+
return { kind: "invalid", message: "Generated icon set was incomplete" };
|
|
2470
|
+
}
|
|
2471
|
+
if (parseBlockIconValue(asset.iconValue).kind !== "generated") {
|
|
2472
|
+
return { kind: "invalid", message: "Generated icon set included an invalid icon reference" };
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
return { kind: "valid", preview };
|
|
2476
|
+
}
|
|
2477
|
+
function GeneratedIconSetDialog({
|
|
2478
|
+
open,
|
|
2479
|
+
onOpenChange,
|
|
2480
|
+
cards,
|
|
2481
|
+
styleGuideSummary,
|
|
2482
|
+
styleGuideEditHref,
|
|
2483
|
+
onGenerate,
|
|
2484
|
+
onApply
|
|
2485
|
+
}) {
|
|
2486
|
+
const [state, dispatch] = useReducer(reducer, { kind: "idle" });
|
|
2487
|
+
const [styleNote, setStyleNote] = useState("");
|
|
2488
|
+
const canGenerate = Boolean(onGenerate) && cards.length > 0 && state.kind !== "generating";
|
|
2489
|
+
const canApply = Boolean(onApply) && state.kind === "preview_ready";
|
|
2490
|
+
async function generate() {
|
|
2491
|
+
if (!onGenerate || cards.length === 0) return;
|
|
2492
|
+
dispatch({ type: "generating" });
|
|
2493
|
+
try {
|
|
2494
|
+
const result = await onGenerate({
|
|
2495
|
+
cards,
|
|
2496
|
+
userStyleNote: styleNote.trim().length > 0 ? styleNote.trim() : null
|
|
2497
|
+
});
|
|
2498
|
+
if (result.kind === "preview_ready") {
|
|
2499
|
+
const validation = validateGeneratedIconSetPreview(result.preview, cards);
|
|
2500
|
+
if (validation.kind === "invalid") {
|
|
2501
|
+
dispatch({ type: "failed", message: validation.message });
|
|
2502
|
+
return;
|
|
2503
|
+
}
|
|
2504
|
+
dispatch({ type: "preview_ready", preview: validation.preview });
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
dispatch({ type: "failed", message: result.message });
|
|
2508
|
+
} catch (error) {
|
|
2509
|
+
dispatch({ type: "failed", message: getGenerationErrorMessage(error) });
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
function close(nextOpen) {
|
|
2513
|
+
onOpenChange(nextOpen);
|
|
2514
|
+
if (!nextOpen) dispatch({ type: "reset" });
|
|
2515
|
+
}
|
|
2516
|
+
async function apply(preview) {
|
|
2517
|
+
if (!onApply) return;
|
|
2518
|
+
dispatch({ type: "applying", preview });
|
|
2519
|
+
try {
|
|
2520
|
+
const result = await onApply(preview);
|
|
2521
|
+
if (result?.kind === "failed") {
|
|
2522
|
+
dispatch({ type: "failed", message: result.message });
|
|
2523
|
+
return;
|
|
2524
|
+
}
|
|
2525
|
+
close(false);
|
|
2526
|
+
} catch (error) {
|
|
2527
|
+
dispatch({ type: "failed", message: getGenerationErrorMessage(error) });
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: close, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-2xl", children: [
|
|
2531
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2532
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Generate icon set" }),
|
|
2533
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: state.kind === "preview_ready" ? state.preview.styleGuideSummary : `${cards.length} cards` })
|
|
2534
|
+
] }),
|
|
2535
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2536
|
+
styleGuideSummary || styleGuideEditHref ? /* @__PURE__ */ jsxs("div", { className: "rounded-md border bg-muted/20 px-3 py-2 text-sm", children: [
|
|
2537
|
+
styleGuideSummary ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: styleGuideSummary }) : null,
|
|
2538
|
+
styleGuideEditHref ? /* @__PURE__ */ jsx(
|
|
2539
|
+
"a",
|
|
2540
|
+
{
|
|
2541
|
+
href: styleGuideEditHref,
|
|
2542
|
+
className: "mt-1 inline-flex text-sm font-medium text-primary underline-offset-4 hover:underline",
|
|
2543
|
+
children: "Edit icon style"
|
|
2544
|
+
}
|
|
2545
|
+
) : null
|
|
2546
|
+
] }) : null,
|
|
2547
|
+
/* @__PURE__ */ jsx("label", { className: "block text-sm font-medium", htmlFor: "generated-icon-style-note", children: "Icon style" }),
|
|
2548
|
+
/* @__PURE__ */ jsx(
|
|
2549
|
+
Textarea,
|
|
2550
|
+
{
|
|
2551
|
+
id: "generated-icon-style-note",
|
|
2552
|
+
value: styleNote,
|
|
2553
|
+
maxLength: 240,
|
|
2554
|
+
disabled: state.kind === "generating",
|
|
2555
|
+
onChange: (event) => setStyleNote(event.currentTarget.value),
|
|
2556
|
+
placeholder: "Simple, soft-edged, lightly textured"
|
|
2557
|
+
}
|
|
2558
|
+
),
|
|
2559
|
+
state.kind === "failed" ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: state.message }) : null,
|
|
2560
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: cards.map((card) => {
|
|
2561
|
+
const previewAsset = state.kind === "preview_ready" || state.kind === "applying" ? state.preview.assets.find((asset) => asset.cardKey === card.cardKey) : null;
|
|
2562
|
+
return /* @__PURE__ */ jsxs(
|
|
2563
|
+
"div",
|
|
2564
|
+
{
|
|
2565
|
+
className: "grid min-h-24 grid-cols-[3rem_1fr] gap-3 rounded-md border bg-muted/20 p-3",
|
|
2566
|
+
children: [
|
|
2567
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-12 items-center justify-center rounded-md border bg-background", children: previewAsset?.src ? /* @__PURE__ */ jsx(
|
|
2568
|
+
"img",
|
|
2569
|
+
{
|
|
2570
|
+
src: previewAsset.src,
|
|
2571
|
+
alt: "",
|
|
2572
|
+
className: "size-10 object-contain"
|
|
2573
|
+
}
|
|
2574
|
+
) : /* @__PURE__ */ jsx(ImagePlus, { className: "size-5 text-muted-foreground", "aria-hidden": "true" }) }),
|
|
2575
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
2576
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: card.title }),
|
|
2577
|
+
card.bodyText ? /* @__PURE__ */ jsx("p", { className: "overflow-hidden text-ellipsis text-xs text-muted-foreground", children: card.bodyText }) : null
|
|
2578
|
+
] })
|
|
2579
|
+
]
|
|
2580
|
+
},
|
|
2581
|
+
card.cardKey
|
|
2582
|
+
);
|
|
2583
|
+
}) })
|
|
2584
|
+
] }),
|
|
2585
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
2586
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => close(false), children: "Cancel" }),
|
|
2587
|
+
/* @__PURE__ */ jsxs(
|
|
2588
|
+
Button,
|
|
2589
|
+
{
|
|
2590
|
+
type: "button",
|
|
2591
|
+
variant: "outline",
|
|
2592
|
+
disabled: !canGenerate,
|
|
2593
|
+
onClick: () => {
|
|
2594
|
+
void generate();
|
|
2595
|
+
},
|
|
2596
|
+
children: [
|
|
2597
|
+
state.kind === "preview_ready" ? /* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Sparkles, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
2598
|
+
state.kind === "preview_ready" ? "Regenerate" : state.kind === "generating" ? "Generating" : "Generate"
|
|
2599
|
+
]
|
|
2600
|
+
}
|
|
2601
|
+
),
|
|
2602
|
+
/* @__PURE__ */ jsx(
|
|
2603
|
+
Button,
|
|
2604
|
+
{
|
|
2605
|
+
type: "button",
|
|
2606
|
+
disabled: !canApply,
|
|
2607
|
+
onClick: () => {
|
|
2608
|
+
if (state.kind !== "preview_ready" || !onApply) return;
|
|
2609
|
+
void apply(state.preview);
|
|
2610
|
+
},
|
|
2611
|
+
children: state.kind === "applying" ? "Applying" : "Apply set"
|
|
2612
|
+
}
|
|
2613
|
+
)
|
|
2614
|
+
] })
|
|
2615
|
+
] }) });
|
|
2616
|
+
}
|
|
2617
|
+
function supportsFeatureCardIconActions(blockKind) {
|
|
2618
|
+
return blockKind === "block.feature-cards";
|
|
2619
|
+
}
|
|
2620
|
+
function FeatureCardIconsPanel({
|
|
2621
|
+
block,
|
|
2622
|
+
uiStore,
|
|
2623
|
+
currentStyleGuideVersionId,
|
|
2624
|
+
iconStyleGuideSummary,
|
|
2625
|
+
iconStyleGuideEditHref,
|
|
2626
|
+
onGenerateIconSet,
|
|
2627
|
+
onApplyGeneratedIconSet
|
|
2628
|
+
}) {
|
|
2629
|
+
const [generateDialogOpen, setGenerateDialogOpen] = useState(false);
|
|
2630
|
+
const blockId = typeof block.id === "string" ? unsafeAsEditorBlockId(block.id) : null;
|
|
2631
|
+
const currentValues = useStoreSelector(
|
|
2632
|
+
uiStore,
|
|
2633
|
+
(state) => blockId ? state.drafts.getCurrentValues(blockId) : null
|
|
2634
|
+
);
|
|
2635
|
+
const content = currentValues ?? block.draftContent ?? block.content ?? null;
|
|
2636
|
+
const status = useMemo(() => getFeatureCardIconStatus(content), [content]);
|
|
2637
|
+
const dialogCards = useMemo(() => getFeatureCardIconDialogCards(content), [content]);
|
|
2638
|
+
const styleSummary = useMemo(
|
|
2639
|
+
() => getFeatureCardGeneratedIconStyleSummary(content, currentStyleGuideVersionId),
|
|
2640
|
+
[content, currentStyleGuideVersionId]
|
|
2641
|
+
);
|
|
2642
|
+
const isComplete = status.totalCards > 0 && status.cardsWithIcons >= status.totalCards;
|
|
2643
|
+
const hasStaleGeneratedIcons = styleSummary.kind === "available" && styleSummary.staleCount > 0;
|
|
2644
|
+
async function applyGeneratedIconSetPreview(preview) {
|
|
2645
|
+
if (!blockId) return { kind: "failed", message: "Could not apply generated icon set" };
|
|
2646
|
+
const appliedPreview = await onApplyGeneratedIconSet?.(preview);
|
|
2647
|
+
const previewToApply = appliedPreview ?? preview;
|
|
2648
|
+
const result = applyGeneratedFeatureCardIconSet({
|
|
2649
|
+
blockId,
|
|
2650
|
+
content,
|
|
2651
|
+
drafts: uiStore.getState().drafts,
|
|
2652
|
+
assets: previewToApply.assets
|
|
2653
|
+
});
|
|
2654
|
+
if (result.kind !== "applied") {
|
|
2655
|
+
return { kind: "failed", message: "Could not apply generated icon set" };
|
|
2656
|
+
}
|
|
2657
|
+
return { kind: "applied" };
|
|
2658
|
+
}
|
|
2659
|
+
if (!supportsFeatureCardIconActions(block.kind) || !blockId) {
|
|
2660
|
+
return null;
|
|
2661
|
+
}
|
|
2662
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2663
|
+
/* @__PURE__ */ jsxs(
|
|
2664
|
+
"section",
|
|
2665
|
+
{
|
|
2666
|
+
className: "rounded-md border bg-muted/20 px-3 py-3",
|
|
2667
|
+
"aria-label": "Icons",
|
|
2668
|
+
"data-testid": "feature-card-icons-panel",
|
|
2669
|
+
children: [
|
|
2670
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2671
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
2672
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Icons" }),
|
|
2673
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
2674
|
+
status.cardsWithIcons,
|
|
2675
|
+
" of ",
|
|
2676
|
+
status.totalCards,
|
|
2677
|
+
" cards"
|
|
2678
|
+
] })
|
|
2679
|
+
] }),
|
|
2680
|
+
/* @__PURE__ */ jsxs(
|
|
2681
|
+
Button,
|
|
2682
|
+
{
|
|
2683
|
+
type: "button",
|
|
2684
|
+
variant: "outline",
|
|
2685
|
+
size: "sm",
|
|
2686
|
+
disabled: status.totalCards === 0 || isComplete,
|
|
2687
|
+
onClick: () => {
|
|
2688
|
+
applyCuratedFeatureCardIconSuggestions({
|
|
2689
|
+
blockId,
|
|
2690
|
+
content,
|
|
2691
|
+
drafts: uiStore.getState().drafts
|
|
2692
|
+
});
|
|
2693
|
+
},
|
|
2694
|
+
children: [
|
|
2695
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
2696
|
+
"Suggest icons"
|
|
2697
|
+
]
|
|
2698
|
+
}
|
|
2699
|
+
),
|
|
2700
|
+
/* @__PURE__ */ jsxs(
|
|
2701
|
+
Button,
|
|
2702
|
+
{
|
|
2703
|
+
type: "button",
|
|
2704
|
+
variant: "outline",
|
|
2705
|
+
size: "sm",
|
|
2706
|
+
disabled: status.totalCards === 0,
|
|
2707
|
+
onClick: () => setGenerateDialogOpen(true),
|
|
2708
|
+
children: [
|
|
2709
|
+
/* @__PURE__ */ jsx(ImagePlus, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
2710
|
+
"Generate icon set"
|
|
2711
|
+
]
|
|
2712
|
+
}
|
|
2713
|
+
)
|
|
2714
|
+
] }),
|
|
2715
|
+
hasStaleGeneratedIcons ? /* @__PURE__ */ jsxs(Callout, { tone: "warning", className: "mt-3 flex flex-wrap items-center gap-2", children: [
|
|
2716
|
+
/* @__PURE__ */ jsx(CalloutDescription, { className: "mt-0 min-w-0 flex-1 text-xs", children: "Generated icons are out of date with the current icon style." }),
|
|
2717
|
+
/* @__PURE__ */ jsxs(
|
|
2718
|
+
Button,
|
|
2719
|
+
{
|
|
2720
|
+
type: "button",
|
|
2721
|
+
variant: "outline",
|
|
2722
|
+
size: "sm",
|
|
2723
|
+
disabled: status.totalCards === 0 || !onGenerateIconSet,
|
|
2724
|
+
onClick: () => setGenerateDialogOpen(true),
|
|
2725
|
+
children: [
|
|
2726
|
+
/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
2727
|
+
"Regenerate set"
|
|
2728
|
+
]
|
|
2729
|
+
}
|
|
2730
|
+
)
|
|
2731
|
+
] }) : null
|
|
2732
|
+
]
|
|
2733
|
+
}
|
|
2734
|
+
),
|
|
2735
|
+
/* @__PURE__ */ jsx(
|
|
2736
|
+
GeneratedIconSetDialog,
|
|
2737
|
+
{
|
|
2738
|
+
open: generateDialogOpen,
|
|
2739
|
+
onOpenChange: setGenerateDialogOpen,
|
|
2740
|
+
cards: dialogCards,
|
|
2741
|
+
styleGuideSummary: iconStyleGuideSummary,
|
|
2742
|
+
styleGuideEditHref: iconStyleGuideEditHref,
|
|
2743
|
+
onGenerate: onGenerateIconSet,
|
|
2744
|
+
onApply: applyGeneratedIconSetPreview
|
|
2745
|
+
}
|
|
2746
|
+
)
|
|
2747
|
+
] });
|
|
2748
|
+
}
|
|
2304
2749
|
function BlockCardBody({
|
|
2305
2750
|
siteId,
|
|
2306
2751
|
block,
|
|
@@ -2313,29 +2758,48 @@ function BlockCardBody({
|
|
|
2313
2758
|
theme,
|
|
2314
2759
|
widgetOverrides,
|
|
2315
2760
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
2316
|
-
pageDesignBlock = null
|
|
2761
|
+
pageDesignBlock = null,
|
|
2762
|
+
currentStyleGuideVersionId,
|
|
2763
|
+
iconStyleGuideSummary,
|
|
2764
|
+
iconStyleGuideEditHref,
|
|
2765
|
+
onGenerateIconSet,
|
|
2766
|
+
onApplyGeneratedIconSet
|
|
2317
2767
|
}) {
|
|
2318
|
-
return /* @__PURE__ */
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2768
|
+
return /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4 pb-6", children: [
|
|
2769
|
+
/* @__PURE__ */ jsx(
|
|
2770
|
+
FeatureCardIconsPanel,
|
|
2771
|
+
{
|
|
2772
|
+
block,
|
|
2773
|
+
uiStore,
|
|
2774
|
+
currentStyleGuideVersionId,
|
|
2775
|
+
iconStyleGuideSummary,
|
|
2776
|
+
iconStyleGuideEditHref,
|
|
2777
|
+
onGenerateIconSet,
|
|
2778
|
+
onApplyGeneratedIconSet
|
|
2779
|
+
}
|
|
2780
|
+
),
|
|
2781
|
+
/* @__PURE__ */ jsx(
|
|
2782
|
+
BlockForm,
|
|
2783
|
+
{
|
|
2784
|
+
siteId,
|
|
2785
|
+
block,
|
|
2786
|
+
manifest,
|
|
2787
|
+
uiStore,
|
|
2788
|
+
hasRecoveryConflict,
|
|
2789
|
+
focusSignal: focusSignal ?? null,
|
|
2790
|
+
onFocusHandled,
|
|
2791
|
+
onSaveSuccess: (data) => {
|
|
2792
|
+
if (block.id && onBlockSave) {
|
|
2793
|
+
onBlockSave(block.id, data);
|
|
2794
|
+
}
|
|
2795
|
+
},
|
|
2796
|
+
theme,
|
|
2797
|
+
widgetOverrides,
|
|
2798
|
+
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
2799
|
+
pageDesignBlock
|
|
2800
|
+
}
|
|
2801
|
+
)
|
|
2802
|
+
] });
|
|
2339
2803
|
}
|
|
2340
2804
|
function getBaselineContent(content) {
|
|
2341
2805
|
if (!content || typeof content !== "object") return {};
|
|
@@ -2579,10 +3043,16 @@ function BlockCardHeader({
|
|
|
2579
3043
|
theme,
|
|
2580
3044
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
2581
3045
|
reorderControlMode = "full",
|
|
2582
|
-
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
3046
|
+
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE,
|
|
3047
|
+
currentStyleGuideVersionId,
|
|
3048
|
+
iconStyleGuideSummary,
|
|
3049
|
+
iconStyleGuideEditHref,
|
|
3050
|
+
onGenerateIconSet,
|
|
3051
|
+
onApplyGeneratedIconSet
|
|
2583
3052
|
}) {
|
|
2584
3053
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
2585
3054
|
const [settingsDialogOpen, setSettingsDialogOpen] = useState(false);
|
|
3055
|
+
const [generateIconSetDialogOpen, setGenerateIconSetDialogOpen] = useState(false);
|
|
2586
3056
|
const [settingsAvailable, setSettingsAvailable] = useState(true);
|
|
2587
3057
|
const showMoveButtons = shouldShowMoveButtons(reorderControlMode);
|
|
2588
3058
|
const showActionsMenu = actionControlMode === "menu";
|
|
@@ -2591,12 +3061,42 @@ function BlockCardHeader({
|
|
|
2591
3061
|
typeof block.id === "string" ? unsafeAsEditorBlockId(block.id) : null
|
|
2592
3062
|
);
|
|
2593
3063
|
const contentToUse = baselineContent ?? block.content;
|
|
3064
|
+
const blockId = typeof block.id === "string" ? unsafeAsEditorBlockId(block.id) : null;
|
|
3065
|
+
const supportsIconActions = supportsFeatureCardIconActions(block.kind);
|
|
3066
|
+
const currentContent = useStoreSelector(
|
|
3067
|
+
uiStore,
|
|
3068
|
+
(state) => supportsIconActions && blockId ? state.drafts.getCurrentValues(blockId) : null
|
|
3069
|
+
);
|
|
3070
|
+
const featureCardIconStatus = supportsIconActions ? getFeatureCardIconStatus(currentContent ?? block.draftContent ?? contentToUse) : null;
|
|
3071
|
+
const featureCardIconActionsAvailable = Boolean(blockId) && supportsIconActions && (featureCardIconStatus?.totalCards ?? 0) > 0;
|
|
3072
|
+
const featureCardIconsComplete = featureCardIconStatus !== null && featureCardIconStatus.totalCards > 0 && featureCardIconStatus.cardsWithIcons >= featureCardIconStatus.totalCards;
|
|
3073
|
+
const featureCardSuggestionActionAvailable = featureCardIconActionsAvailable && !featureCardIconsComplete;
|
|
3074
|
+
const generatedIconSetActionsAvailable = featureCardIconActionsAvailable && Boolean(onGenerateIconSet);
|
|
3075
|
+
const featureCardIconContent = currentContent ?? block.draftContent ?? contentToUse;
|
|
3076
|
+
const featureCardIconDialogCards = supportsIconActions ? getFeatureCardIconDialogCards(featureCardIconContent) : [];
|
|
3077
|
+
const featureCardIconStyleSummary = supportsIconActions ? getFeatureCardGeneratedIconStyleSummary(featureCardIconContent, currentStyleGuideVersionId) : { kind: "unavailable" };
|
|
3078
|
+
const hasStaleGeneratedIcons = featureCardIconStyleSummary.kind === "available" && featureCardIconStyleSummary.staleCount > 0;
|
|
3079
|
+
async function applyGeneratedIconSetPreview(preview) {
|
|
3080
|
+
if (!blockId) return { kind: "failed", message: "Could not apply generated icon set" };
|
|
3081
|
+
const appliedPreview = await onApplyGeneratedIconSet?.(preview);
|
|
3082
|
+
const previewToApply = appliedPreview ?? preview;
|
|
3083
|
+
const result = applyGeneratedFeatureCardIconSet({
|
|
3084
|
+
blockId,
|
|
3085
|
+
content: featureCardIconContent,
|
|
3086
|
+
drafts: uiStore.getState().drafts,
|
|
3087
|
+
assets: previewToApply.assets
|
|
3088
|
+
});
|
|
3089
|
+
if (result.kind !== "applied") {
|
|
3090
|
+
return { kind: "failed", message: "Could not apply generated icon set" };
|
|
3091
|
+
}
|
|
3092
|
+
return { kind: "applied" };
|
|
3093
|
+
}
|
|
2594
3094
|
const { displayTitle, showSubtitle } = resolveBlockTitle(
|
|
2595
3095
|
manifest,
|
|
2596
3096
|
contentToUse,
|
|
2597
3097
|
block.kind
|
|
2598
3098
|
);
|
|
2599
|
-
const hasMenuActions = settingsAvailable || Boolean(onDuplicate) || Boolean(onDelete);
|
|
3099
|
+
const hasMenuActions = settingsAvailable || featureCardSuggestionActionAvailable || generatedIconSetActionsAvailable || Boolean(onDuplicate) || Boolean(onDelete);
|
|
2600
3100
|
const settingsModal = /* @__PURE__ */ jsx(
|
|
2601
3101
|
BlockSettingsModal,
|
|
2602
3102
|
{
|
|
@@ -2706,7 +3206,39 @@ function BlockCardHeader({
|
|
|
2706
3206
|
/* @__PURE__ */ jsx(Settings, { className: "mr-2 h-4 w-4" }),
|
|
2707
3207
|
"Settings"
|
|
2708
3208
|
] }) : null,
|
|
2709
|
-
|
|
3209
|
+
featureCardIconActionsAvailable ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3210
|
+
settingsAvailable ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}) : null,
|
|
3211
|
+
/* @__PURE__ */ jsxs(
|
|
3212
|
+
DropdownMenuItem,
|
|
3213
|
+
{
|
|
3214
|
+
disabled: !blockId || featureCardIconsComplete,
|
|
3215
|
+
onSelect: () => {
|
|
3216
|
+
if (!blockId) return;
|
|
3217
|
+
applyCuratedFeatureCardIconSuggestions({
|
|
3218
|
+
blockId,
|
|
3219
|
+
content: currentContent ?? block.draftContent ?? contentToUse,
|
|
3220
|
+
drafts: uiStore.getState().drafts
|
|
3221
|
+
});
|
|
3222
|
+
},
|
|
3223
|
+
children: [
|
|
3224
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "mr-2 h-4 w-4" }),
|
|
3225
|
+
"Suggest icons"
|
|
3226
|
+
]
|
|
3227
|
+
}
|
|
3228
|
+
),
|
|
3229
|
+
generatedIconSetActionsAvailable ? /* @__PURE__ */ jsxs(
|
|
3230
|
+
DropdownMenuItem,
|
|
3231
|
+
{
|
|
3232
|
+
disabled: !blockId || featureCardIconDialogCards.length === 0,
|
|
3233
|
+
onSelect: () => setGenerateIconSetDialogOpen(true),
|
|
3234
|
+
children: [
|
|
3235
|
+
hasStaleGeneratedIcons ? /* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }) : /* @__PURE__ */ jsx(ImagePlus, { className: "mr-2 h-4 w-4" }),
|
|
3236
|
+
hasStaleGeneratedIcons ? "Regenerate icon set" : "Generate icon set"
|
|
3237
|
+
]
|
|
3238
|
+
}
|
|
3239
|
+
) : null
|
|
3240
|
+
] }) : null,
|
|
3241
|
+
(settingsAvailable || featureCardIconActionsAvailable) && (onDuplicate || onDelete) ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}) : null,
|
|
2710
3242
|
onDuplicate ? /* @__PURE__ */ jsxs(
|
|
2711
3243
|
DropdownMenuItem,
|
|
2712
3244
|
{
|
|
@@ -2803,7 +3335,19 @@ function BlockCardHeader({
|
|
|
2803
3335
|
}
|
|
2804
3336
|
)
|
|
2805
3337
|
] })
|
|
2806
|
-
] }) })
|
|
3338
|
+
] }) }),
|
|
3339
|
+
generatedIconSetActionsAvailable ? /* @__PURE__ */ jsx(
|
|
3340
|
+
GeneratedIconSetDialog,
|
|
3341
|
+
{
|
|
3342
|
+
open: generateIconSetDialogOpen,
|
|
3343
|
+
onOpenChange: setGenerateIconSetDialogOpen,
|
|
3344
|
+
cards: featureCardIconDialogCards,
|
|
3345
|
+
styleGuideSummary: iconStyleGuideSummary,
|
|
3346
|
+
styleGuideEditHref: iconStyleGuideEditHref,
|
|
3347
|
+
onGenerate: onGenerateIconSet,
|
|
3348
|
+
onApply: applyGeneratedIconSetPreview
|
|
3349
|
+
}
|
|
3350
|
+
) : null
|
|
2807
3351
|
] });
|
|
2808
3352
|
}
|
|
2809
3353
|
function BlockCard({
|
|
@@ -2831,7 +3375,12 @@ function BlockCard({
|
|
|
2831
3375
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
2832
3376
|
pageDesignBlock = null,
|
|
2833
3377
|
reorderControlMode = DEFAULT_REORDER_CONTROL_MODE,
|
|
2834
|
-
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
3378
|
+
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE,
|
|
3379
|
+
currentStyleGuideVersionId,
|
|
3380
|
+
iconStyleGuideSummary,
|
|
3381
|
+
iconStyleGuideEditHref,
|
|
3382
|
+
onGenerateIconSet,
|
|
3383
|
+
onApplyGeneratedIconSet
|
|
2835
3384
|
}) {
|
|
2836
3385
|
const contentId = block.id ? `builder-block-content-${block.id}` : void 0;
|
|
2837
3386
|
return /* @__PURE__ */ jsx(
|
|
@@ -2862,7 +3411,12 @@ function BlockCard({
|
|
|
2862
3411
|
theme,
|
|
2863
3412
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
2864
3413
|
reorderControlMode,
|
|
2865
|
-
actionControlMode
|
|
3414
|
+
actionControlMode,
|
|
3415
|
+
currentStyleGuideVersionId,
|
|
3416
|
+
iconStyleGuideSummary,
|
|
3417
|
+
iconStyleGuideEditHref,
|
|
3418
|
+
onGenerateIconSet,
|
|
3419
|
+
onApplyGeneratedIconSet
|
|
2866
3420
|
}
|
|
2867
3421
|
),
|
|
2868
3422
|
/* @__PURE__ */ jsx(CollapsibleContent, { id: contentId, children: /* @__PURE__ */ jsx(
|
|
@@ -2879,7 +3433,12 @@ function BlockCard({
|
|
|
2879
3433
|
theme,
|
|
2880
3434
|
widgetOverrides,
|
|
2881
3435
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
2882
|
-
pageDesignBlock
|
|
3436
|
+
pageDesignBlock,
|
|
3437
|
+
currentStyleGuideVersionId,
|
|
3438
|
+
iconStyleGuideSummary,
|
|
3439
|
+
iconStyleGuideEditHref,
|
|
3440
|
+
onGenerateIconSet,
|
|
3441
|
+
onApplyGeneratedIconSet
|
|
2883
3442
|
}
|
|
2884
3443
|
) })
|
|
2885
3444
|
] })
|
|
@@ -2911,7 +3470,12 @@ var SortableBlockItem = memo(function SortableBlockItem2({
|
|
|
2911
3470
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2 = false,
|
|
2912
3471
|
pageDesignBlock = null,
|
|
2913
3472
|
reorderControlMode = DEFAULT_REORDER_CONTROL_MODE,
|
|
2914
|
-
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE
|
|
3473
|
+
actionControlMode = DEFAULT_BLOCK_ACTION_CONTROL_MODE,
|
|
3474
|
+
currentStyleGuideVersionId,
|
|
3475
|
+
iconStyleGuideSummary,
|
|
3476
|
+
iconStyleGuideEditHref,
|
|
3477
|
+
onGenerateIconSet,
|
|
3478
|
+
onApplyGeneratedIconSet
|
|
2915
3479
|
}) {
|
|
2916
3480
|
const sortable = useSortable({
|
|
2917
3481
|
id: block.id,
|
|
@@ -2994,7 +3558,12 @@ var SortableBlockItem = memo(function SortableBlockItem2({
|
|
|
2994
3558
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
2995
3559
|
pageDesignBlock,
|
|
2996
3560
|
reorderControlMode,
|
|
2997
|
-
actionControlMode
|
|
3561
|
+
actionControlMode,
|
|
3562
|
+
currentStyleGuideVersionId,
|
|
3563
|
+
iconStyleGuideSummary,
|
|
3564
|
+
iconStyleGuideEditHref,
|
|
3565
|
+
onGenerateIconSet,
|
|
3566
|
+
onApplyGeneratedIconSet
|
|
2998
3567
|
}
|
|
2999
3568
|
)
|
|
3000
3569
|
}
|
|
@@ -3046,6 +3615,7 @@ var BlockEditor = forwardRef(
|
|
|
3046
3615
|
);
|
|
3047
3616
|
const [fetchedContentTypes, setFetchedContentTypes] = useState(enabledContentTypes);
|
|
3048
3617
|
const [fetchingContentTypes, setFetchingContentTypes] = useState(false);
|
|
3618
|
+
const [iconStyleGuide, setIconStyleGuide] = useState(null);
|
|
3049
3619
|
const allowReordering = enableReordering;
|
|
3050
3620
|
const allowCreation = enableCreation;
|
|
3051
3621
|
const conflictedBlockIdSet = useMemo(
|
|
@@ -3072,6 +3642,99 @@ var BlockEditor = forwardRef(
|
|
|
3072
3642
|
useEffect(() => {
|
|
3073
3643
|
setBlockList(normalizeBlockListInitial(blocks));
|
|
3074
3644
|
}, [blocks]);
|
|
3645
|
+
useEffect(() => {
|
|
3646
|
+
if (typeof apiClient !== "function") {
|
|
3647
|
+
setIconStyleGuide(null);
|
|
3648
|
+
return void 0;
|
|
3649
|
+
}
|
|
3650
|
+
let cancelled = false;
|
|
3651
|
+
void Promise.resolve().then(() => apiClient({
|
|
3652
|
+
endpoint: "getSiteIconStyleGuide",
|
|
3653
|
+
params: { siteId }
|
|
3654
|
+
})).then(unwrapResponse).then((response) => {
|
|
3655
|
+
if (cancelled) return;
|
|
3656
|
+
const versionId = parseSiteIconStyleGuideVersionId(response.guide.versionId);
|
|
3657
|
+
setIconStyleGuide(versionId ? {
|
|
3658
|
+
versionId,
|
|
3659
|
+
summary: response.guide.displaySummary,
|
|
3660
|
+
editHref: `/dashboard/sites/${siteId}/settings/icon-style-guide`
|
|
3661
|
+
} : null);
|
|
3662
|
+
}).catch(() => {
|
|
3663
|
+
if (!cancelled) setIconStyleGuide(null);
|
|
3664
|
+
});
|
|
3665
|
+
return () => {
|
|
3666
|
+
cancelled = true;
|
|
3667
|
+
};
|
|
3668
|
+
}, [apiClient, siteId]);
|
|
3669
|
+
const generateFeatureCardIconSet = useCallback(async (input) => {
|
|
3670
|
+
if (typeof apiClient !== "function") {
|
|
3671
|
+
return { kind: "failed", message: "Generated icon set API is unavailable" };
|
|
3672
|
+
}
|
|
3673
|
+
try {
|
|
3674
|
+
const response = unwrapResponse(await apiClient({
|
|
3675
|
+
endpoint: "generateGeneratedIconSet",
|
|
3676
|
+
params: { siteId },
|
|
3677
|
+
body: {
|
|
3678
|
+
blockKind: "block.feature-cards",
|
|
3679
|
+
blockLabel: "Feature cards",
|
|
3680
|
+
userStyleNote: input.userStyleNote,
|
|
3681
|
+
cards: input.cards.map((card) => ({
|
|
3682
|
+
cardKey: card.cardKey,
|
|
3683
|
+
title: card.title,
|
|
3684
|
+
bodyText: card.bodyText,
|
|
3685
|
+
semanticIconId: card.semanticIconId
|
|
3686
|
+
}))
|
|
3687
|
+
}
|
|
3688
|
+
}));
|
|
3689
|
+
const assets = response.preview.assets.map((asset) => {
|
|
3690
|
+
const iconValue = parseBlockIconValue(asset.iconValue);
|
|
3691
|
+
if (iconValue.kind !== "generated") {
|
|
3692
|
+
throw new Error("Generated icon response included an invalid icon reference");
|
|
3693
|
+
}
|
|
3694
|
+
return {
|
|
3695
|
+
cardKey: asset.cardKey,
|
|
3696
|
+
title: input.cards.find((card) => card.cardKey === asset.cardKey)?.title ?? asset.cardKey,
|
|
3697
|
+
src: asset.src,
|
|
3698
|
+
iconValue
|
|
3699
|
+
};
|
|
3700
|
+
});
|
|
3701
|
+
return {
|
|
3702
|
+
kind: "preview_ready",
|
|
3703
|
+
preview: {
|
|
3704
|
+
setId: response.candidate.setId,
|
|
3705
|
+
styleGuideSummary: response.styleGuide.displaySummary,
|
|
3706
|
+
candidate: response.candidate,
|
|
3707
|
+
assets
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
} catch (error) {
|
|
3711
|
+
return {
|
|
3712
|
+
kind: "failed",
|
|
3713
|
+
message: error instanceof Error && error.message ? error.message : "Failed to generate icon set"
|
|
3714
|
+
};
|
|
3715
|
+
}
|
|
3716
|
+
}, [apiClient, siteId]);
|
|
3717
|
+
const applyGeneratedFeatureCardIconSet2 = useCallback(async (preview) => {
|
|
3718
|
+
if (typeof apiClient !== "function") return preview;
|
|
3719
|
+
if (!preview.candidate) return preview;
|
|
3720
|
+
const response = unwrapResponse(await apiClient({
|
|
3721
|
+
endpoint: "applyGeneratedIconSet",
|
|
3722
|
+
params: { siteId },
|
|
3723
|
+
body: { candidate: preview.candidate }
|
|
3724
|
+
}));
|
|
3725
|
+
const iconValuesByCardKey = new Map(response.assets.map((asset) => [asset.cardKey, asset.iconValue]));
|
|
3726
|
+
return {
|
|
3727
|
+
...preview,
|
|
3728
|
+
assets: preview.assets.map((asset) => {
|
|
3729
|
+
const applied = iconValuesByCardKey.get(asset.cardKey);
|
|
3730
|
+
const iconValue = parseBlockIconValue(applied ?? asset.iconValue);
|
|
3731
|
+
if (iconValue.kind !== "generated") {
|
|
3732
|
+
throw new Error("Generated icon apply response included an invalid icon reference");
|
|
3733
|
+
}
|
|
3734
|
+
return { ...asset, iconValue };
|
|
3735
|
+
})
|
|
3736
|
+
};
|
|
3737
|
+
}, [apiClient, siteId]);
|
|
3075
3738
|
useEffect(() => {
|
|
3076
3739
|
const unsubscribe = uiStore.subscribe(() => {
|
|
3077
3740
|
const structureList = uiStore.getState().structure.getList();
|
|
@@ -3385,7 +4048,12 @@ var BlockEditor = forwardRef(
|
|
|
3385
4048
|
hideThemeV2RawStyleFields: hideThemeV2RawStyleFields2,
|
|
3386
4049
|
pageDesignBlock: block.id ? pageDesignBlockById.get(block.id) ?? null : null,
|
|
3387
4050
|
reorderControlMode,
|
|
3388
|
-
actionControlMode
|
|
4051
|
+
actionControlMode,
|
|
4052
|
+
currentStyleGuideVersionId: iconStyleGuide?.versionId ?? null,
|
|
4053
|
+
iconStyleGuideSummary: iconStyleGuide?.summary ?? null,
|
|
4054
|
+
iconStyleGuideEditHref: iconStyleGuide?.editHref ?? null,
|
|
4055
|
+
onGenerateIconSet: generateFeatureCardIconSet,
|
|
4056
|
+
onApplyGeneratedIconSet: applyGeneratedFeatureCardIconSet2
|
|
3389
4057
|
}
|
|
3390
4058
|
),
|
|
3391
4059
|
allowCreation && index < blockList.length - 1 ? /* @__PURE__ */ jsx(
|
|
@@ -4835,15 +5503,17 @@ function EntryPickerField({
|
|
|
4835
5503
|
}
|
|
4836
5504
|
function IconPickerField({ path, backend, config }) {
|
|
4837
5505
|
const { value, error, setValue } = useField(path, backend);
|
|
4838
|
-
const
|
|
4839
|
-
|
|
4840
|
-
|
|
5506
|
+
const configuredPreset = config.ui?.iconPickerPreset;
|
|
5507
|
+
const preset = resolveIconPickerPreset(configuredPreset);
|
|
5508
|
+
if (configuredPreset && !isIconPickerPreset(configuredPreset) && true) {
|
|
5509
|
+
console.warn(`[IconPickerField] Unknown iconPickerPreset "${configuredPreset}" at "${path}". Falling back to "cta".`);
|
|
4841
5510
|
}
|
|
4842
|
-
const
|
|
5511
|
+
const options = getIconPickerOptionsForPreset(preset);
|
|
5512
|
+
const selected = typeof value === "string" && isKnownIconName(value) && options.some((option) => option.id === value) ? value : void 0;
|
|
4843
5513
|
return /* @__PURE__ */ jsx(FieldFrame, { label: config.label, description: config.description, error: error?.message, children: () => /* @__PURE__ */ jsx(
|
|
4844
5514
|
Combobox,
|
|
4845
5515
|
{
|
|
4846
|
-
items:
|
|
5516
|
+
items: options.map((opt) => ({ id: opt.id, label: opt.label, searchText: opt.searchText, item: opt })),
|
|
4847
5517
|
value: selected,
|
|
4848
5518
|
onSelect: (entry) => {
|
|
4849
5519
|
if (!entry) {
|
|
@@ -4855,7 +5525,7 @@ function IconPickerField({ path, backend, config }) {
|
|
|
4855
5525
|
placeholder: "Select icon\u2026",
|
|
4856
5526
|
clearLabel: "Clear",
|
|
4857
5527
|
renderItem: (entry) => {
|
|
4858
|
-
const Icon =
|
|
5528
|
+
const Icon = getIconComponent(entry.id);
|
|
4859
5529
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4860
5530
|
Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }) : null,
|
|
4861
5531
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: entry.label })
|
|
@@ -6864,8 +7534,15 @@ function SiteChromeLookRow({
|
|
|
6864
7534
|
}
|
|
6865
7535
|
function PaletteRow({ expanded, onToggle, siteStyle, currentId, currentLabel, currentSwatch, onPreview, disabled }) {
|
|
6866
7536
|
const options = useMemo(
|
|
6867
|
-
() =>
|
|
6868
|
-
|
|
7537
|
+
() => {
|
|
7538
|
+
const recommended = requireEntriesForCuratedChoices(paletteVariants, siteStyle.paletteVariantChoices);
|
|
7539
|
+
if (recommended.some((variant) => variant.id === currentId)) {
|
|
7540
|
+
return recommended;
|
|
7541
|
+
}
|
|
7542
|
+
const current = findPaletteVariant(currentId);
|
|
7543
|
+
return current ? [current, ...recommended] : recommended;
|
|
7544
|
+
},
|
|
7545
|
+
[currentId, siteStyle.paletteVariantChoices]
|
|
6869
7546
|
);
|
|
6870
7547
|
return /* @__PURE__ */ jsx(
|
|
6871
7548
|
StyleRowFrame,
|
|
@@ -7010,7 +7687,7 @@ function describeWarning(warning) {
|
|
|
7010
7687
|
case "rejected-personality":
|
|
7011
7688
|
return `Button style changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
7012
7689
|
case "rejected-palette":
|
|
7013
|
-
return `Palette changed to ${warning.fellBackTo} because ${warning.requested} is not
|
|
7690
|
+
return `Palette changed to ${warning.fellBackTo} because ${warning.requested} is not available.`;
|
|
7014
7691
|
case "rejected-typography-preset":
|
|
7015
7692
|
return `Typography changed to ${warning.fellBackTo} because ${warning.requested} is not offered for this site style.`;
|
|
7016
7693
|
default: {
|