camox 0.44.0 → 0.45.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/dist/components/AuthGate.js +0 -6
- package/dist/components/DeviceSelector.js +96 -0
- package/dist/components/PlatformLabel.js +20 -24
- package/dist/core/components/lexical/HighlightNode.js +1 -1
- package/dist/core/components/lexical/InlineContentEditable.js +15 -19
- package/dist/core/components/lexical/InlineLexicalEditor.js +54 -74
- package/dist/core/components/lexical/InlineStylesPlugin.js +53 -53
- package/dist/core/components/lexical/MaxLengthPlugin.js +59 -0
- package/dist/core/components/lexical/SelectionBroadcaster.js +53 -54
- package/dist/core/components/lexical/SidebarLexicalEditor.js +322 -229
- package/dist/core/components/lexical/SummaryToggleGuard.js +42 -0
- package/dist/core/components/lexical/TextLinkPopover.js +169 -180
- package/dist/core/createApp.d.ts +241 -312
- package/dist/core/createApp.js +123 -29
- package/dist/core/createBlock.d.ts +5 -5
- package/dist/core/createBlock.js +385 -152
- package/dist/core/createCollection.d.ts +55 -0
- package/dist/core/createCollection.js +93 -0
- package/dist/core/createLayout.d.ts +197 -61
- package/dist/core/createLayout.js +114 -56
- package/dist/core/defineDocument.d.ts +3 -5
- package/dist/core/derivedRoutes.js +49 -1
- package/dist/core/dom.d.ts +13 -4
- package/dist/core/dom.js +44 -1
- package/dist/core/editing/BlockEditingRuntime.d.ts +16 -0
- package/dist/core/editing/BlockEditingRuntime.js +6 -15
- package/dist/core/editing/CompleteBlockEditingRuntime.js +28 -23
- package/dist/core/editing/createEditableBlock.d.ts +754 -633
- package/dist/core/editing/createEditableBlock.js +2113 -1066
- package/dist/core/editing/referenceWrites.js +51 -0
- package/dist/core/editing/useLatestRecord.js +90 -0
- package/dist/core/hooks/useArtifactHost.js +139 -0
- package/dist/core/hooks/useFieldSelection.js +43 -18
- package/dist/core/hooks/useIsEditable.js +12 -10
- package/dist/core/hooks/useOverlayMessage.js +15 -19
- package/dist/core/lib/artifact.d.ts +21 -0
- package/dist/core/lib/artifact.js +154 -0
- package/dist/core/lib/artifactColors.js +123 -0
- package/dist/core/lib/artifactData.d.ts +1 -0
- package/dist/core/lib/artifactData.js +131 -0
- package/dist/core/lib/artifactHost.js +205 -0
- package/dist/core/lib/artifactRuntime.js +36 -0
- package/dist/core/lib/artifactTheme.js +57 -0
- package/dist/core/lib/contentType.d.ts +302 -106
- package/dist/core/lib/contentType.js +201 -173
- package/dist/core/lib/fieldTypes.js +3 -0
- package/dist/core/lib/iconTypes.d.ts +3 -3
- package/dist/core/lib/icons.d.ts +4 -4
- package/dist/core/lib/icons.js +40 -44
- package/dist/core/lib/imagePlaceholder.js +177 -0
- package/dist/core/lib/imageTransform.js +1 -1
- package/dist/core/lib/lexicalReact.d.ts +3 -1
- package/dist/core/lib/lexicalState.js +1 -1
- package/dist/core/lib/previewPaused.js +9 -0
- package/dist/core/lib/recordScope.js +316 -0
- package/dist/core/lib/reference.d.ts +81 -0
- package/dist/core/lib/reference.js +29 -0
- package/dist/core/lib/textLinks.js +7 -5
- package/dist/core/lib/textStyles.d.ts +5 -7
- package/dist/core/lib/textStyles.js +2 -2
- package/dist/core/notFound.d.ts +7 -0
- package/dist/core/notFound.js +11 -0
- package/dist/core/pageDestinations.js +6 -3
- package/dist/core/recordItem.js +34 -0
- package/dist/core/requestContext.d.ts +26 -0
- package/dist/core/requestContext.js +20 -0
- package/dist/features/canvas/CamoxCanvas.js +1734 -0
- package/dist/features/canvas/CanvasBlockFrame.js +353 -0
- package/dist/features/canvas/CanvasBlockHeader.js +55 -0
- package/dist/features/canvas/CanvasLoadingScreen.js +35 -0
- package/dist/features/canvas/CanvasOverlays.js +254 -0
- package/dist/features/canvas/CanvasPageEdge.js +87 -0
- package/dist/features/canvas/CanvasPageFrame.js +335 -0
- package/dist/features/canvas/CanvasPageHeader.js +125 -0
- package/dist/features/canvas/CanvasPreviewPageSlot.js +103 -0
- package/dist/features/canvas/CanvasShelfMarker.js +255 -0
- package/dist/features/canvas/DerivedPagePathInput.js +238 -0
- package/dist/features/canvas/canvasCamera.js +229 -0
- package/dist/features/canvas/canvasFlight.js +104 -0
- package/dist/features/canvas/canvasFrameCapture.js +364 -0
- package/dist/features/canvas/canvasFrameDocument.js +317 -0
- package/dist/features/canvas/canvasFrameMode.js +53 -0
- package/dist/features/canvas/canvasInsertionSeams.js +44 -0
- package/dist/features/canvas/canvasItems.js +120 -0
- package/dist/features/canvas/canvasOverlayGeometry.js +240 -0
- package/dist/features/canvas/canvasPages.js +79 -0
- package/dist/features/canvas/canvasScreenSpace.js +26 -0
- package/dist/features/canvas/canvasSelection.js +18 -0
- package/dist/features/canvas/canvasStore.js +149 -0
- package/dist/features/canvas/canvasThumbnails.js +304 -0
- package/dist/features/canvas/canvasZoom.js +10 -0
- package/dist/features/canvas/sidebar/CanvasInspector.js +202 -0
- package/dist/features/canvas/sidebar/CanvasNavigator.js +226 -0
- package/dist/features/canvas/sidebar/CanvasSidebar.js +60 -0
- package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +48 -0
- package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +39 -0
- package/dist/features/canvas/sidebar/CatalogBlockInspector.js +189 -0
- package/dist/features/canvas/sidebar/CuratedPageInspector.js +69 -0
- package/dist/features/canvas/sidebar/DerivedPageInspector.js +37 -0
- package/dist/features/canvas/sidebar/LayoutPageBlocks.js +78 -0
- package/dist/features/canvas/sidebar/LayoutPageOverview.js +71 -0
- package/dist/features/canvas/sidebar/PageInspector.js +157 -0
- package/dist/features/canvas/sidebar/PageInspectorSkeleton.js +90 -0
- package/dist/features/canvas/sidebar/PageOverview.js +27 -0
- package/dist/features/canvas/sidebar/SingletonPageInspector.js +31 -0
- package/dist/features/canvas/useCanvasCamera.js +803 -0
- package/dist/features/canvas/useCanvasFrame.js +149 -0
- package/dist/features/canvas/useCanvasFrameInput.js +97 -0
- package/dist/features/canvas/useCanvasNearness.js +57 -0
- package/dist/features/canvas/useDiscoveredPreviewPaths.js +62 -0
- package/dist/features/content/CamoxContent.d.ts +2 -5
- package/dist/features/content/CamoxContent.js +174 -271
- package/dist/features/content/CollectionItemSheetContext.js +106 -0
- package/dist/features/content/ContentAssets.js +315 -0
- package/dist/features/content/ContentCollection.js +663 -0
- package/dist/features/content/collection-form.js +58 -0
- package/dist/features/content/components/AssetCard.js +80 -84
- package/dist/features/content/components/AssetCardSkeleton.js +4 -8
- package/dist/features/content/components/ContentSidebar.js +129 -18
- package/dist/features/content/components/ContentSidebarGroup.js +37 -0
- package/dist/features/content/components/DeleteCollectionItemButton.js +202 -0
- package/dist/features/content/components/MissingFromLocale.js +282 -0
- package/dist/features/content/components/UploadDropZone.js +27 -31
- package/dist/features/content/components/UploadProgressDrawer.js +90 -98
- package/dist/features/navigation/navigation.d.ts +66 -20
- package/dist/features/navigation/navigation.js +257 -90
- package/dist/features/og/defaultFonts.js +8 -8
- package/dist/features/og/geist-variable-ttf-base64.js +1 -1
- package/dist/features/og/imageResponse.d.ts +8 -0
- package/dist/features/og/imageResponse.js +26 -0
- package/dist/features/page/CuratedPageContent.js +167 -0
- package/dist/features/page/DerivedPageContent.js +26 -30
- package/dist/features/page/SharedLayoutContent.js +25 -27
- package/dist/features/preview/CamoxPreview.d.ts +23 -61
- package/dist/features/preview/CamoxPreview.js +816 -537
- package/dist/features/preview/EditablePageContent.js +1 -1
- package/dist/features/preview/EditablePageExperience.js +16 -22
- package/dist/features/preview/components/AddBlockDialog.js +270 -0
- package/dist/features/preview/components/AssetFieldEditor.js +173 -154
- package/dist/features/preview/components/AssetLightbox.js +181 -134
- package/dist/features/preview/components/AssetPickerModal.js +153 -170
- package/dist/features/preview/components/BlockActionsPopover.js +150 -149
- package/dist/features/preview/components/BlockErrorBoundary.js +8 -12
- package/dist/features/preview/components/BlockThumbnail.js +176 -100
- package/dist/features/preview/components/CanvasPreview.js +243 -0
- package/dist/features/preview/components/CreatePageModal.js +128 -137
- package/dist/features/preview/components/DebouncedFieldEditor.js +29 -33
- package/dist/features/preview/components/DerivedLayoutDialog.js +21 -19
- package/dist/features/preview/components/DrillRow.js +150 -0
- package/dist/features/preview/components/FieldOverlayStyles.js +11 -8
- package/dist/features/preview/components/FieldToolbar.js +160 -110
- package/dist/features/preview/components/Frame.js +108 -20
- package/dist/features/preview/components/IconFieldEditor.js +62 -66
- package/dist/features/preview/components/ItemFieldsEditor.js +231 -205
- package/dist/features/preview/components/LinkFieldEditor.js +135 -139
- package/dist/features/preview/components/Metadata.js +22 -30
- package/dist/features/preview/components/MobilePreviewDrawer.js +89 -108
- package/dist/features/preview/components/MultipleAssetFieldEditor.js +334 -246
- package/dist/features/preview/components/OverlayTracker.js +9 -41
- package/dist/features/preview/components/Overlays.js +81 -69
- package/dist/features/preview/components/PageInfo.js +1748 -0
- package/dist/features/preview/components/PageInfoSkeleton.js +51 -0
- package/dist/features/preview/components/PageLocationFieldset.js +112 -116
- package/dist/features/preview/components/PageNavigatorHeader.js +24 -0
- package/dist/features/preview/components/PageNicknameField.js +22 -26
- package/dist/features/preview/components/PagePicker.js +128 -130
- package/dist/features/preview/components/PageTree.js +525 -532
- package/dist/features/preview/components/PreviewActivation.js +28 -32
- package/dist/features/preview/components/PreviewPanel.js +620 -319
- package/dist/features/preview/components/PreviewToolbar.js +105 -333
- package/dist/features/preview/components/RecordCard.js +80 -0
- package/dist/features/preview/components/RecordCombobox.js +178 -0
- package/dist/features/preview/components/ReferenceFieldEditor.js +149 -0
- package/dist/features/preview/components/ReferenceListFieldEditor.js +432 -0
- package/dist/features/preview/components/RemovedBlockPlaceholder.js +95 -0
- package/dist/features/preview/components/RepeatableItemsList.js +125 -138
- package/dist/features/preview/components/SelectionEditor.js +993 -0
- package/dist/features/preview/components/ShikiMarkdown.js +14 -18
- package/dist/features/preview/components/SidebarSection.js +52 -64
- package/dist/features/preview/components/StudioEditingFallback.js +56 -0
- package/dist/features/preview/components/UnlinkAssetButton.js +104 -107
- package/dist/features/preview/components/blockGridNavigation.js +15 -0
- package/dist/features/preview/components/contentFieldSchema.js +8 -0
- package/dist/features/preview/components/useFieldWriter.js +200 -0
- package/dist/features/preview/components/useRecordView.js +383 -0
- package/dist/features/preview/components/useRepeatableItemActions.js +35 -37
- package/dist/features/preview/components/useUpdateBlockPosition.js +37 -37
- package/dist/features/preview/editingFrame.js +197 -0
- package/dist/features/preview/overlayHighlights.js +17 -44
- package/dist/features/preview/overlayMessages.js +72 -1
- package/dist/features/preview/pageRecord.js +189 -0
- package/dist/features/preview/previewConstants.js +6 -2
- package/dist/features/preview/previewPageFrame.js +95 -0
- package/dist/features/preview/previewPreparation.js +7 -0
- package/dist/features/preview/previewSelection.js +32 -63
- package/dist/features/preview/previewStore.js +225 -123
- package/dist/features/preview/referencePickerFocus.js +29 -0
- package/dist/features/preview/repeatableItemTargets.js +56 -0
- package/dist/features/preview/selectionReveal.js +21 -0
- package/dist/features/preview/usePreviewViewportActions.js +114 -0
- package/dist/features/preview/viewportContinuity.js +109 -0
- package/dist/features/provider/AuthenticatedCamoxProvider.js +69 -44
- package/dist/features/provider/CamoxProvider.d.ts +3 -6
- package/dist/features/provider/CamoxProvider.js +38 -50
- package/dist/features/provider/CoreCamoxProvider.js +66 -50
- package/dist/features/provider/LocalhostPreviewProvider.js +78 -114
- package/dist/features/provider/PreviewSignInPage.js +54 -0
- package/dist/features/provider/components/CamoxAppContext.js +11 -11
- package/dist/features/provider/components/CommandPalette.js +75 -82
- package/dist/features/provider/useAdminShortcuts.js +7 -11
- package/dist/features/routes/pageRuntime.d.ts +44 -4
- package/dist/features/routes/pageRuntime.js +244 -137
- package/dist/features/runtime/RuntimeChrome.js +117 -115
- package/dist/features/runtime/alternates.js +64 -0
- package/dist/features/runtime/analytics.d.ts +7 -0
- package/dist/features/runtime/analytics.js +66 -0
- package/dist/features/runtime/artifactSources.js +87 -0
- package/dist/features/runtime/editingFallback.js +20 -0
- package/dist/features/runtime/linkPrefetch.js +97 -0
- package/dist/features/runtime/livePages.js +62 -0
- package/dist/features/runtime/llmsTxt.js +40 -0
- package/dist/features/runtime/loopbackFetch.js +18 -0
- package/dist/features/runtime/navigationAccessibility.js +51 -0
- package/dist/features/runtime/navigationTarget.js +23 -2
- package/dist/features/runtime/pageApp.js +229 -158
- package/dist/features/runtime/pageBlockTypes.js +20 -0
- package/dist/features/runtime/pageClient.d.ts +2 -4
- package/dist/features/runtime/pageClient.js +18 -3
- package/dist/features/runtime/pageNavigation.js +254 -32
- package/dist/features/runtime/pageServer.d.ts +2 -4
- package/dist/features/runtime/pageServer.js +6 -2
- package/dist/features/runtime/pageViewport.js +7 -0
- package/dist/features/runtime/runtime.d.ts +59 -24
- package/dist/features/runtime/runtime.js +779 -191
- package/dist/features/runtime/runtimeChromeLoader.js +58 -0
- package/dist/features/runtime/runtimeRoutes.d.ts +19 -0
- package/dist/features/runtime/runtimeRoutes.js +25 -0
- package/dist/features/runtime/scrollRestoration.js +133 -0
- package/dist/features/runtime/studioApp.d.ts +4 -3
- package/dist/features/runtime/studioApp.js +5 -9
- package/dist/features/runtime/studioClient.d.ts +2 -4
- package/dist/features/runtime/studioClient.js +12 -3
- package/dist/features/runtime/studioServer.d.ts +2 -4
- package/dist/features/runtime/studioServer.js +6 -1
- package/dist/features/runtime/worker.d.ts +6 -0
- package/dist/features/runtime/worker.js +23 -0
- package/dist/features/runtime/workerRequest.js +44 -0
- package/dist/features/studio/CamoxStudio.d.ts +2 -6
- package/dist/features/studio/CamoxStudio.js +34 -49
- package/dist/features/studio/FollowAgentProvider.js +338 -0
- package/dist/features/studio/components/ChatSidebar.js +356 -0
- package/dist/features/studio/components/DraftsControl.js +676 -0
- package/dist/features/studio/components/FaviconDialog.js +318 -0
- package/dist/features/studio/components/LocalePicker.js +785 -0
- package/dist/features/studio/components/Navbar.js +123 -103
- package/dist/features/studio/components/ProjectMenu.js +239 -260
- package/dist/features/studio/components/RenameDraftDialog.js +206 -0
- package/dist/features/studio/components/ReviewDraftSheet.js +1472 -0
- package/dist/features/studio/components/ThreadComposer.js +157 -0
- package/dist/features/studio/components/ThreadMarkdown.js +113 -0
- package/dist/features/studio/components/ThreadMessages.js +270 -0
- package/dist/features/studio/components/UserButton.js +34 -23
- package/dist/features/studio/draftLabel.js +33 -0
- package/dist/features/studio/draftNotice.js +13 -0
- package/dist/features/studio/followAgent.js +250 -0
- package/dist/features/studio/followAgentContext.js +7 -0
- package/dist/features/studio/localeOptions.js +118 -0
- package/dist/features/studio/localeSwitch.js +19 -0
- package/dist/features/studio/routes.js +48 -1
- package/dist/features/studio/studioStore.js +64 -1
- package/dist/features/studio/useTheme.js +24 -27
- package/dist/features/vite/artifactRuntimeMinification.js +36 -0
- package/dist/features/vite/blockBoilerplate.js +6 -5
- package/dist/features/vite/blockChunks.js +31 -0
- package/dist/features/vite/bundlerLogs.js +17 -0
- package/dist/features/vite/definitionsSync.js +158 -226
- package/dist/features/vite/devAuthentication.js +4 -16
- package/dist/features/vite/devSignIn.js +87 -0
- package/dist/features/vite/iconGeneration.js +1 -1
- package/dist/features/vite/layoutGeneration.js +11 -1
- package/dist/features/vite/publishSeededContent.js +30 -0
- package/dist/features/vite/routeGeneration.js +6 -7
- package/dist/features/vite/runtimeDev.js +80 -99
- package/dist/features/vite/vite.d.ts +51 -31
- package/dist/features/vite/vite.js +224 -127
- package/dist/features/vite/workerBuild.js +39 -0
- package/dist/hooks/use-debounced-field.js +116 -47
- package/dist/hooks/use-file-upload.js +114 -67
- package/dist/hooks/use-marquee-selection.js +32 -36
- package/dist/hooks/use-page-destinations.js +69 -37
- package/dist/lib/api-client-server.d.ts +5 -0
- package/dist/lib/api-client-server.js +10 -4
- package/dist/lib/api-client.d.ts +6 -0
- package/dist/lib/api-client.js +51 -16
- package/dist/lib/api-socket.js +17 -0
- package/dist/lib/auth-page-styles.js +39 -0
- package/dist/lib/auth.js +117 -61
- package/dist/lib/collection-cache.js +23 -0
- package/dist/lib/draft-scope.d.ts +4 -0
- package/dist/lib/draft-scope.js +222 -0
- package/dist/lib/html.js +12 -0
- package/dist/lib/link-pages.js +154 -0
- package/dist/lib/locale-path.d.ts +22 -0
- package/dist/lib/locale-path.js +57 -0
- package/dist/lib/normalized-data.js +252 -152
- package/dist/lib/preview-handoff.js +2 -2
- package/dist/lib/queries.d.ts +11 -0
- package/dist/lib/queries.js +70 -141
- package/dist/lib/studio-reads.d.ts +14 -0
- package/dist/lib/studio-reads.js +574 -0
- package/dist/lib/use-project-room.js +50 -50
- package/dist/lib/use-thread.js +310 -0
- package/dist/lib/utils.js +25 -29
- package/dist/lib/view-locale-context.js +22 -0
- package/dist/lib/view-locale.js +46 -0
- package/dist/package.js +5 -0
- package/dist/studio-overlays.css +41 -151
- package/dist/studio.css +2 -2
- package/package.json +70 -73
- package/skills/camox/SKILL.md +16 -11
- package/skills/camox/references/artifacts.md +179 -0
- package/skills/camox/references/block-definitions.md +75 -59
- package/skills/camox/references/cli-common.md +9 -11
- package/skills/camox/references/cli-content.md +92 -69
- package/skills/camox/references/cli-publishing.md +26 -0
- package/skills/camox/references/dom-integrations.md +27 -0
- package/skills/camox/references/field-styling.md +4 -4
- package/skills/camox/references/layout-definitions.md +16 -14
- package/skills/camox/references/localization.md +56 -0
- package/skills/camox/references/routed-layouts.md +133 -15
- package/skills/camox-expand/SKILL.md +69 -0
- package/skills/camox-expand/references/jobs.md +39 -0
- package/skills/camoxify/SKILL.md +29 -7
- package/dist/core/components/AddBlockControlBar.js +0 -78
- package/dist/core/hooks/useRequireDraftSource.js +0 -23
- package/dist/features/metadata/sitemap.d.ts +0 -8
- package/dist/features/metadata/sitemap.js +0 -17
- package/dist/features/og/imageResponse.node.d.ts +0 -12
- package/dist/features/og/imageResponse.node.js +0 -49
- package/dist/features/og/imageResponse.workerd.d.ts +0 -12
- package/dist/features/og/imageResponse.workerd.js +0 -40
- package/dist/features/page/PublishedPageContent.js +0 -205
- package/dist/features/page/PublishedPageExperience.js +0 -23
- package/dist/features/preview/DerivedPreview.js +0 -134
- package/dist/features/preview/commentsEnabled.js +0 -8
- package/dist/features/preview/components/AddBlockSidebar.js +0 -381
- package/dist/features/preview/components/AttachedComments.js +0 -331
- package/dist/features/preview/components/CommentHeader.js +0 -122
- package/dist/features/preview/components/CommentSidebar.js +0 -29
- package/dist/features/preview/components/CommentTargetQuote.js +0 -167
- package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +0 -5
- package/dist/features/preview/components/DerivedLayoutSidebar.js +0 -179
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +0 -69
- package/dist/features/preview/components/LeftSidebar.js +0 -68
- package/dist/features/preview/components/PageEditorSidebar.js +0 -563
- package/dist/features/preview/components/PageInfoSidebar.js +0 -1551
- package/dist/features/preview/components/PageNavigatorSidebar.js +0 -78
- package/dist/features/preview/components/PageStatusBadge.js +0 -97
- package/dist/features/preview/components/PeekedBlock.js +0 -217
- package/dist/features/preview/components/PreviewComments.js +0 -56
- package/dist/features/preview/components/PreviewToolbarSpacer.js +0 -43
- package/dist/features/preview/components/PublicationRow.js +0 -422
- package/dist/features/preview/components/PublishDialog.js +0 -194
- package/dist/features/preview/components/RightSidebar.js +0 -59
- package/dist/features/preview/components/SendFeedbackDialog.js +0 -83
- package/dist/features/preview/previewCommentsStore.js +0 -135
- package/dist/features/preview/publication.js +0 -81
- package/dist/features/preview/usePageComments.js +0 -39
- package/dist/features/runtime/SharedChromeContext.js +0 -7
- package/dist/features/studio/components/EnvironmentMenu.js +0 -425
- package/dist/features/vite/appGeneration.js +0 -89
- package/dist/lib/view-queries.js +0 -28
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/Matches.d.ts +0 -114
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/RouterProvider.d.ts +0 -25
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/config.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/defer.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/fileRoute.d.ts +0 -20
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/global.d.ts +0 -8
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/hash-scroll.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/index.d.ts +0 -18
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/link.d.ts +0 -161
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/load-matches.d.ts +0 -6
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/location.d.ts +0 -54
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/lru-cache.d.ts +0 -8
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/manifest.d.ts +0 -32
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/new-process-route-tree.d.ts +0 -115
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/not-found.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/redirect.d.ts +0 -49
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/rewrite.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/root.d.ts +0 -6
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/route.d.ts +0 -343
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/routeInfo.d.ts +0 -48
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/router.d.ts +0 -695
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/scroll-restoration.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchMiddleware.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchParams.d.ts +0 -5
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/RawStream.d.ts +0 -38
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/seroval-plugins.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/transformer.d.ts +0 -65
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/stores.d.ts +0 -69
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/structuralSharing.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/typePrimitives.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderData.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderDeps.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useNavigate.d.ts +0 -10
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useParams.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useRouteContext.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useSearch.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/utils.d.ts +0 -28
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/validators.d.ts +0 -49
- package/skills/camox/references/cli-environments.md +0 -37
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { previewStore, sameEditingOwner } from "../preview/previewStore.js";
|
|
2
|
+
|
|
3
|
+
//#region src/features/studio/followAgent.ts
|
|
4
|
+
/**
|
|
5
|
+
* How long following stays on a page it went to before it leaves for another one, in
|
|
6
|
+
* milliseconds. A product tuning value: long enough to see each destination, short enough to
|
|
7
|
+
* keep up with the agent.
|
|
8
|
+
*/
|
|
9
|
+
const FOLLOW_MINIMUM_STAY = 2e3;
|
|
10
|
+
const pageRowId = (page) => page.owner.kind === "page" ? page.owner.pageId : null;
|
|
11
|
+
function findPage(where, ref) {
|
|
12
|
+
return where.pages.find((page) => "key" in ref ? page.key === ref.key : pageRowId(page) === ref.pageId);
|
|
13
|
+
}
|
|
14
|
+
/** The Page the editor is on, if any. */
|
|
15
|
+
const currentPage = (where) => where.pageKey ? where.pages.find((page) => page.key === where.pageKey) : void 0;
|
|
16
|
+
const refKey = (ref) => "key" in ref ? `key:${ref.key}` : `page:${ref.pageId}`;
|
|
17
|
+
function locate(where, here, touch) {
|
|
18
|
+
const elsewhere = !!touch.locale && touch.locale !== where.locale;
|
|
19
|
+
const keptBlock = (id) => id && !elsewhere && touch.kind !== "deleted" && touch.kind !== "settings" ? id : void 0;
|
|
20
|
+
const at = (page, blockId) => {
|
|
21
|
+
const id = keptBlock(blockId);
|
|
22
|
+
return {
|
|
23
|
+
page,
|
|
24
|
+
...id ? { blockId: id } : {}
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
if (touch.entity === "page") {
|
|
28
|
+
const shown = where.pages.some((page) => pageRowId(page) === touch.pageId);
|
|
29
|
+
if (elsewhere && !shown) return null;
|
|
30
|
+
return at({ pageId: touch.pageId }, touch.blockId);
|
|
31
|
+
}
|
|
32
|
+
if (touch.entity === "layout") {
|
|
33
|
+
const page = here?.layoutId === touch.layoutId ? here : where.pages.find((candidate) => candidate.layoutId === touch.layoutId && candidate.pathname);
|
|
34
|
+
return page ? at({ key: page.key }, touch.blockId) : null;
|
|
35
|
+
}
|
|
36
|
+
const placement = here?.blocks?.find((block) => block.type === touch.blockType);
|
|
37
|
+
if (here && placement) return at({ key: here.key }, placement.id);
|
|
38
|
+
return elsewhere ? null : { catalog: touch.blockType };
|
|
39
|
+
}
|
|
40
|
+
function destinationOf(where, batch) {
|
|
41
|
+
const here = currentPage(where);
|
|
42
|
+
const deletedPages = new Set(batch.touches.flatMap((touch) => touch.entity === "page" && touch.kind === "deleted" && !touch.blockId ? [touch.pageId] : []));
|
|
43
|
+
const located = batch.touches.filter((touch) => !(touch.entity === "page" && deletedPages.has(touch.pageId))).flatMap((touch) => {
|
|
44
|
+
const at = locate(where, here, touch);
|
|
45
|
+
return at ? [at] : [];
|
|
46
|
+
});
|
|
47
|
+
const touched = /* @__PURE__ */ new Map();
|
|
48
|
+
const identity = (ref) => {
|
|
49
|
+
const page = findPage(where, ref);
|
|
50
|
+
return page ? `key:${page.key}` : refKey(ref);
|
|
51
|
+
};
|
|
52
|
+
for (const at of located) {
|
|
53
|
+
if ("catalog" in at) continue;
|
|
54
|
+
const key = identity(at.page);
|
|
55
|
+
const entry = touched.get(key) ?? {
|
|
56
|
+
page: at.page,
|
|
57
|
+
blockIds: [],
|
|
58
|
+
count: 0
|
|
59
|
+
};
|
|
60
|
+
entry.count += 1;
|
|
61
|
+
if (at.blockId && !entry.blockIds.includes(at.blockId)) entry.blockIds.push(at.blockId);
|
|
62
|
+
touched.set(key, entry);
|
|
63
|
+
}
|
|
64
|
+
if (touched.size === 0) {
|
|
65
|
+
const catalog = located.find((at) => "catalog" in at);
|
|
66
|
+
return catalog && "catalog" in catalog ? {
|
|
67
|
+
kind: "catalog",
|
|
68
|
+
blockType: catalog.catalog
|
|
69
|
+
} : null;
|
|
70
|
+
}
|
|
71
|
+
const order = (ref) => {
|
|
72
|
+
const page = findPage(where, ref);
|
|
73
|
+
return page ? where.pages.indexOf(page) : where.pages.length;
|
|
74
|
+
};
|
|
75
|
+
const entries = [...touched.values()];
|
|
76
|
+
const chosen = (here && touched.get(`key:${here.key}`)) ?? entries.reduce((best, entry) => entry.count > best.count || entry.count === best.count && order(entry.page) < order(best.page) ? entry : best);
|
|
77
|
+
return {
|
|
78
|
+
kind: "page",
|
|
79
|
+
page: chosen.page,
|
|
80
|
+
blockIds: chosen.blockIds
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** The topmost of the touched blocks by its order on the page; ones not shown yet come last. */
|
|
84
|
+
function topmostBlock(page, blockIds) {
|
|
85
|
+
const position = (id) => {
|
|
86
|
+
const index = page.blocks?.findIndex((block) => block.id === id) ?? -1;
|
|
87
|
+
return index === -1 ? Infinity : index;
|
|
88
|
+
};
|
|
89
|
+
return [...blockIds].sort((a, b) => position(a) - position(b))[0];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Following the agent on the Canvas or in the Preview: each touched batch gives at most one
|
|
93
|
+
* destination, which the Studio goes to through the existing selection. Pages are selected
|
|
94
|
+
* through the URL, replacing the history entry, and blocks through the preview store once the
|
|
95
|
+
* destination page's editing frame is active.
|
|
96
|
+
*/
|
|
97
|
+
function createFollowAgent({ navigate, where: initial }) {
|
|
98
|
+
let where = initial;
|
|
99
|
+
let following = true;
|
|
100
|
+
/** When following last arrived on another page; it stays there for the minimum stay. */
|
|
101
|
+
let arrivedAt = -Infinity;
|
|
102
|
+
/** The latest destination on another page, waiting for the minimum stay or for its page. */
|
|
103
|
+
let pendingNavigation = null;
|
|
104
|
+
/** When the pending destination's page has to show by, once following could go there. */
|
|
105
|
+
let pendingNavigationUntil = 0;
|
|
106
|
+
let timer = null;
|
|
107
|
+
/** Blocks to select once their page's editing frame is active. */
|
|
108
|
+
let blocksToSelect = null;
|
|
109
|
+
/** The block following last selected, to move to a topmost one that shows later. */
|
|
110
|
+
let selected = null;
|
|
111
|
+
/** The block following selected last, whichever page it's on, to tell the editor's apart. */
|
|
112
|
+
let ownSelection = null;
|
|
113
|
+
/** Selects the topmost of the touched blocks on `page`, if one shows. */
|
|
114
|
+
const selectTopmost = (touched, page) => {
|
|
115
|
+
const blockId = topmostBlock(page, touched.blockIds);
|
|
116
|
+
if (!blockId) return;
|
|
117
|
+
selected = {
|
|
118
|
+
page: touched.page,
|
|
119
|
+
blockIds: touched.blockIds,
|
|
120
|
+
blockId
|
|
121
|
+
};
|
|
122
|
+
ownSelection = {
|
|
123
|
+
owner: page.owner,
|
|
124
|
+
blockId
|
|
125
|
+
};
|
|
126
|
+
previewStore.send({
|
|
127
|
+
type: "setFocusedBlock",
|
|
128
|
+
...page.owner,
|
|
129
|
+
blockId
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const selectBlocks = () => {
|
|
133
|
+
if (!blocksToSelect) return;
|
|
134
|
+
const page = findPage(where, blocksToSelect.page);
|
|
135
|
+
const { editingContext } = previewStore.getSnapshot().context;
|
|
136
|
+
if (!page || !sameEditingOwner(editingContext, page.owner)) return;
|
|
137
|
+
const touched = blocksToSelect;
|
|
138
|
+
blocksToSelect = null;
|
|
139
|
+
selectTopmost(touched, page);
|
|
140
|
+
};
|
|
141
|
+
/** Reselects when a touched block above the selected one shows, while the selection is ours. */
|
|
142
|
+
const reselectTopmost = () => {
|
|
143
|
+
if (!selected) return;
|
|
144
|
+
const page = findPage(where, selected.page);
|
|
145
|
+
const selection = previewStore.getSnapshot().context.editingContext?.selection;
|
|
146
|
+
if (!page || selection?.type !== "block" || selection.blockId !== selected.blockId) {
|
|
147
|
+
selected = null;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (topmostBlock(page, selected.blockIds) !== selected.blockId) selectTopmost(selected, page);
|
|
151
|
+
};
|
|
152
|
+
const clearTimer = () => {
|
|
153
|
+
if (timer !== null) clearTimeout(timer);
|
|
154
|
+
timer = null;
|
|
155
|
+
};
|
|
156
|
+
/** Goes to the pending destination, once the minimum stay is over and its page is known. */
|
|
157
|
+
const navigatePending = () => {
|
|
158
|
+
if (!pendingNavigation) return;
|
|
159
|
+
const wait = arrivedAt + FOLLOW_MINIMUM_STAY - Date.now();
|
|
160
|
+
if (wait > 0) {
|
|
161
|
+
timer ??= setTimeout(() => {
|
|
162
|
+
timer = null;
|
|
163
|
+
navigatePending();
|
|
164
|
+
}, wait);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (Date.now() >= pendingNavigationUntil) {
|
|
168
|
+
pendingNavigation = null;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const destination = pendingNavigation;
|
|
172
|
+
const pathname = destination.kind === "catalog" ? where.blockCatalogPath(destination.blockType) : findPage(where, destination.page)?.pathname;
|
|
173
|
+
if (!pathname) return;
|
|
174
|
+
pendingNavigation = null;
|
|
175
|
+
arrivedAt = Date.now();
|
|
176
|
+
blocksToSelect = destination.kind === "page" && destination.blockIds.length ? destination : null;
|
|
177
|
+
selected = null;
|
|
178
|
+
navigate({
|
|
179
|
+
to: `${pathname}${where.location.search}`,
|
|
180
|
+
replace: true,
|
|
181
|
+
source: "follow"
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Whether the editor selected something themselves: a selection following didn't make.
|
|
186
|
+
* Clearing it isn't one, as frames do when the Canvas mounts or a navigation releases them.
|
|
187
|
+
*/
|
|
188
|
+
const editorSelected = () => {
|
|
189
|
+
const { editingContext } = previewStore.getSnapshot().context;
|
|
190
|
+
const selection = editingContext?.selection;
|
|
191
|
+
if (!selection) return false;
|
|
192
|
+
return !(ownSelection && selection.type === "block" && selection.blockId === ownSelection.blockId && sameEditingOwner(editingContext, ownSelection.owner));
|
|
193
|
+
};
|
|
194
|
+
let lastSelection = previewStore.getSnapshot().context.editingContext?.selection ?? null;
|
|
195
|
+
const subscription = previewStore.subscribe(({ context }) => {
|
|
196
|
+
const selection = context.editingContext?.selection ?? null;
|
|
197
|
+
const changed = selection !== lastSelection;
|
|
198
|
+
lastSelection = selection;
|
|
199
|
+
if (changed && editorSelected()) {
|
|
200
|
+
follow.takeOver();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
selectBlocks();
|
|
204
|
+
});
|
|
205
|
+
const follow = {
|
|
206
|
+
receive(batch) {
|
|
207
|
+
if (!following) return;
|
|
208
|
+
const destination = destinationOf(where, batch);
|
|
209
|
+
if (!destination) return;
|
|
210
|
+
const here = currentPage(where);
|
|
211
|
+
if (destination.kind === "page" && here && findPage(where, destination.page) === here) {
|
|
212
|
+
pendingNavigation = null;
|
|
213
|
+
clearTimer();
|
|
214
|
+
if (!destination.blockIds.length) return;
|
|
215
|
+
blocksToSelect = destination;
|
|
216
|
+
selectBlocks();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
pendingNavigation = destination;
|
|
220
|
+
pendingNavigationUntil = Math.max(Date.now(), arrivedAt + FOLLOW_MINIMUM_STAY) + FOLLOW_MINIMUM_STAY;
|
|
221
|
+
navigatePending();
|
|
222
|
+
},
|
|
223
|
+
update(next) {
|
|
224
|
+
const navigated = next.location.pathname !== where.location.pathname;
|
|
225
|
+
where = next;
|
|
226
|
+
if (navigated && next.location.source === void 0) follow.takeOver();
|
|
227
|
+
navigatePending();
|
|
228
|
+
selectBlocks();
|
|
229
|
+
reselectTopmost();
|
|
230
|
+
},
|
|
231
|
+
takeOver() {
|
|
232
|
+
following = false;
|
|
233
|
+
pendingNavigation = null;
|
|
234
|
+
blocksToSelect = null;
|
|
235
|
+
selected = null;
|
|
236
|
+
clearTimer();
|
|
237
|
+
},
|
|
238
|
+
resume() {
|
|
239
|
+
following = true;
|
|
240
|
+
},
|
|
241
|
+
dispose() {
|
|
242
|
+
clearTimer();
|
|
243
|
+
subscription.unsubscribe();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
return follow;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//#endregion
|
|
250
|
+
export { FOLLOW_MINIMUM_STAY, createFollowAgent };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//#region src/features/studio/localeOptions.ts
|
|
2
|
+
const localeNames = new Intl.DisplayNames(["en"], { type: "language" });
|
|
3
|
+
/** A locale's name as the studio shows it, "German (de)", or its tag alone when unnamed. */
|
|
4
|
+
function localeLabel(tag) {
|
|
5
|
+
try {
|
|
6
|
+
const name = localeNames.of(tag);
|
|
7
|
+
return name && name !== tag ? `${name} (${tag})` : tag;
|
|
8
|
+
} catch {
|
|
9
|
+
return tag;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** The BCP 47 tags the studio offers to add: widely used languages and their main regions. */
|
|
13
|
+
const OFFERED_TAGS = [
|
|
14
|
+
"af",
|
|
15
|
+
"am",
|
|
16
|
+
"ar",
|
|
17
|
+
"az",
|
|
18
|
+
"be",
|
|
19
|
+
"bg",
|
|
20
|
+
"bn",
|
|
21
|
+
"bs",
|
|
22
|
+
"ca",
|
|
23
|
+
"cs",
|
|
24
|
+
"cy",
|
|
25
|
+
"da",
|
|
26
|
+
"de",
|
|
27
|
+
"de-AT",
|
|
28
|
+
"de-CH",
|
|
29
|
+
"el",
|
|
30
|
+
"en",
|
|
31
|
+
"en-AU",
|
|
32
|
+
"en-CA",
|
|
33
|
+
"en-GB",
|
|
34
|
+
"en-IE",
|
|
35
|
+
"en-IN",
|
|
36
|
+
"en-NZ",
|
|
37
|
+
"en-US",
|
|
38
|
+
"es",
|
|
39
|
+
"es-419",
|
|
40
|
+
"es-ES",
|
|
41
|
+
"es-MX",
|
|
42
|
+
"et",
|
|
43
|
+
"eu",
|
|
44
|
+
"fa",
|
|
45
|
+
"fi",
|
|
46
|
+
"fil",
|
|
47
|
+
"fr",
|
|
48
|
+
"fr-BE",
|
|
49
|
+
"fr-CA",
|
|
50
|
+
"fr-CH",
|
|
51
|
+
"ga",
|
|
52
|
+
"gl",
|
|
53
|
+
"gu",
|
|
54
|
+
"he",
|
|
55
|
+
"hi",
|
|
56
|
+
"hr",
|
|
57
|
+
"hu",
|
|
58
|
+
"hy",
|
|
59
|
+
"id",
|
|
60
|
+
"is",
|
|
61
|
+
"it",
|
|
62
|
+
"ja",
|
|
63
|
+
"ka",
|
|
64
|
+
"kk",
|
|
65
|
+
"km",
|
|
66
|
+
"kn",
|
|
67
|
+
"ko",
|
|
68
|
+
"lo",
|
|
69
|
+
"lt",
|
|
70
|
+
"lv",
|
|
71
|
+
"mk",
|
|
72
|
+
"ml",
|
|
73
|
+
"mn",
|
|
74
|
+
"mr",
|
|
75
|
+
"ms",
|
|
76
|
+
"mt",
|
|
77
|
+
"my",
|
|
78
|
+
"nb",
|
|
79
|
+
"ne",
|
|
80
|
+
"nl",
|
|
81
|
+
"nl-BE",
|
|
82
|
+
"pa",
|
|
83
|
+
"pl",
|
|
84
|
+
"pt",
|
|
85
|
+
"pt-BR",
|
|
86
|
+
"pt-PT",
|
|
87
|
+
"ro",
|
|
88
|
+
"ru",
|
|
89
|
+
"si",
|
|
90
|
+
"sk",
|
|
91
|
+
"sl",
|
|
92
|
+
"sq",
|
|
93
|
+
"sr",
|
|
94
|
+
"sv",
|
|
95
|
+
"sw",
|
|
96
|
+
"ta",
|
|
97
|
+
"te",
|
|
98
|
+
"th",
|
|
99
|
+
"tr",
|
|
100
|
+
"uk",
|
|
101
|
+
"ur",
|
|
102
|
+
"uz",
|
|
103
|
+
"vi",
|
|
104
|
+
"zh-Hans",
|
|
105
|
+
"zh-Hant",
|
|
106
|
+
"zu"
|
|
107
|
+
];
|
|
108
|
+
/** The locales a project can add, by name: the offered tags it doesn't have yet. */
|
|
109
|
+
function localeOptions(existing) {
|
|
110
|
+
const taken = new Set(existing.map((locale) => locale.tag.toLowerCase()));
|
|
111
|
+
return OFFERED_TAGS.filter((tag) => !taken.has(tag.toLowerCase())).map((tag) => ({
|
|
112
|
+
tag,
|
|
113
|
+
label: localeLabel(tag)
|
|
114
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
export { localeLabel, localeOptions };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { STUDIO_BASE_PATH } from "./routes.js";
|
|
2
|
+
|
|
3
|
+
//#region src/features/studio/localeSwitch.ts
|
|
4
|
+
/**
|
|
5
|
+
* The locale-relative path switching to another locale goes to from `path`. A curated page keeps
|
|
6
|
+
* its localization's path there, found by its id (ADR 0015). Studio routes and singleton pages
|
|
7
|
+
* keep their code-owned path. A derived layout's record page goes to the record's page there, as
|
|
8
|
+
* that locale's route discovery finds it. Anything else, such as a page missing from the other
|
|
9
|
+
* locale, goes to that locale's home.
|
|
10
|
+
*/
|
|
11
|
+
function pathInLocale(path, { shown, target, singleton, recordPath }) {
|
|
12
|
+
if (path === "/camox" || path.startsWith(`${"/camox"}/`) || singleton(path)) return path;
|
|
13
|
+
const page = shown.find((candidate) => candidate.fullPath === path);
|
|
14
|
+
if (page) return target.find((candidate) => candidate.id === page.id)?.fullPath ?? "/";
|
|
15
|
+
return recordPath ?? "/";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { pathInLocale };
|
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
const STUDIO_ROUTE_SEGMENT = "camox";
|
|
3
3
|
const STUDIO_BASE_PATH = `/${STUDIO_ROUTE_SEGMENT}`;
|
|
4
4
|
const STUDIO_CONTENT_PATH = `${STUDIO_BASE_PATH}/content`;
|
|
5
|
+
const STUDIO_ASSETS_PATH = `${STUDIO_CONTENT_PATH}/assets`;
|
|
6
|
+
const collectionContentPath = (collectionId) => `${STUDIO_CONTENT_PATH}/collections/${encodeURIComponent(collectionId)}`;
|
|
7
|
+
function matchCollectionContentPath(pathname) {
|
|
8
|
+
const match = /^\/camox\/content\/collections\/([^/]+)(?:(\/new)|\/([^/]+)\/edit)?$/.exec(pathname);
|
|
9
|
+
if (!match) return null;
|
|
10
|
+
try {
|
|
11
|
+
const collectionId = decodeURIComponent(match[1]);
|
|
12
|
+
if (!collectionId || collectionId.includes("/")) return null;
|
|
13
|
+
if (!match[3]) return {
|
|
14
|
+
collectionId,
|
|
15
|
+
isNew: !!match[2]
|
|
16
|
+
};
|
|
17
|
+
const itemId = decodeURIComponent(match[3]);
|
|
18
|
+
if (!itemId || itemId.includes("/")) return null;
|
|
19
|
+
return {
|
|
20
|
+
collectionId,
|
|
21
|
+
isNew: false,
|
|
22
|
+
itemId
|
|
23
|
+
};
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** The Studio URL of the Canvas with nothing selected. */
|
|
29
|
+
const STUDIO_CANVAS_PATH = `${STUDIO_BASE_PATH}/canvas`;
|
|
30
|
+
const STUDIO_BLOCKS_PATH = `${STUDIO_BASE_PATH}/blocks`;
|
|
31
|
+
/** The Studio URL of a block of the Block Catalog. */
|
|
32
|
+
const blockCatalogPath = (blockId) => `${STUDIO_BLOCKS_PATH}/${encodeURIComponent(blockId)}`;
|
|
33
|
+
/** The id of the Block Catalog block a pathname selects, if any. */
|
|
34
|
+
function matchBlockCatalogPath(pathname) {
|
|
35
|
+
const match = /^\/camox\/blocks\/([^/]+)$/.exec(pathname);
|
|
36
|
+
if (!match) return null;
|
|
37
|
+
try {
|
|
38
|
+
return decodeURIComponent(match[1]) || null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A location that only exists on the Canvas: the Canvas with
|
|
45
|
+
* nothing selected, or a block of the Block Catalog.
|
|
46
|
+
*/
|
|
47
|
+
function matchCanvasOnlyPath(pathname) {
|
|
48
|
+
if (pathname === "/camox/canvas") return {};
|
|
49
|
+
const blockId = matchBlockCatalogPath(pathname);
|
|
50
|
+
return blockId ? { blockId } : null;
|
|
51
|
+
}
|
|
5
52
|
|
|
6
53
|
//#endregion
|
|
7
|
-
export { STUDIO_BASE_PATH, STUDIO_CONTENT_PATH, STUDIO_ROUTE_SEGMENT };
|
|
54
|
+
export { STUDIO_ASSETS_PATH, STUDIO_BASE_PATH, STUDIO_BLOCKS_PATH, STUDIO_CANVAS_PATH, STUDIO_CONTENT_PATH, STUDIO_ROUTE_SEGMENT, blockCatalogPath, collectionContentPath, matchBlockCatalogPath, matchCanvasOnlyPath, matchCollectionContentPath };
|
|
@@ -4,7 +4,14 @@ import { createStore } from "@xstate/store-react";
|
|
|
4
4
|
const studioStore = createStore({
|
|
5
5
|
context: {
|
|
6
6
|
isCommandPaletteOpen: false,
|
|
7
|
-
commandPalettePages: []
|
|
7
|
+
commandPalettePages: [],
|
|
8
|
+
reviewDraftSheet: {
|
|
9
|
+
open: false,
|
|
10
|
+
startRenaming: false
|
|
11
|
+
},
|
|
12
|
+
isDiscardDraftDialogOpen: false,
|
|
13
|
+
localeDialog: null,
|
|
14
|
+
websiteLocation: null
|
|
8
15
|
},
|
|
9
16
|
on: {
|
|
10
17
|
openCommandPalette: (context) => {
|
|
@@ -38,6 +45,62 @@ const studioStore = createStore({
|
|
|
38
45
|
...context,
|
|
39
46
|
commandPalettePages: context.commandPalettePages.slice(0, -1)
|
|
40
47
|
};
|
|
48
|
+
},
|
|
49
|
+
openReviewDraftSheet: (context, event) => {
|
|
50
|
+
return {
|
|
51
|
+
...context,
|
|
52
|
+
reviewDraftSheet: {
|
|
53
|
+
open: true,
|
|
54
|
+
startRenaming: event.startRenaming ?? false
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
closeReviewDraftSheet: (context) => {
|
|
59
|
+
return {
|
|
60
|
+
...context,
|
|
61
|
+
reviewDraftSheet: {
|
|
62
|
+
open: false,
|
|
63
|
+
startRenaming: false
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
openDiscardDraftDialog: (context) => {
|
|
68
|
+
return {
|
|
69
|
+
...context,
|
|
70
|
+
isDiscardDraftDialogOpen: true
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
closeDiscardDraftDialog: (context) => {
|
|
74
|
+
return {
|
|
75
|
+
...context,
|
|
76
|
+
isDiscardDraftDialogOpen: false
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
openLocaleDialog: (context, event) => {
|
|
80
|
+
return {
|
|
81
|
+
...context,
|
|
82
|
+
localeDialog: event.dialog
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
closeLocaleDialog: (context) => {
|
|
86
|
+
return {
|
|
87
|
+
...context,
|
|
88
|
+
localeDialog: null
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
rememberWebsiteLocation: (context, event) => {
|
|
92
|
+
const previous = context.websiteLocation;
|
|
93
|
+
const { locale, path, search, hash } = event.location;
|
|
94
|
+
if (previous?.locale === locale && previous.path === path && previous.search === search && previous.hash === hash) return context;
|
|
95
|
+
return {
|
|
96
|
+
...context,
|
|
97
|
+
websiteLocation: {
|
|
98
|
+
locale,
|
|
99
|
+
path,
|
|
100
|
+
search,
|
|
101
|
+
hash
|
|
102
|
+
}
|
|
103
|
+
};
|
|
41
104
|
}
|
|
42
105
|
}
|
|
43
106
|
});
|
|
@@ -35,31 +35,32 @@ function setTheme(theme) {
|
|
|
35
35
|
applyTheme(theme);
|
|
36
36
|
notify();
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Owns the studio theme: writes the active class onto `<html>` and persists
|
|
40
|
+
* changes to localStorage. Should only be mounted from the studio chrome —
|
|
41
|
+
* never from contexts that share `<html>` with the user's site.
|
|
42
|
+
*/
|
|
38
43
|
function useApplyTheme() {
|
|
39
|
-
const $ = c(
|
|
40
|
-
if ($[0] !== "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874") {
|
|
41
|
-
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
42
|
-
$[0] = "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874";
|
|
43
|
-
}
|
|
44
|
+
const $ = c(4);
|
|
44
45
|
const theme = React.useSyncExternalStore(subscribe, readStoredTheme, _temp2);
|
|
45
46
|
const resolvedTheme = React.useSyncExternalStore(subscribe, _temp3, _temp4);
|
|
46
47
|
let t0;
|
|
47
|
-
if ($[
|
|
48
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
48
49
|
t0 = [];
|
|
49
|
-
$[
|
|
50
|
-
} else t0 = $[
|
|
50
|
+
$[0] = t0;
|
|
51
|
+
} else t0 = $[0];
|
|
51
52
|
React.useEffect(_temp7, t0);
|
|
52
53
|
let t1;
|
|
53
|
-
if ($[
|
|
54
|
+
if ($[1] !== resolvedTheme || $[2] !== theme) {
|
|
54
55
|
t1 = {
|
|
55
56
|
theme,
|
|
56
57
|
resolvedTheme,
|
|
57
58
|
setTheme
|
|
58
59
|
};
|
|
59
|
-
$[
|
|
60
|
-
$[
|
|
61
|
-
$[
|
|
62
|
-
} else t1 = $[
|
|
60
|
+
$[1] = resolvedTheme;
|
|
61
|
+
$[2] = theme;
|
|
62
|
+
$[3] = t1;
|
|
63
|
+
} else t1 = $[3];
|
|
63
64
|
return t1;
|
|
64
65
|
}
|
|
65
66
|
function _temp7() {
|
|
@@ -103,15 +104,11 @@ function _temp2() {
|
|
|
103
104
|
return "system";
|
|
104
105
|
}
|
|
105
106
|
function useThemeActions() {
|
|
106
|
-
const $ = c(
|
|
107
|
-
if ($[0] !== "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874") {
|
|
108
|
-
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
109
|
-
$[0] = "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874";
|
|
110
|
-
}
|
|
107
|
+
const $ = c(4);
|
|
111
108
|
const { theme, setTheme } = useApplyTheme();
|
|
112
109
|
let t0;
|
|
113
110
|
let t1;
|
|
114
|
-
if ($[
|
|
111
|
+
if ($[0] !== setTheme || $[1] !== theme) {
|
|
115
112
|
t0 = () => {
|
|
116
113
|
const actions = [
|
|
117
114
|
{
|
|
@@ -162,22 +159,22 @@ function useThemeActions() {
|
|
|
162
159
|
return () => {
|
|
163
160
|
actionsStore.send({
|
|
164
161
|
type: "unregisterManyActions",
|
|
165
|
-
ids: actions.map(
|
|
162
|
+
ids: actions.map(_temp10)
|
|
166
163
|
});
|
|
167
164
|
};
|
|
168
165
|
};
|
|
169
166
|
t1 = [theme, setTheme];
|
|
170
|
-
$[
|
|
171
|
-
$[
|
|
172
|
-
$[
|
|
173
|
-
$[
|
|
167
|
+
$[0] = setTheme;
|
|
168
|
+
$[1] = theme;
|
|
169
|
+
$[2] = t0;
|
|
170
|
+
$[3] = t1;
|
|
174
171
|
} else {
|
|
175
|
-
t0 = $[
|
|
176
|
-
t1 = $[
|
|
172
|
+
t0 = $[2];
|
|
173
|
+
t1 = $[3];
|
|
177
174
|
}
|
|
178
175
|
React.useEffect(t0, t1);
|
|
179
176
|
}
|
|
180
|
-
function
|
|
177
|
+
function _temp10(a) {
|
|
181
178
|
return a.id;
|
|
182
179
|
}
|
|
183
180
|
function _temp9() {}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { minifySync } from "vite-plus";
|
|
2
|
+
|
|
3
|
+
//#region src/features/vite/artifactRuntimeMinification.ts
|
|
4
|
+
/** The runtime's source module, also with the query Vite's dev server may add to it. */
|
|
5
|
+
const RUNTIME_MODULE = /[\\/]src[\\/]core[\\/]lib[\\/]artifactRuntime\.ts(\?.*)?$/;
|
|
6
|
+
const RUNTIME_EXPORT = /export const ARTIFACT_RUNTIME = `([^`]*)`;/;
|
|
7
|
+
/**
|
|
8
|
+
* Minifies the `camox` runtime in the source of `artifactRuntime.ts`. Every artifact frame inlines
|
|
9
|
+
* the runtime in its `srcDoc`, so the website's HTML carries one copy per artifact, and the SDK's
|
|
10
|
+
* bundle is otherwise left unminified. Throws when the module no longer holds the runtime as one
|
|
11
|
+
* plain template literal, rather than shipping it unminified.
|
|
12
|
+
*/
|
|
13
|
+
function minifyArtifactRuntimeModule(code) {
|
|
14
|
+
const match = RUNTIME_EXPORT.exec(code);
|
|
15
|
+
if (!match) throw new Error("artifactRuntime.ts no longer exports ARTIFACT_RUNTIME as `…`.");
|
|
16
|
+
const runtime = match[1];
|
|
17
|
+
if (runtime.includes("\\") || runtime.includes("${")) throw new Error("The artifact runtime must have no backslashes or interpolations.");
|
|
18
|
+
const { code: minified, errors } = minifySync("artifactRuntime.js", runtime);
|
|
19
|
+
if (errors.length > 0) throw new Error(`The artifact runtime failed to minify: ${errors[0].message}`);
|
|
20
|
+
return code.replace(match[0], () => `export const ARTIFACT_RUNTIME = ${JSON.stringify(minified.trim())};`);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A build `transform` that minifies the runtime's source module and leaves every other module
|
|
24
|
+
* alone. The SDK's own build applies it, and so does the `camox` Vite plugin, for apps that
|
|
25
|
+
* compile the SDK from source.
|
|
26
|
+
*/
|
|
27
|
+
function transformArtifactRuntime(code, id) {
|
|
28
|
+
if (!RUNTIME_MODULE.test(id)) return null;
|
|
29
|
+
return {
|
|
30
|
+
code: minifyArtifactRuntimeModule(code),
|
|
31
|
+
map: { mappings: "" }
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { minifyArtifactRuntimeModule, transformArtifactRuntime };
|
|
@@ -17,15 +17,15 @@ function getBlockBoilerplate(filename) {
|
|
|
17
17
|
const name = filename.replace(/\.tsx?$/, "");
|
|
18
18
|
const camelName = kebabToCamel(name);
|
|
19
19
|
const pascalName = kebabToPascal(name);
|
|
20
|
-
return `import {
|
|
20
|
+
return `import { createBlock } from "camox/createBlock";
|
|
21
21
|
|
|
22
22
|
const ${camelName} = createBlock({
|
|
23
23
|
id: "${name}",
|
|
24
24
|
title: "${kebabToTitle(name)}",
|
|
25
25
|
description: "Describe when the AI should use this block.",
|
|
26
|
-
content: {
|
|
27
|
-
title:
|
|
28
|
-
},
|
|
26
|
+
content: (field) => ({
|
|
27
|
+
title: field.string({ default: "Title" }),
|
|
28
|
+
}),
|
|
29
29
|
component: ${pascalName}Component,
|
|
30
30
|
toMarkdown: (c) => [c.title]
|
|
31
31
|
});
|
|
@@ -49,7 +49,8 @@ function watchNewBlockFiles(server) {
|
|
|
49
49
|
if (filePath.startsWith(blocksDir) && /\.tsx?$/.test(filePath) && !filePath.includes("index.")) try {
|
|
50
50
|
if (readFileSync(filePath, "utf-8").trim().length < MAX_EMPTY_BLOCK_CHARACTER_COUNT) {
|
|
51
51
|
const filename = basename(filePath);
|
|
52
|
-
|
|
52
|
+
const boilerplate = getBlockBoilerplate(filename);
|
|
53
|
+
writeFileSync(filePath, boilerplate);
|
|
53
54
|
server.config.logger.info(`[camox] Auto-filled block boilerplate: ${filename}`, { timestamp: true });
|
|
54
55
|
}
|
|
55
56
|
} catch {
|