entangle-ui 0.10.0 → 0.11.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/CHANGELOG.md +72 -0
- package/README.md +7 -5
- package/dist/esm/assets/src/components/controls/Select/{Select.css.ts.vanilla-oZnFUorL.css → Select.css.ts.vanilla-Cpu2BvWL.css} +3 -0
- package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyPanel.css.ts.vanilla-RYv_XgOu.css → PropertyPanel.css.ts.vanilla-Dpr_k5I3.css} +4 -1
- package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyRow.css.ts.vanilla-C3YZnnHb.css → PropertyRow.css.ts.vanilla-pq1Uhd2a.css} +15 -8
- package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertySection.css.ts.vanilla-DK12opZc.css → PropertySection.css.ts.vanilla-6MWWAqyd.css} +50 -32
- package/dist/esm/components/Icons/AddIcon.js.map +1 -1
- package/dist/esm/components/Icons/AiChatIcon.js.map +1 -1
- package/dist/esm/components/Icons/AiSparklesIcon.js.map +1 -1
- package/dist/esm/components/Icons/ArchiveIcon.js.map +1 -1
- package/dist/esm/components/Icons/ArrowDownIcon.js.map +1 -1
- package/dist/esm/components/Icons/ArrowLeftIcon.js.map +1 -1
- package/dist/esm/components/Icons/ArrowRightIcon.js.map +1 -1
- package/dist/esm/components/Icons/ArrowUpIcon.js.map +1 -1
- package/dist/esm/components/Icons/BookmarkIcon.js.map +1 -1
- package/dist/esm/components/Icons/BugIcon.js.map +1 -1
- package/dist/esm/components/Icons/BuildingIcon.js.map +1 -1
- package/dist/esm/components/Icons/CalendarIcon.js.map +1 -1
- package/dist/esm/components/Icons/CameraIcon.js +31 -0
- package/dist/esm/components/Icons/CameraIcon.js.map +1 -0
- package/dist/esm/components/Icons/CheckIcon.js.map +1 -1
- package/dist/esm/components/Icons/ChevronDownIcon.js.map +1 -1
- package/dist/esm/components/Icons/ChevronLeftIcon.js.map +1 -1
- package/dist/esm/components/Icons/ChevronRightIcon.js.map +1 -1
- package/dist/esm/components/Icons/ChevronUpIcon.js.map +1 -1
- package/dist/esm/components/Icons/CircleIcon.js.map +1 -1
- package/dist/esm/components/Icons/ClockIcon.js.map +1 -1
- package/dist/esm/components/Icons/CloseIcon.js.map +1 -1
- package/dist/esm/components/Icons/CloudUploadIcon.js.map +1 -1
- package/dist/esm/components/Icons/CodeIcon.js.map +1 -1
- package/dist/esm/components/Icons/CopyIcon.js.map +1 -1
- package/dist/esm/components/Icons/CubeIcon.js +31 -0
- package/dist/esm/components/Icons/CubeIcon.js.map +1 -0
- package/dist/esm/components/Icons/CutIcon.js.map +1 -1
- package/dist/esm/components/Icons/DotsHorizontalIcon.js.map +1 -1
- package/dist/esm/components/Icons/DotsVerticalIcon.js.map +1 -1
- package/dist/esm/components/Icons/DownloadIcon.js.map +1 -1
- package/dist/esm/components/Icons/EditIcon.js.map +1 -1
- package/dist/esm/components/Icons/ErrorIcon.js.map +1 -1
- package/dist/esm/components/Icons/ExternalLinkIcon.js.map +1 -1
- package/dist/esm/components/Icons/EyeDropperIcon.js.map +1 -1
- package/dist/esm/components/Icons/EyeIcon.js.map +1 -1
- package/dist/esm/components/Icons/FileTextIcon.js.map +1 -1
- package/dist/esm/components/Icons/FilterIcon.js.map +1 -1
- package/dist/esm/components/Icons/FirstIcon.js.map +1 -1
- package/dist/esm/components/Icons/FolderCogIcon.js.map +1 -1
- package/dist/esm/components/Icons/FolderIcon.js.map +1 -1
- package/dist/esm/components/Icons/FolderOpenIcon.js.map +1 -1
- package/dist/esm/components/Icons/FullscreenIcon.js.map +1 -1
- package/dist/esm/components/Icons/GitBranchIcon.js.map +1 -1
- package/dist/esm/components/Icons/GridIcon.js.map +1 -1
- package/dist/esm/components/Icons/HeartIcon.js.map +1 -1
- package/dist/esm/components/Icons/HelpIcon.js.map +1 -1
- package/dist/esm/components/Icons/HomeIcon.js.map +1 -1
- package/dist/esm/components/Icons/ImageIcon.js.map +1 -1
- package/dist/esm/components/Icons/InfoIcon.js.map +1 -1
- package/dist/esm/components/Icons/LastIcon.js.map +1 -1
- package/dist/esm/components/Icons/LinkIcon.js.map +1 -1
- package/dist/esm/components/Icons/ListIcon.js.map +1 -1
- package/dist/esm/components/Icons/LockIcon.js.map +1 -1
- package/dist/esm/components/Icons/MaximizeIcon.js.map +1 -1
- package/dist/esm/components/Icons/MenuIcon.js.map +1 -1
- package/dist/esm/components/Icons/MinimizeIcon.js.map +1 -1
- package/dist/esm/components/Icons/MinusIcon.js.map +1 -1
- package/dist/esm/components/Icons/OrbitIcon.js +31 -0
- package/dist/esm/components/Icons/OrbitIcon.js.map +1 -0
- package/dist/esm/components/Icons/PasteIcon.js.map +1 -1
- package/dist/esm/components/Icons/PauseIcon.js.map +1 -1
- package/dist/esm/components/Icons/PinIcon.js.map +1 -1
- package/dist/esm/components/Icons/PlayIcon.js.map +1 -1
- package/dist/esm/components/Icons/RedoIcon.js.map +1 -1
- package/dist/esm/components/Icons/RefreshIcon.js.map +1 -1
- package/dist/esm/components/Icons/RobotIcon.js.map +1 -1
- package/dist/esm/components/Icons/RotateIcon.js +32 -0
- package/dist/esm/components/Icons/RotateIcon.js.map +1 -0
- package/dist/esm/components/Icons/SaveIcon.js.map +1 -1
- package/dist/esm/components/Icons/SearchIcon.js.map +1 -1
- package/dist/esm/components/Icons/SendIcon.js.map +1 -1
- package/dist/esm/components/Icons/SettingsIcon.js.map +1 -1
- package/dist/esm/components/Icons/SortIcon.js.map +1 -1
- package/dist/esm/components/Icons/SpinIcon.js +32 -0
- package/dist/esm/components/Icons/SpinIcon.js.map +1 -0
- package/dist/esm/components/Icons/StarIcon.js.map +1 -1
- package/dist/esm/components/Icons/StopIcon.js.map +1 -1
- package/dist/esm/components/Icons/SuccessIcon.js.map +1 -1
- package/dist/esm/components/Icons/TagIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentAlignedIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentAutoIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentFreeIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentLinearIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentMirroredIcon.js.map +1 -1
- package/dist/esm/components/Icons/TangentStepIcon.js.map +1 -1
- package/dist/esm/components/Icons/TerminalIcon.js.map +1 -1
- package/dist/esm/components/Icons/TrashIcon.js.map +1 -1
- package/dist/esm/components/Icons/UndoIcon.js.map +1 -1
- package/dist/esm/components/Icons/UnlinkIcon.js.map +1 -1
- package/dist/esm/components/Icons/UnlockIcon.js.map +1 -1
- package/dist/esm/components/Icons/UploadIcon.js.map +1 -1
- package/dist/esm/components/Icons/UserIcon.js.map +1 -1
- package/dist/esm/components/Icons/UsersIcon.js.map +1 -1
- package/dist/esm/components/Icons/WarningIcon.js.map +1 -1
- package/dist/esm/components/Icons/ZoomFitIcon.js +32 -0
- package/dist/esm/components/Icons/ZoomFitIcon.js.map +1 -0
- package/dist/esm/components/Icons/ZoomInIcon.js.map +1 -1
- package/dist/esm/components/Icons/ZoomOutIcon.js.map +1 -1
- package/dist/esm/components/controls/CartesianPicker/CartesianPicker.js.map +1 -1
- package/dist/esm/components/controls/CartesianPicker/useCartesianInteraction.js.map +1 -1
- package/dist/esm/components/controls/CartesianPicker/useCartesianRenderer.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/AlphaSlider.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorArea.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorInputs.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorPalette.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorPicker.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorPresets.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/ColorSwatch.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/EyeDropper.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/HueSlider.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/colorUtils.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/palettes/material.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/palettes/professional.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/palettes/tailwind.js.map +1 -1
- package/dist/esm/components/controls/ColorPicker/useColor.js.map +1 -1
- package/dist/esm/components/controls/Combobox/Combobox.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/CurveCanvas.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/CurveEditor.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/CurveToolbar.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/curvePresets.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/curveUtils.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/useCurveInteraction.js.map +1 -1
- package/dist/esm/components/controls/CurveEditor/useCurveRenderer.js.map +1 -1
- package/dist/esm/components/controls/FileTree/FileTree.js +7 -1
- package/dist/esm/components/controls/FileTree/FileTree.js.map +1 -1
- package/dist/esm/components/controls/FileTree/fileTreeIcons.js.map +1 -1
- package/dist/esm/components/controls/FileTree/fileTreeLabels.js.map +1 -1
- package/dist/esm/components/controls/FileTree/useFileTreeDrop.js +1 -1
- package/dist/esm/components/controls/FileTree/useFileTreeDrop.js.map +1 -1
- package/dist/esm/components/controls/FileUploader/FileUploader.js.map +1 -1
- package/dist/esm/components/controls/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/controls/NumberInput/NumberInput.js.map +1 -1
- package/dist/esm/components/controls/NumberInput/useNumberInput.js.map +1 -1
- package/dist/esm/components/controls/Select/Select.css.js +1 -1
- package/dist/esm/components/controls/Select/Select.js +15 -7
- package/dist/esm/components/controls/Select/Select.js.map +1 -1
- package/dist/esm/components/controls/Slider/Slider.js.map +1 -1
- package/dist/esm/components/controls/TagInput/TagInput.js.map +1 -1
- package/dist/esm/components/controls/TreeView/TreeNode.js +6 -0
- package/dist/esm/components/controls/TreeView/TreeNode.js.map +1 -1
- package/dist/esm/components/controls/TreeView/TreeView.js.map +1 -1
- package/dist/esm/components/controls/TreeView/useTreeState.js.map +1 -1
- package/dist/esm/components/controls/VectorInput/VectorInput.js +6 -0
- package/dist/esm/components/controls/VectorInput/VectorInput.js.map +1 -1
- package/dist/esm/components/data/DataTable/DataTable.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowser.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserAnnouncementLive.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserBreadcrumbs.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserContext.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserContextMenu.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserRenameField.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserSidebar.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserStatusBar.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserStore.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js +6 -0
- package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/assetBrowserFilter.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/assetBrowserFormat.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/assetBrowserGeometry.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/assetBrowserKeyboard.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/assetBrowserLabels.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/slots.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetBrowserAnnouncement.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetGridKeyboardNav.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js.map +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js +1 -1
- package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatActionBar.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatAttachment.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatBubble.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js +6 -0
- package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatContextChip.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatEmptyState.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatIcons.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatInput.js +6 -0
- package/dist/esm/components/editor/ChatPanel/ChatInput.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatInputToolbar.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatMarkdownRenderer.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatMessage.js +6 -0
- package/dist/esm/components/editor/ChatPanel/ChatMessage.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatMessageList.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatPanel.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatToolCall.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatTypingIndicator.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/useChatInput.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/useChatMessages.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/useChatScroll.js.map +1 -1
- package/dist/esm/components/editor/Minimap/Minimap.js +1 -1
- package/dist/esm/components/editor/Minimap/Minimap.js.map +1 -1
- package/dist/esm/components/editor/Minimap/Minimap.types.js.map +1 -1
- package/dist/esm/components/editor/Minimap/MinimapContext.js.map +1 -1
- package/dist/esm/components/editor/Minimap/MinimapCorner.js.map +1 -1
- package/dist/esm/components/editor/Minimap/MinimapFooter.js.map +1 -1
- package/dist/esm/components/editor/Minimap/MinimapStore.js.map +1 -1
- package/dist/esm/components/editor/Minimap/MinimapTitle.js.map +1 -1
- package/dist/esm/components/editor/Minimap/ViewportMinimap.js +1 -1
- package/dist/esm/components/editor/Minimap/ViewportMinimap.js.map +1 -1
- package/dist/esm/components/editor/Minimap/computeBoundsFromItems.js.map +1 -1
- package/dist/esm/components/editor/Minimap/index.js.map +1 -1
- package/dist/esm/components/editor/Minimap/minimapCoords.js.map +1 -1
- package/dist/esm/components/editor/Minimap/minimapDrawing.js.map +1 -1
- package/dist/esm/components/editor/Minimap/minimapHitTest.js.map +1 -1
- package/dist/esm/components/editor/Minimap/useMinimapGestures.js +1 -1
- package/dist/esm/components/editor/Minimap/useMinimapGestures.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraph.js +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraph.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraph.types.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphContext.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphEdgeLabels.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphGroup.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphMinimap.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNodeContext.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNodeParts.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSectionContext.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphPin.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphPortVisual.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphSlots.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphSpawnPalette.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphStore.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/NodeGraphToolbar.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/createTypeMatchValidator.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/nodeGraphActions.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/nodeGraphDrawing.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/nodeGraphIds.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/nodeGraphMath.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/sortSlots.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useDragGesture.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraph.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraph.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js +1 -1
- package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js.map +1 -1
- package/dist/esm/components/editor/NodeGraph/useStoreSlice.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyGroup.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js +4 -3
- package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js +5 -4
- package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js +7 -6
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.js +18 -3
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js +11 -10
- package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertySection.js +29 -21
- package/dist/esm/components/editor/PropertyInspector/PropertySection.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/usePropertyUndo.js.map +1 -1
- package/dist/esm/components/editor/Timeline/Timeline.js +1 -1
- package/dist/esm/components/editor/Timeline/Timeline.js.map +1 -1
- package/dist/esm/components/editor/Timeline/Timeline.types.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineContext.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineFooter.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineMinimap.js +1 -1
- package/dist/esm/components/editor/Timeline/TimelineMinimap.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineStore.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineToolbar.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js +1 -1
- package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js.map +1 -1
- package/dist/esm/components/editor/Timeline/TimelineTrackScale.js.map +1 -1
- package/dist/esm/components/editor/Timeline/index.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineCoords.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineDrawing.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineEdits.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineHitTest.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineLayout.js.map +1 -1
- package/dist/esm/components/editor/Timeline/timelineSelection.js.map +1 -1
- package/dist/esm/components/editor/Timeline/useTimelineDraw.js +1 -1
- package/dist/esm/components/editor/Timeline/useTimelineDraw.js.map +1 -1
- package/dist/esm/components/editor/Timeline/useTimelineGestures.js +1 -1
- package/dist/esm/components/editor/Timeline/useTimelineGestures.js.map +1 -1
- package/dist/esm/components/editor/Timeline/useTimelinePlayback.js.map +1 -1
- package/dist/esm/components/editor/TransformControl/TransformControl.js.map +1 -1
- package/dist/esm/components/editor/ViewportGizmo/ViewportGizmo.js.map +1 -1
- package/dist/esm/components/editor/ViewportGizmo/gizmoMath.js.map +1 -1
- package/dist/esm/components/editor/ViewportGizmo/useGizmoInteraction.js.map +1 -1
- package/dist/esm/components/editor/ViewportGizmo/useGizmoRenderer.js.map +1 -1
- package/dist/esm/components/feedback/Alert/Alert.js.map +1 -1
- package/dist/esm/components/feedback/Alert/AlertActions.js.map +1 -1
- package/dist/esm/components/feedback/Alert/AlertDescription.js.map +1 -1
- package/dist/esm/components/feedback/Alert/AlertTitle.js.map +1 -1
- package/dist/esm/components/feedback/CommandPalette/CommandPalette.js.map +1 -1
- package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js.map +1 -1
- package/dist/esm/components/feedback/CommandPalette/useRecentItems.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/Dialog.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/DialogBody.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/DialogClose.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/DialogFooter.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/DialogHeader.js.map +1 -1
- package/dist/esm/components/feedback/Dialog/useDialogAnimation.js.map +1 -1
- package/dist/esm/components/feedback/Drawer/Drawer.js.map +1 -1
- package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js.map +1 -1
- package/dist/esm/components/feedback/EmptyState/EmptyState.js.map +1 -1
- package/dist/esm/components/feedback/LogView/LogView.js.map +1 -1
- package/dist/esm/components/feedback/LogView/LogViewBody.js.map +1 -1
- package/dist/esm/components/feedback/LogView/LogViewContext.js.map +1 -1
- package/dist/esm/components/feedback/LogView/LogViewParts.js.map +1 -1
- package/dist/esm/components/feedback/LogView/LogViewStore.js.map +1 -1
- package/dist/esm/components/feedback/LogView/logViewLabels.js.map +1 -1
- package/dist/esm/components/feedback/LogView/logViewLevels.js.map +1 -1
- package/dist/esm/components/feedback/LogView/logViewUtils.js.map +1 -1
- package/dist/esm/components/feedback/LogView/useFollowTail.js.map +1 -1
- package/dist/esm/components/feedback/LogView/useLogSelection.js.map +1 -1
- package/dist/esm/components/feedback/ProgressBar/CircularProgress.js.map +1 -1
- package/dist/esm/components/feedback/ProgressBar/ProgressBar.js.map +1 -1
- package/dist/esm/components/feedback/Skeleton/Skeleton.js.map +1 -1
- package/dist/esm/components/feedback/Skeleton/SkeletonGroup.js.map +1 -1
- package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js.map +1 -1
- package/dist/esm/components/feedback/Spinner/Spinner.js.map +1 -1
- package/dist/esm/components/feedback/Stat/Stat.js.map +1 -1
- package/dist/esm/components/feedback/Toast/ToastContainer.js.map +1 -1
- package/dist/esm/components/feedback/Toast/ToastItem.js.map +1 -1
- package/dist/esm/components/feedback/Toast/ToastProvider.js.map +1 -1
- package/dist/esm/components/feedback/Toast/useToast.js.map +1 -1
- package/dist/esm/components/form/FormHelperText.js.map +1 -1
- package/dist/esm/components/form/FormLabel.js.map +1 -1
- package/dist/esm/components/form/InputWrapper.js.map +1 -1
- package/dist/esm/components/layout/Accordion/Accordion.js.map +1 -1
- package/dist/esm/components/layout/Accordion/AccordionContent.js.map +1 -1
- package/dist/esm/components/layout/Accordion/AccordionItem.js.map +1 -1
- package/dist/esm/components/layout/Accordion/AccordionTrigger.js.map +1 -1
- package/dist/esm/components/layout/Card/Card.js.map +1 -1
- package/dist/esm/components/layout/Divider/Divider.js.map +1 -1
- package/dist/esm/components/layout/Flex/Flex.js.map +1 -1
- package/dist/esm/components/layout/Grid/Grid.js.map +1 -1
- package/dist/esm/components/layout/ListItem/ListItem.js.map +1 -1
- package/dist/esm/components/layout/PageHeader/PageHeader.js.map +1 -1
- package/dist/esm/components/layout/PanelSurface/PanelSurface.js.map +1 -1
- package/dist/esm/components/layout/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/esm/components/layout/Spacer/Spacer.js.map +1 -1
- package/dist/esm/components/layout/SplitPane/SplitPane.js.map +1 -1
- package/dist/esm/components/layout/SplitPane/SplitPanePanel.js.map +1 -1
- package/dist/esm/components/layout/Stack/Stack.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbSeparator.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js +6 -0
- package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/esm/components/navigation/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/esm/components/navigation/Menu/Menu.js.map +1 -1
- package/dist/esm/components/navigation/Menu/MenuGapContext.js.map +1 -1
- package/dist/esm/components/navigation/Pagination/Pagination.js.map +1 -1
- package/dist/esm/components/navigation/Pagination/usePagination.js.map +1 -1
- package/dist/esm/components/navigation/PathBar/PathBar.js +7 -1
- package/dist/esm/components/navigation/PathBar/PathBar.js.map +1 -1
- package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js +6 -0
- package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js.map +1 -1
- package/dist/esm/components/navigation/PathBar/pathUtils.js.map +1 -1
- package/dist/esm/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/esm/components/navigation/SegmentedControl/SegmentedControlItem.js.map +1 -1
- package/dist/esm/components/navigation/Tabs/Tab.js.map +1 -1
- package/dist/esm/components/navigation/Tabs/TabList.js.map +1 -1
- package/dist/esm/components/navigation/Tabs/TabPanel.js.map +1 -1
- package/dist/esm/components/navigation/Tabs/Tabs.js.map +1 -1
- package/dist/esm/components/primitives/Avatar/Avatar.js +6 -0
- package/dist/esm/components/primitives/Avatar/Avatar.js.map +1 -1
- package/dist/esm/components/primitives/Avatar/AvatarGroup.js.map +1 -1
- package/dist/esm/components/primitives/Badge/Badge.js +6 -0
- package/dist/esm/components/primitives/Badge/Badge.js.map +1 -1
- package/dist/esm/components/primitives/Button/Button.js.map +1 -1
- package/dist/esm/components/primitives/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/components/primitives/Checkbox/CheckboxGroup.js.map +1 -1
- package/dist/esm/components/primitives/Code/Code.js.map +1 -1
- package/dist/esm/components/primitives/Collapsible/Collapsible.js.map +1 -1
- package/dist/esm/components/primitives/HoverCard/HoverCard.js.map +1 -1
- package/dist/esm/components/primitives/Icon/Icon.js.map +1 -1
- package/dist/esm/components/primitives/IconButton/IconButton.js.map +1 -1
- package/dist/esm/components/primitives/Input/Input.js.map +1 -1
- package/dist/esm/components/primitives/Kbd/Kbd.js.map +1 -1
- package/dist/esm/components/primitives/Link/Link.js.map +1 -1
- package/dist/esm/components/primitives/Paper/Paper.js.map +1 -1
- package/dist/esm/components/primitives/Popover/Popover.js.map +1 -1
- package/dist/esm/components/primitives/Popover/PopoverClose.js.map +1 -1
- package/dist/esm/components/primitives/Popover/PopoverContent.js.map +1 -1
- package/dist/esm/components/primitives/Popover/PopoverTrigger.js.map +1 -1
- package/dist/esm/components/primitives/Radio/Radio.js.map +1 -1
- package/dist/esm/components/primitives/Radio/RadioGroup.js.map +1 -1
- package/dist/esm/components/primitives/Switch/Switch.js.map +1 -1
- package/dist/esm/components/primitives/Text/Text.js.map +1 -1
- package/dist/esm/components/primitives/TextArea/TextArea.js.map +1 -1
- package/dist/esm/components/primitives/Tooltip/Arrow.js.map +1 -1
- package/dist/esm/components/primitives/Tooltip/Tooltip.js.map +1 -1
- package/dist/esm/components/primitives/Tooltip/utils.js.map +1 -1
- package/dist/esm/components/primitives/VisuallyHidden/VisuallyHidden.js.map +1 -1
- package/dist/esm/components/primitives/canvas/CanvasContainer.js.map +1 -1
- package/dist/esm/components/primitives/canvas/canvasCoords.js.map +1 -1
- package/dist/esm/components/primitives/canvas/canvasDrawing.js.map +1 -1
- package/dist/esm/components/primitives/canvas/canvasTheme.js.map +1 -1
- package/dist/esm/components/primitives/canvas/useCanvasRenderer.js.map +1 -1
- package/dist/esm/components/primitives/viewport/Viewport.js +1 -1
- package/dist/esm/components/primitives/viewport/Viewport.js.map +1 -1
- package/dist/esm/components/primitives/viewport/ViewportContext.js.map +1 -1
- package/dist/esm/components/primitives/viewport/ViewportLayer.js +1 -1
- package/dist/esm/components/primitives/viewport/ViewportLayer.js.map +1 -1
- package/dist/esm/components/primitives/viewport/ViewportOverlay.js.map +1 -1
- package/dist/esm/components/primitives/viewport/ViewportStore.js.map +1 -1
- package/dist/esm/components/primitives/viewport/ViewportWorld.js.map +1 -1
- package/dist/esm/components/primitives/viewport/useViewportGestures.js +1 -1
- package/dist/esm/components/primitives/viewport/useViewportGestures.js.map +1 -1
- package/dist/esm/components/primitives/viewport/viewportCoords.js.map +1 -1
- package/dist/esm/components/primitives/viewport/viewportMath.js.map +1 -1
- package/dist/esm/components/shell/AppShell/AppShell.js.map +1 -1
- package/dist/esm/components/shell/FloatingPanel/FloatingPanel.js.map +1 -1
- package/dist/esm/components/shell/MenuBar/MenuBar.js.map +1 -1
- package/dist/esm/components/shell/StatusBar/StatusBar.js.map +1 -1
- package/dist/esm/components/shell/Toolbar/Toolbar.js.map +1 -1
- package/dist/esm/context/KeyboardContext.js.map +1 -1
- package/dist/esm/hooks/useBreakpoint/useBreakpoint.js.map +1 -1
- package/dist/esm/hooks/useClickOutside/useClickOutside.js.map +1 -1
- package/dist/esm/hooks/useClipboard/useClipboard.js.map +1 -1
- package/dist/esm/hooks/useControlledState/useControlledState.js.map +1 -1
- package/dist/esm/hooks/useDebounced/useDebouncedCallback.js.map +1 -1
- package/dist/esm/hooks/useDebounced/useDebouncedValue.js.map +1 -1
- package/dist/esm/hooks/useDisclosure/useDisclosure.js.map +1 -1
- package/dist/esm/hooks/useEventCallback/useEventCallback.js.map +1 -1
- package/dist/esm/hooks/useFocusTrap/useFocusTrap.js.map +1 -1
- package/dist/esm/hooks/useHotkey/useHotkey.js.map +1 -1
- package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js.map +1 -1
- package/dist/esm/hooks/useIsMounted/useIsMounted.js.map +1 -1
- package/dist/esm/hooks/useKeyboard/useKeyboard.js.map +1 -1
- package/dist/esm/hooks/useKeyboard/utils.js.map +1 -1
- package/dist/esm/hooks/useLatest/useLatest.js.map +1 -1
- package/dist/esm/hooks/useListboxNav/useListboxNav.js.map +1 -1
- package/dist/esm/hooks/useMediaQuery/useMediaQuery.js.map +1 -1
- package/dist/esm/hooks/useMergedRef/useMergedRef.js.map +1 -1
- package/dist/esm/hooks/useNavigationHistory/useNavigationHistory.js.map +1 -1
- package/dist/esm/hooks/useResizeObserver/useResizeObserver.js.map +1 -1
- package/dist/esm/hooks/useTheme/useTheme.js +1 -1
- package/dist/esm/hooks/useTheme/useTheme.js.map +1 -1
- package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/esm/styles.js +3 -0
- package/dist/esm/styles.js.map +1 -0
- package/dist/esm/theme/ThemeProvider.js +5 -3
- package/dist/esm/theme/ThemeProvider.js.map +1 -1
- package/dist/esm/theme/VanillaThemeProvider.js.map +1 -1
- package/dist/esm/theme/breakpoints.js.map +1 -1
- package/dist/esm/theme/createCustomTheme.js +1 -1
- package/dist/esm/theme/createCustomTheme.js.map +1 -1
- package/dist/esm/theme/createLightTheme.js.map +1 -1
- package/dist/esm/theme/darkThemeValues.js.map +1 -1
- package/dist/esm/theme/lightThemeValues.js.map +1 -1
- package/dist/esm/theme/themeContractData.js.map +1 -1
- package/dist/esm/utils/cx.js.map +1 -1
- package/dist/esm/utils/devWarn.js.map +1 -1
- package/dist/esm/utils/mathExpression.js.map +1 -1
- package/dist/esm/utils/mathUtils.js.map +1 -1
- package/dist/esm/utils/objects.js.map +1 -1
- package/dist/esm/utils/platform.js.map +1 -1
- package/dist/tokens/tokens.dark.css +1 -1
- package/dist/tokens/tokens.json +1 -1
- package/dist/tokens/tokens.light.css +1 -1
- package/dist/types/components/Icons/CameraIcon.d.ts +34 -0
- package/dist/types/components/Icons/CubeIcon.d.ts +34 -0
- package/dist/types/components/Icons/OrbitIcon.d.ts +34 -0
- package/dist/types/components/Icons/RotateIcon.d.ts +35 -0
- package/dist/types/components/Icons/SpinIcon.d.ts +35 -0
- package/dist/types/components/Icons/ZoomFitIcon.d.ts +35 -0
- package/dist/types/components/controls/Select/Select.d.ts +1 -1
- package/dist/types/components/controls/Select/Select.types.d.ts +43 -9
- package/dist/types/components/editor/PropertyInspector/PropertyInspector.types.d.ts +49 -3
- package/dist/types/components/primitives/Button/Button.d.ts +1 -1
- package/dist/types/components/primitives/IconButton/IconButton.d.ts +1 -1
- package/dist/types/index.d.ts +6 -0
- package/dist/types/theme/ThemeProvider.d.ts +5 -3
- package/package.json +6 -2
- package/dist/esm/_virtual/_commonjsHelpers.js +0 -6
- package/dist/esm/_virtual/_commonjsHelpers.js.map +0 -1
- package/dist/esm/_virtual/cjs.js +0 -4
- package/dist/esm/_virtual/cjs.js.map +0 -1
- package/dist/esm/_virtual/cssesc.js +0 -8
- package/dist/esm/_virtual/cssesc.js.map +0 -1
- package/dist/esm/_virtual/picocolors.js +0 -8
- package/dist/esm/_virtual/picocolors.js.map +0 -1
- package/dist/esm/_virtual/picocolors2.js +0 -4
- package/dist/esm/_virtual/picocolors2.js.map +0 -1
- package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js +0 -56
- package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js +0 -46
- package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js +0 -13
- package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js +0 -962
- package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js +0 -309
- package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js +0 -18
- package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js +0 -23
- package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js +0 -1543
- package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js.map +0 -1
- package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js +0 -38
- package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js.map +0 -1
- package/dist/esm/node_modules/css-what/lib/es/parse.js +0 -424
- package/dist/esm/node_modules/css-what/lib/es/parse.js.map +0 -1
- package/dist/esm/node_modules/css-what/lib/es/types.js +0 -29
- package/dist/esm/node_modules/css-what/lib/es/types.js.map +0 -1
- package/dist/esm/node_modules/cssesc/cssesc.js +0 -120
- package/dist/esm/node_modules/cssesc/cssesc.js.map +0 -1
- package/dist/esm/node_modules/dedent/dist/dedent.js +0 -100
- package/dist/esm/node_modules/dedent/dist/dedent.js.map +0 -1
- package/dist/esm/node_modules/deep-object-diff/mjs/diff.js +0 -40
- package/dist/esm/node_modules/deep-object-diff/mjs/diff.js.map +0 -1
- package/dist/esm/node_modules/deep-object-diff/mjs/utils.js +0 -9
- package/dist/esm/node_modules/deep-object-diff/mjs/utils.js.map +0 -1
- package/dist/esm/node_modules/deepmerge/dist/cjs.js +0 -143
- package/dist/esm/node_modules/deepmerge/dist/cjs.js.map +0 -1
- package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js +0 -1386
- package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js.map +0 -1
- package/dist/esm/node_modules/modern-ahocorasick/dist/index.js +0 -102
- package/dist/esm/node_modules/modern-ahocorasick/dist/index.js.map +0 -1
- package/dist/esm/node_modules/picocolors/picocolors.js +0 -87
- package/dist/esm/node_modules/picocolors/picocolors.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetBrowserFilter.js","sources":["
|
|
1
|
+
{"version":3,"file":"assetBrowserFilter.js","sources":["src/components/editor/AssetBrowser/assetBrowserFilter.ts"],"sourcesContent":["import type {\n AssetFilterState,\n AssetItem,\n AssetSortState,\n} from './AssetBrowser.types';\n\n/** Case-insensitive name match. An empty/blank query keeps every item. */\nexport function filterBySearch(\n items: readonly AssetItem[],\n query: string\n): AssetItem[] {\n const q = query.trim().toLowerCase();\n if (q === '') return items.slice();\n return items.filter(item => item.name.toLowerCase().includes(q));\n}\n\n/**\n * Type filter. Folders always pass (they have no asset type and must stay\n * navigable). An empty/undefined `types` list keeps every item.\n */\nexport function filterByType(\n items: readonly AssetItem[],\n types: readonly string[] | undefined\n): AssetItem[] {\n if (!types || types.length === 0) return items.slice();\n const set = new Set(types);\n return items.filter(\n item => item.kind === 'folder' || set.has(item.assetType ?? 'unknown')\n );\n}\n\nfunction toTime(value: number | Date | undefined): number {\n if (value === undefined) return Number.NEGATIVE_INFINITY;\n return value instanceof Date ? value.getTime() : value;\n}\n\nfunction compareField(a: AssetItem, b: AssetItem, field: string): number {\n switch (field) {\n case 'name':\n return a.name.localeCompare(b.name);\n case 'type':\n return (a.assetType ?? '').localeCompare(b.assetType ?? '');\n case 'size':\n return (a.size ?? 0) - (b.size ?? 0);\n case 'modified':\n return toTime(a.modifiedAt) - toTime(b.modifiedAt);\n default: {\n const av = a.meta?.[field];\n const bv = b.meta?.[field];\n if (typeof av === 'number' && typeof bv === 'number') return av - bv;\n const as = typeof av === 'string' ? av : '';\n const bs = typeof bv === 'string' ? bv : '';\n return as.localeCompare(bs);\n }\n }\n}\n\n/**\n * Sort a stable copy. Folders always group before files; within a group the\n * chosen field + direction applies. Name is the tiebreaker for equal fields.\n */\nexport function sortItems(\n items: readonly AssetItem[],\n sort: AssetSortState\n): AssetItem[] {\n const dir = sort.direction === 'desc' ? -1 : 1;\n return items.slice().sort((a, b) => {\n if (a.kind !== b.kind) return a.kind === 'folder' ? -1 : 1;\n const primary = compareField(a, b, sort.field);\n if (primary !== 0) return primary * dir;\n return a.name.localeCompare(b.name) * dir;\n });\n}\n\nexport interface ShapeAssetsOptions {\n search: string;\n filters: AssetFilterState;\n sort: AssetSortState;\n manualSearch: boolean;\n manualFilter: boolean;\n manualSort: boolean;\n}\n\n/**\n * Apply the non-manual axes (search → filter → sort) to produce the displayed\n * list. Manual axes trust `items` as already shaped for that axis.\n */\nexport function shapeAssets(\n items: readonly AssetItem[],\n options: ShapeAssetsOptions\n): AssetItem[] {\n let result: AssetItem[] = items.slice();\n if (!options.manualSearch) result = filterBySearch(result, options.search);\n if (!options.manualFilter)\n result = filterByType(result, options.filters.types);\n if (!options.manualSort) result = sortItems(result, options.sort);\n return result;\n}\n\n/** Distinct asset types present among files, in first-seen order. */\nexport function collectTypes(items: readonly AssetItem[]): string[] {\n const seen: string[] = [];\n const set = new Set<string>();\n for (const item of items) {\n if (item.kind !== 'file') continue;\n const type = item.assetType ?? 'unknown';\n if (!set.has(type)) {\n set.add(type);\n seen.push(type);\n }\n }\n return seen;\n}\n"],"names":[],"mappings":"AAMA;AACM,SAAU,cAAc,CAC5B,KAA2B,EAC3B,KAAa,EAAA;IAEb,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;IACpC,IAAI,CAAC,KAAK,EAAE;AAAE,QAAA,OAAO,KAAK,CAAC,KAAK,EAAE;IAClC,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClE;AAEA;;;AAGG;AACG,SAAU,YAAY,CAC1B,KAA2B,EAC3B,KAAoC,EAAA;AAEpC,IAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK,CAAC,KAAK,EAAE;AACtD,IAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC;IAC1B,OAAO,KAAK,CAAC,MAAM,CACjB,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,CACvE;AACH;AAEA,SAAS,MAAM,CAAC,KAAgC,EAAA;IAC9C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,iBAAiB;AACxD,IAAA,OAAO,KAAK,YAAY,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,KAAK;AACxD;AAEA,SAAS,YAAY,CAAC,CAAY,EAAE,CAAY,EAAE,KAAa,EAAA;IAC7D,QAAQ,KAAK;AACX,QAAA,KAAK,MAAM;YACT,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,QAAA,KAAK,MAAM;AACT,YAAA,OAAO,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC;AAC7D,QAAA,KAAK,MAAM;AACT,YAAA,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACtC,QAAA,KAAK,UAAU;AACb,YAAA,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;QACpD,SAAS;YACP,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;YAC1B,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;YAC1B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,OAAO,EAAE,GAAG,EAAE;AACpE,YAAA,MAAM,EAAE,GAAG,OAAO,EAAE,KAAK,QAAQ,GAAG,EAAE,GAAG,EAAE;AAC3C,YAAA,MAAM,EAAE,GAAG,OAAO,EAAE,KAAK,QAAQ,GAAG,EAAE,GAAG,EAAE;AAC3C,YAAA,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7B;;AAEJ;AAEA;;;AAGG;AACG,SAAU,SAAS,CACvB,KAA2B,EAC3B,IAAoB,EAAA;AAEpB,IAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC;AAC9C,IAAA,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;AACjC,QAAA,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;AAAE,YAAA,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,GAAG,EAAE,GAAG,CAAC;AAC1D,QAAA,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;QAC9C,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,OAAO,GAAG,GAAG;AACvC,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG;AAC3C,IAAA,CAAC,CAAC;AACJ;AAWA;;;AAGG;AACG,SAAU,WAAW,CACzB,KAA2B,EAC3B,OAA2B,EAAA;AAE3B,IAAA,IAAI,MAAM,GAAgB,KAAK,CAAC,KAAK,EAAE;IACvC,IAAI,CAAC,OAAO,CAAC,YAAY;QAAE,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;IAC1E,IAAI,CAAC,OAAO,CAAC,YAAY;QACvB,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IACtD,IAAI,CAAC,OAAO,CAAC,UAAU;QAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;AACjE,IAAA,OAAO,MAAM;AACf;AAEA;AACM,SAAU,YAAY,CAAC,KAA2B,EAAA;IACtD,MAAM,IAAI,GAAa,EAAE;AACzB,IAAA,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU;AAC7B,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE;AAC1B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAClB,YAAA,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AACb,YAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACjB;IACF;AACA,IAAA,OAAO,IAAI;AACb;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetBrowserFormat.js","sources":["
|
|
1
|
+
{"version":3,"file":"assetBrowserFormat.js","sources":["src/components/editor/AssetBrowser/assetBrowserFormat.ts"],"sourcesContent":["/** Humanize a byte count (e.g. 2048 → \"2 KB\"). Empty for undefined. */\nexport function formatBytes(bytes: number | undefined): string {\n if (bytes === undefined || Number.isNaN(bytes)) return '';\n if (bytes < 1024) return `${bytes} B`;\n const units = ['KB', 'MB', 'GB', 'TB'];\n let value = bytes / 1024;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n const rounded = value >= 10 ? Math.round(value) : Math.round(value * 10) / 10;\n return `${rounded} ${units[unit]}`;\n}\n\n/** Short locale date string. Empty for undefined. */\nexport function formatDate(value: number | Date | undefined): string {\n if (value === undefined) return '';\n const date = value instanceof Date ? value : new Date(value);\n if (Number.isNaN(date.getTime())) return '';\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n}\n"],"names":[],"mappings":"AAAA;AACM,SAAU,WAAW,CAAC,KAAyB,EAAA;IACnD,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,EAAE;IACzD,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,CAAA,EAAG,KAAK,CAAA,EAAA,CAAI;IACrC,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;AACtC,IAAA,IAAI,KAAK,GAAG,KAAK,GAAG,IAAI;IACxB,IAAI,IAAI,GAAG,CAAC;AACZ,IAAA,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QAC/C,KAAK,IAAI,IAAI;QACb,IAAI,IAAI,CAAC;IACX;IACA,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE;IAC7E,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,KAAK,CAAC,IAAI,CAAC,EAAE;AACpC;AAEA;AACM,SAAU,UAAU,CAAC,KAAgC,EAAA;IACzD,IAAI,KAAK,KAAK,SAAS;AAAE,QAAA,OAAO,EAAE;AAClC,IAAA,MAAM,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;IAC5D,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;AAAE,QAAA,OAAO,EAAE;AAC3C,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE;AACxC,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,GAAG,EAAE,SAAS;AACf,KAAA,CAAC;AACJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetBrowserGeometry.js","sources":["
|
|
1
|
+
{"version":3,"file":"assetBrowserGeometry.js","sources":["src/components/editor/AssetBrowser/assetBrowserGeometry.ts"],"sourcesContent":["import type { AssetThumbnailSize } from './AssetBrowser.types';\nimport type { MarqueeRect } from './AssetBrowserStore';\n\n/** Thumbnail edge length (px) for the named scales. */\nexport const THUMB_PX: Record<'sm' | 'md' | 'lg', number> = {\n sm: 72,\n md: 104,\n lg: 144,\n};\n\nexport const CELL_PADDING = 6;\nexport const LABEL_HEIGHT = 32;\nexport const GRID_GAP = 8;\n\nexport function resolveThumbPx(size: AssetThumbnailSize): number {\n if (typeof size === 'number') return Math.max(32, size);\n return THUMB_PX[size];\n}\n\nexport function cellWidth(thumbPx: number): number {\n return thumbPx + CELL_PADDING * 2 + 2; // + border\n}\n\nexport function cellHeight(thumbPx: number): number {\n return thumbPx + CELL_PADDING * 2 + LABEL_HEIGHT + 2;\n}\n\nexport function rowHeight(thumbPx: number): number {\n return cellHeight(thumbPx) + GRID_GAP;\n}\n\n/** How many columns fit in `width` px of usable (padding-excluded) space. */\nexport function columnsFor(width: number, thumbPx: number): number {\n if (width <= 0) return 1;\n const stride = cellWidth(thumbPx) + GRID_GAP;\n return Math.max(1, Math.floor((width + GRID_GAP) / stride));\n}\n\n/** Content-space rectangle of the item at `index` for a given column count. */\nexport function itemRect(\n index: number,\n columns: number,\n thumbPx: number\n): MarqueeRect {\n const cols = Math.max(1, columns);\n const col = index % cols;\n const row = Math.floor(index / cols);\n const stride = cellWidth(thumbPx) + GRID_GAP;\n return {\n x: col * stride,\n y: row * rowHeight(thumbPx),\n width: cellWidth(thumbPx),\n height: cellHeight(thumbPx),\n };\n}\n\nexport function rectsIntersect(a: MarqueeRect, b: MarqueeRect): boolean {\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\n/**\n * Stable DOM id for a grid cell, namespaced by the grid's `useId`. Used to\n * wire the grid's `aria-activedescendant` to the roving-focus cell. CSS.escape\n * is unnecessary — this is set on the element's `id`/attribute as a raw value,\n * never used in a selector.\n */\nexport function cellDomId(gridId: string, assetId: string): string {\n return `${gridId}-cell-${assetId}`;\n}\n\n/** Normalize two content-space points into a positive-size rectangle. */\nexport function rectFromPoints(\n ax: number,\n ay: number,\n bx: number,\n by: number\n): MarqueeRect {\n return {\n x: Math.min(ax, bx),\n y: Math.min(ay, by),\n width: Math.abs(ax - bx),\n height: Math.abs(ay - by),\n };\n}\n"],"names":[],"mappings":"AAGA;AACO,MAAM,QAAQ,GAAuC;AAC1D,IAAA,EAAE,EAAE,EAAE;AACN,IAAA,EAAE,EAAE,GAAG;AACP,IAAA,EAAE,EAAE,GAAG;;AAGF,MAAM,YAAY,GAAG;AACrB,MAAM,YAAY,GAAG;AACrB,MAAM,QAAQ,GAAG;AAElB,SAAU,cAAc,CAAC,IAAwB,EAAA;IACrD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC;AACvD,IAAA,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB;AAEM,SAAU,SAAS,CAAC,OAAe,EAAA;IACvC,OAAO,OAAO,GAAG,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC;AACxC;AAEM,SAAU,UAAU,CAAC,OAAe,EAAA;IACxC,OAAO,OAAO,GAAG,YAAY,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC;AACtD;AAEM,SAAU,SAAS,CAAC,OAAe,EAAA;AACvC,IAAA,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,QAAQ;AACvC;AAEA;AACM,SAAU,UAAU,CAAC,KAAa,EAAE,OAAe,EAAA;IACvD,IAAI,KAAK,IAAI,CAAC;AAAE,QAAA,OAAO,CAAC;IACxB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,QAAQ;AAC5C,IAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,QAAQ,IAAI,MAAM,CAAC,CAAC;AAC7D;AAEA;SACgB,QAAQ,CACtB,KAAa,EACb,OAAe,EACf,OAAe,EAAA;IAEf,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;AACjC,IAAA,MAAM,GAAG,GAAG,KAAK,GAAG,IAAI;IACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IACpC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,QAAQ;IAC5C,OAAO;QACL,CAAC,EAAE,GAAG,GAAG,MAAM;AACf,QAAA,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC;AAC3B,QAAA,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC;AACzB,QAAA,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC;KAC5B;AACH;AAEM,SAAU,cAAc,CAAC,CAAc,EAAE,CAAc,EAAA;IAC3D,QACE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK;QACnB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM;QACpB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAExB;AAEA;;;;;AAKG;AACG,SAAU,SAAS,CAAC,MAAc,EAAE,OAAe,EAAA;AACvD,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,MAAA,EAAS,OAAO,EAAE;AACpC;AAEA;AACM,SAAU,cAAc,CAC5B,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EAAA;IAEV,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;QACnB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;QACnB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;QACxB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;KAC1B;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetBrowserKeyboard.js","sources":["
|
|
1
|
+
{"version":3,"file":"assetBrowserKeyboard.js","sources":["src/components/editor/AssetBrowser/assetBrowserKeyboard.ts"],"sourcesContent":["export interface GridNavParams {\n /** Number of columns currently laid out. */\n columns: number;\n /** Total item count. */\n count: number;\n /** Rows that fit in one viewport — used by PageUp/PageDown. */\n rowsPerPage: number;\n}\n\n/**\n * Pure 2D grid keyboard navigation. Given the focused index and a key, return\n * the next index. Returns the clamped target, or the original index when the\n * key is not a navigation key or the move would leave the grid.\n */\nexport function nextGridIndex(\n current: number,\n key: string,\n params: GridNavParams\n): number {\n const { count } = params;\n if (count === 0) return -1;\n\n const columns = Math.max(1, params.columns);\n const rowsPerPage = Math.max(1, params.rowsPerPage);\n const last = count - 1;\n const clamp = (n: number): number => Math.min(last, Math.max(0, n));\n\n // Starting from \"nothing focused\", any nav key lands on the first item.\n if (current < 0) {\n switch (key) {\n case 'ArrowRight':\n case 'ArrowDown':\n case 'ArrowLeft':\n case 'ArrowUp':\n case 'Home':\n case 'PageUp':\n return 0;\n case 'End':\n case 'PageDown':\n return last;\n default:\n return current;\n }\n }\n\n switch (key) {\n case 'ArrowRight':\n return current < last ? current + 1 : current;\n case 'ArrowLeft':\n return current > 0 ? current - 1 : current;\n case 'ArrowDown': {\n const target = current + columns;\n return target <= last ? target : current;\n }\n case 'ArrowUp': {\n const target = current - columns;\n return target >= 0 ? target : current;\n }\n case 'Home':\n return 0;\n case 'End':\n return last;\n case 'PageDown':\n return clamp(current + columns * rowsPerPage);\n case 'PageUp':\n return clamp(current - columns * rowsPerPage);\n default:\n return current;\n }\n}\n\n/** Inclusive index range between two indices, regardless of order. */\nexport function indexRange(a: number, b: number): [number, number] {\n return a <= b ? [a, b] : [b, a];\n}\n"],"names":[],"mappings":"AASA;;;;AAIG;SACa,aAAa,CAC3B,OAAe,EACf,GAAW,EACX,MAAqB,EAAA;AAErB,IAAA,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM;IACxB,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE;AAE1B,IAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;AAC3C,IAAA,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;AACnD,IAAA,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC;IACtB,MAAM,KAAK,GAAG,CAAC,CAAS,KAAa,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;AAGnE,IAAA,IAAI,OAAO,GAAG,CAAC,EAAE;QACf,QAAQ,GAAG;AACT,YAAA,KAAK,YAAY;AACjB,YAAA,KAAK,WAAW;AAChB,YAAA,KAAK,WAAW;AAChB,YAAA,KAAK,SAAS;AACd,YAAA,KAAK,MAAM;AACX,YAAA,KAAK,QAAQ;AACX,gBAAA,OAAO,CAAC;AACV,YAAA,KAAK,KAAK;AACV,YAAA,KAAK,UAAU;AACb,gBAAA,OAAO,IAAI;AACb,YAAA;AACE,gBAAA,OAAO,OAAO;;IAEpB;IAEA,QAAQ,GAAG;AACT,QAAA,KAAK,YAAY;AACf,YAAA,OAAO,OAAO,GAAG,IAAI,GAAG,OAAO,GAAG,CAAC,GAAG,OAAO;AAC/C,QAAA,KAAK,WAAW;AACd,YAAA,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,GAAG,OAAO;QAC5C,KAAK,WAAW,EAAE;AAChB,YAAA,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO;YAChC,OAAO,MAAM,IAAI,IAAI,GAAG,MAAM,GAAG,OAAO;QAC1C;QACA,KAAK,SAAS,EAAE;AACd,YAAA,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO;YAChC,OAAO,MAAM,IAAI,CAAC,GAAG,MAAM,GAAG,OAAO;QACvC;AACA,QAAA,KAAK,MAAM;AACT,YAAA,OAAO,CAAC;AACV,QAAA,KAAK,KAAK;AACR,YAAA,OAAO,IAAI;AACb,QAAA,KAAK,UAAU;YACb,OAAO,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;AAC/C,QAAA,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;AAC/C,QAAA;AACE,YAAA,OAAO,OAAO;;AAEpB;AAEA;AACM,SAAU,UAAU,CAAC,CAAS,EAAE,CAAS,EAAA;AAC7C,IAAA,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACjC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetBrowserLabels.js","sources":["
|
|
1
|
+
{"version":3,"file":"assetBrowserLabels.js","sources":["src/components/editor/AssetBrowser/assetBrowserLabels.ts"],"sourcesContent":["import type { AssetSortField } from './AssetBrowser.types';\n\n/**\n * Every user-facing string in the AssetBrowser chrome. Pass a partial\n * `labels` prop to translate or reword any subset; unspecified keys fall back\n * to {@link DEFAULT_ASSET_BROWSER_LABELS} (English).\n *\n * The `*Aria` keys are accessible names (screen-reader only); the rest are\n * visible text. `sortFields` maps each sortable field id to its menu/column\n * label. `itemCount` / `selectedCount` build the live-region announcement and\n * receive the relevant counts.\n */\nexport interface AssetBrowserLabels {\n /** Search input placeholder. @default \"Search assets…\" */\n searchPlaceholder: string;\n /** Accessible name of the view-mode toggle. @default \"View mode\" */\n viewModeAria: string;\n /** Grid-view tooltip. @default \"Grid view\" */\n gridViewTooltip: string;\n /** List-view tooltip. @default \"List view\" */\n listViewTooltip: string;\n /** Accessible name of the grid region. @default \"Assets\" */\n gridAria: string;\n /** Sort menu trigger. @default \"Sort\" */\n sort: string;\n /** Ascending radio item. @default \"Ascending\" */\n sortAscending: string;\n /** Descending radio item. @default \"Descending\" */\n sortDescending: string;\n /** Filter menu trigger. @default \"Filter\" */\n filter: string;\n /** Back button accessible name. @default \"Back\" */\n back: string;\n /** Forward button accessible name. @default \"Forward\" */\n forward: string;\n /** Thumbnail-size control accessible name. @default \"Thumbnail size\" */\n thumbnailSizeAria: string;\n /** Default empty-folder message. @default \"This folder is empty.\" */\n empty: string;\n /** Loading message (list view) / skeleton aria. @default \"Loading assets…\" */\n loading: string;\n /** Built-in error title. @default \"Couldn’t load assets\" */\n errorTitle: string;\n /** Built-in error description. */\n errorDescription: string;\n /** Retry button. @default \"Retry\" */\n retry: string;\n /** File-import drop overlay. @default \"Drop files to import\" */\n importOverlay: string;\n /** List \"Type\" value for folders. @default \"Folder\" */\n folder: string;\n /** Rename default-action label + rename-field accessible name. @default \"Rename\" */\n rename: string;\n /** Delete default-action label. @default \"Delete\" */\n delete: string;\n /** Duplicate default-action label. @default \"Duplicate\" */\n duplicate: string;\n /** New-folder default-action label. @default \"New folder\" */\n newFolder: string;\n /** Per-sort-field labels (also the list column headers). */\n sortFields: Record<AssetSortField, string>;\n /** Live-region item count, e.g. `n => \\`${n} items\\``. */\n itemCount: (count: number) => string;\n /** Live-region selected count suffix, e.g. `n => \\`, ${n} selected\\``. */\n selectedCount: (count: number) => string;\n}\n\nexport const DEFAULT_ASSET_BROWSER_LABELS: AssetBrowserLabels = {\n searchPlaceholder: 'Search assets…',\n viewModeAria: 'View mode',\n gridViewTooltip: 'Grid view',\n listViewTooltip: 'List view',\n gridAria: 'Assets',\n sort: 'Sort',\n sortAscending: 'Ascending',\n sortDescending: 'Descending',\n filter: 'Filter',\n back: 'Back',\n forward: 'Forward',\n thumbnailSizeAria: 'Thumbnail size',\n empty: 'This folder is empty.',\n loading: 'Loading assets…',\n errorTitle: 'Couldn’t load assets',\n errorDescription: 'Something went wrong while loading this folder.',\n retry: 'Retry',\n importOverlay: 'Drop files to import',\n folder: 'Folder',\n rename: 'Rename',\n delete: 'Delete',\n duplicate: 'Duplicate',\n newFolder: 'New folder',\n sortFields: {\n name: 'Name',\n type: 'Type',\n size: 'Size',\n modified: 'Modified',\n },\n itemCount: count => `${count} item${count === 1 ? '' : 's'}`,\n selectedCount: count => `, ${count} selected`,\n};\n\n/**\n * Merge a consumer's partial `labels` onto the English defaults. `sortFields`\n * is merged one level deep so overriding a single column label keeps the rest.\n */\nexport function resolveLabels(\n overrides: Partial<AssetBrowserLabels> | undefined\n): AssetBrowserLabels {\n if (!overrides) return DEFAULT_ASSET_BROWSER_LABELS;\n return {\n ...DEFAULT_ASSET_BROWSER_LABELS,\n ...overrides,\n sortFields: {\n ...DEFAULT_ASSET_BROWSER_LABELS.sortFields,\n ...overrides.sortFields,\n },\n };\n}\n"],"names":[],"mappings":"AAmEO,MAAM,4BAA4B,GAAuB;AAC9D,IAAA,iBAAiB,EAAE,gBAAgB;AACnC,IAAA,YAAY,EAAE,WAAW;AACzB,IAAA,eAAe,EAAE,WAAW;AAC5B,IAAA,eAAe,EAAE,WAAW;AAC5B,IAAA,QAAQ,EAAE,QAAQ;AAClB,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,aAAa,EAAE,WAAW;AAC1B,IAAA,cAAc,EAAE,YAAY;AAC5B,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,iBAAiB,EAAE,gBAAgB;AACnC,IAAA,KAAK,EAAE,uBAAuB;AAC9B,IAAA,OAAO,EAAE,iBAAiB;AAC1B,IAAA,UAAU,EAAE,sBAAsB;AAClC,IAAA,gBAAgB,EAAE,iDAAiD;AACnE,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,aAAa,EAAE,sBAAsB;AACrC,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,SAAS,EAAE,WAAW;AACtB,IAAA,SAAS,EAAE,YAAY;AACvB,IAAA,UAAU,EAAE;AACV,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,QAAQ,EAAE,UAAU;AACrB,KAAA;AACD,IAAA,SAAS,EAAE,KAAK,IAAI,CAAA,EAAG,KAAK,CAAA,KAAA,EAAQ,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,CAAA,CAAE;AAC5D,IAAA,aAAa,EAAE,KAAK,IAAI,CAAA,EAAA,EAAK,KAAK,CAAA,SAAA,CAAW;;AAG/C;;;AAGG;AACG,SAAU,aAAa,CAC3B,SAAkD,EAAA;AAElD,IAAA,IAAI,CAAC,SAAS;AAAE,QAAA,OAAO,4BAA4B;IACnD,OAAO;AACL,QAAA,GAAG,4BAA4B;AAC/B,QAAA,GAAG,SAAS;AACZ,QAAA,UAAU,EAAE;YACV,GAAG,4BAA4B,CAAC,UAAU;YAC1C,GAAG,SAAS,CAAC,UAAU;AACxB,SAAA;KACF;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slots.js","sources":["
|
|
1
|
+
{"version":3,"file":"slots.js","sources":["src/components/editor/AssetBrowser/slots.ts"],"sourcesContent":["import type React from 'react';\n\n/**\n * Symbol marker identifying an AssetBrowser compound slot. Survives\n * `React.memo`, function wrapping, and minification — unlike `displayName`.\n */\nexport const ASSET_BROWSER_SLOT: unique symbol = Symbol.for(\n 'etui.assetBrowser.slot'\n);\n\nexport type AssetBrowserSlotKind = 'toolbar' | 'sidebar';\n\ninterface SlotMarker {\n [ASSET_BROWSER_SLOT]: AssetBrowserSlotKind;\n}\n\n/** Tags a component function with its slot kind. */\nexport function markSlot<T>(component: T, kind: AssetBrowserSlotKind): T {\n (component as unknown as SlotMarker)[ASSET_BROWSER_SLOT] = kind;\n return component;\n}\n\n/** Reads the slot kind off a React element's component type, or `null`. */\nexport function getSlotKind(\n el: React.ReactElement\n): AssetBrowserSlotKind | null {\n const type = el.type as Partial<SlotMarker> | null | undefined;\n return type?.[ASSET_BROWSER_SLOT] ?? null;\n}\n"],"names":[],"mappings":"AAEA;;;AAGG;AACI,MAAM,kBAAkB,GAAkB,MAAM,CAAC,GAAG,CACzD,wBAAwB;AAS1B;AACM,SAAU,QAAQ,CAAI,SAAY,EAAE,IAA0B,EAAA;AACjE,IAAA,SAAmC,CAAC,kBAAkB,CAAC,GAAG,IAAI;AAC/D,IAAA,OAAO,SAAS;AAClB;AAEA;AACM,SAAU,WAAW,CACzB,EAAsB,EAAA;AAEtB,IAAA,MAAM,IAAI,GAAG,EAAE,CAAC,IAA8C;AAC9D,IAAA,OAAO,IAAI,GAAG,kBAAkB,CAAC,IAAI,IAAI;AAC3C;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetBrowserAnnouncement.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetBrowserAnnouncement.js","sources":["src/components/editor/AssetBrowser/useAssetBrowserAnnouncement.ts"],"sourcesContent":["'use client';\n\nimport {\n useAssetBrowserContext,\n useAssetSelection,\n} from './AssetBrowserContext';\n\n/**\n * The polite-live a11y announcement string (\"N items, M selected\"). Subscribes\n * to the displayed-items count from the item context and the selection-size\n * slice from the store, so consumers can use it inside a tightly-scoped\n * subcomponent without lifting the value to the root.\n */\nexport function useAssetBrowserAnnouncement(): string {\n const { displayedItems, labels } = useAssetBrowserContext();\n const selectionSet = useAssetSelection();\n const count = displayedItems.length;\n const selected = selectionSet.size;\n return `${labels.itemCount(count)}${selected > 0 ? labels.selectedCount(selected) : ''}`;\n}\n"],"names":[],"mappings":";;;AAOA;;;;;AAKG;;;AAGD;AACA;AACA;;AAEF;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetBrowserHandle.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetBrowserHandle.js","sources":["src/components/editor/AssetBrowser/useAssetBrowserHandle.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useImperativeHandle } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport type { AssetBrowserHandle, AssetItem } from './AssetBrowser.types';\nimport type { AssetBrowserStore } from './AssetBrowserStore';\nimport type { Ref, RefObject } from 'react';\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value);\n }\n return value.replace(/[\"\\\\]/g, '\\\\$&');\n}\n\nexport interface UseAssetBrowserHandleOptions {\n ref: Ref<AssetBrowserHandle> | undefined;\n rootRef: RefObject<HTMLDivElement | null>;\n store: AssetBrowserStore;\n /** Latest `items` — read by `getSelectedItems`. */\n items: readonly AssetItem[];\n /** Latest displayed (filtered + sorted) list — used to resolve scroll targets. */\n displayed: readonly AssetItem[];\n selectAll: () => void;\n clearSelection: () => void;\n /** Stable mutation handler — enters inline rename for an id. */\n beginRename: (id: string) => void;\n}\n\n/**\n * Wires the imperative `AssetBrowserHandle` onto the consumer-provided ref.\n * Each handle method has a stable identity (`useCallback`) and reads the latest\n * props through `useLatest` refs, so the handle object is built once and its\n * methods always see the latest props. `scrollToItem` prefers the\n * store-registered grid scroller (works under virtualization) and falls back\n * to a `data-asset-id` DOM query for the list view or when no grid is mounted.\n */\nexport function useAssetBrowserHandle(\n options: UseAssetBrowserHandleOptions\n): void {\n const {\n ref,\n rootRef,\n store,\n items,\n displayed,\n selectAll,\n clearSelection,\n beginRename,\n } = options;\n\n const itemsRef = useLatest(items);\n const displayedRef = useLatest(displayed);\n\n const focus = useCallback((): void => {\n rootRef.current?.focus();\n }, [rootRef]);\n\n const getElement = useCallback(\n (): HTMLDivElement | null => rootRef.current,\n [rootRef]\n );\n\n const scrollToItem = useCallback(\n (id: string): void => {\n store.setFocusedId(id);\n const index = displayedRef.current.findIndex(it => it.id === id);\n if (index >= 0 && store.scrollToIndex(index)) return;\n const el = rootRef.current?.querySelector(\n `[data-asset-id=\"${cssEscape(id)}\"]`\n );\n el?.scrollIntoView({ block: 'nearest' });\n },\n [store, rootRef, displayedRef]\n );\n\n const getSelectedItems = useCallback(\n (): AssetItem[] =>\n itemsRef.current.filter(it => store.getSelection().has(it.id)),\n [store, itemsRef]\n );\n\n const beginRenameHandle = useCallback(\n (id: string): void => {\n // Bring the target into view first so the rename field is visible even\n // when it was outside the virtualization window.\n scrollToItem(id);\n beginRename(id);\n },\n [scrollToItem, beginRename]\n );\n\n useImperativeHandle(\n ref,\n (): AssetBrowserHandle => ({\n focus,\n getElement,\n selectAll,\n clearSelection,\n scrollToItem,\n getSelectedItems,\n beginRename: beginRenameHandle,\n }),\n [\n focus,\n getElement,\n selectAll,\n clearSelection,\n scrollToItem,\n getSelectedItems,\n beginRenameHandle,\n ]\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAUA;AACE;AACE;;;AAGJ;AAgBA;;;;;;;AAOG;AACG;AAGJ;AAWA;AACA;AAEA;AACE;AACF;AAEA;AAKA;AAEI;AACA;;;AAEA;;;AAQJ;AAMA;;;;;AAME;AAIF;;;;;;;AASI;AACD;;;;;;;;AASA;AAEL;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useControlledState } from '../../../hooks/useControlledState/useControlledState.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetBrowserViewState.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetBrowserViewState.js","sources":["src/components/editor/AssetBrowser/useAssetBrowserViewState.ts"],"sourcesContent":["'use client';\n\nimport { useDeferredValue, useMemo } from 'react';\n\nimport { useControlledState } from '@/hooks';\n\nimport { collectTypes, shapeAssets } from './assetBrowserFilter';\nimport { resolveThumbPx } from './assetBrowserGeometry';\n\nimport type {\n AssetFilterState,\n AssetItem,\n AssetSortState,\n AssetThumbnailSize,\n AssetType,\n AssetView,\n} from './AssetBrowser.types';\n\nconst DEFAULT_SORT: AssetSortState = { field: 'name', direction: 'asc' };\n\nexport interface UseAssetBrowserViewStateOptions {\n items: readonly AssetItem[];\n selectionMode: 'single' | 'multiple' | false;\n marquee: boolean;\n\n view?: AssetView;\n defaultView?: AssetView;\n onViewChange?: (view: AssetView) => void;\n\n thumbnailSize?: AssetThumbnailSize;\n defaultThumbnailSize?: AssetThumbnailSize;\n onThumbnailSizeChange?: (size: AssetThumbnailSize) => void;\n\n search?: string;\n defaultSearch?: string;\n onSearchChange?: (query: string) => void;\n manualSearch: boolean;\n\n filters?: AssetFilterState;\n defaultFilters?: AssetFilterState;\n onFiltersChange?: (filters: AssetFilterState) => void;\n manualFilter: boolean;\n\n sort?: AssetSortState;\n defaultSort?: AssetSortState;\n onSortChange?: (sort: AssetSortState) => void;\n manualSort: boolean;\n\n filterableTypesProp?: AssetType[];\n}\n\nexport interface AssetBrowserViewState {\n view: AssetView;\n setView: (view: AssetView) => void;\n thumbnailSize: AssetThumbnailSize;\n setThumbnailSize: (size: AssetThumbnailSize) => void;\n thumbnailSizePx: number;\n search: string;\n setSearch: (query: string) => void;\n filters: AssetFilterState;\n setFilters: (filters: AssetFilterState) => void;\n sort: AssetSortState;\n setSort: (sort: AssetSortState) => void;\n filterableTypes: string[];\n /** Search (deferred) + filter + sort applied — what the views render. */\n displayed: AssetItem[];\n /** Resolved from `selectionMode === 'multiple'` and the `marquee` prop. */\n marqueeEnabled: boolean;\n}\n\n/**\n * View-state aggregate for `AssetBrowser`. Wraps the five `useControlledState`\n * pairs (view / thumbnailSize / search / filters / sort) and computes the\n * derived values (`thumbnailSizePx`, `filterableTypes`, `displayed`,\n * `marqueeEnabled`). Search is run through `useDeferredValue` so heavy filter\n * + sort passes can lag behind responsive keystrokes.\n */\nexport function useAssetBrowserViewState(\n options: UseAssetBrowserViewStateOptions\n): AssetBrowserViewState {\n const [view, setView] = useControlledState<AssetView>({\n value: options.view,\n defaultValue: options.defaultView,\n onChange: options.onViewChange,\n fallback: 'grid',\n });\n const [thumbnailSize, setThumbnailSize] =\n useControlledState<AssetThumbnailSize>({\n value: options.thumbnailSize,\n defaultValue: options.defaultThumbnailSize,\n onChange: options.onThumbnailSizeChange,\n fallback: 'md',\n });\n const [search, setSearch] = useControlledState<string>({\n value: options.search,\n defaultValue: options.defaultSearch,\n onChange: options.onSearchChange,\n fallback: '',\n });\n const [filters, setFilters] = useControlledState<AssetFilterState>({\n value: options.filters,\n defaultValue: options.defaultFilters,\n onChange: options.onFiltersChange,\n fallback: {},\n });\n const [sort, setSort] = useControlledState<AssetSortState>({\n value: options.sort,\n defaultValue: options.defaultSort,\n onChange: options.onSortChange,\n fallback: DEFAULT_SORT,\n });\n\n const deferredSearch = useDeferredValue(search);\n const thumbnailSizePx = resolveThumbPx(thumbnailSize);\n const marqueeEnabled =\n options.selectionMode === 'multiple' && options.marquee;\n\n const filterableTypes = useMemo(\n () => options.filterableTypesProp ?? collectTypes(options.items),\n [options.filterableTypesProp, options.items]\n );\n\n const displayed = useMemo(\n () =>\n shapeAssets(options.items, {\n search: deferredSearch,\n filters,\n sort,\n manualSearch: options.manualSearch,\n manualFilter: options.manualFilter,\n manualSort: options.manualSort,\n }),\n [\n options.items,\n deferredSearch,\n filters,\n sort,\n options.manualSearch,\n options.manualFilter,\n options.manualSort,\n ]\n );\n\n return useMemo(\n () => ({\n view,\n setView,\n thumbnailSize,\n setThumbnailSize,\n thumbnailSizePx,\n search,\n setSearch,\n filters,\n setFilters,\n sort,\n setSort,\n filterableTypes,\n displayed,\n marqueeEnabled,\n }),\n [\n view,\n setView,\n thumbnailSize,\n setThumbnailSize,\n thumbnailSizePx,\n search,\n setSearch,\n filters,\n setFilters,\n sort,\n setSort,\n filterableTypes,\n displayed,\n marqueeEnabled,\n ]\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAkBA;AAoDA;;;;;;AAMG;AACG;AAGJ;;;;AAIE;AACD;AACD;;;;AAKI;AACD;AACH;;;;AAIE;AACD;AACD;;;;AAIE;AACD;AACD;;;;AAIE;AACD;AAED;AACA;;AAIA;AAKA;AAGM;;;;;;AAMD;AAED;;;;AAIA;AACA;AACA;AACD;AAGH;;;;;;;;;;;;;;;AAgBG;;;;;;;;;;;;;;;AAgBA;AAEL;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetDnd.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetDnd.js","sources":["src/components/editor/AssetBrowser/useAssetDnd.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport type { AssetItem } from './AssetBrowser.types';\nimport type { AssetDndContext } from './AssetBrowserContext';\nimport type { AssetBrowserStore } from './AssetBrowserStore';\nimport type { DragEvent } from 'react';\n\nexport interface UseAssetDndOptions {\n store: AssetBrowserStore;\n mime: string;\n items: readonly AssetItem[];\n selection: ReadonlySet<string>;\n currentFolderId: string | undefined;\n getDragData?: (items: AssetItem[]) => Record<string, string>;\n onItemDragStart?: (items: AssetItem[], event: DragEvent) => void;\n onItemDragEnd?: (items: AssetItem[], event: DragEvent) => void;\n onItemsMove?: (payload: {\n itemIds: string[];\n targetFolderId: string;\n }) => void;\n onFilesImport?: (payload: {\n files: File[];\n targetFolderId: string | null;\n }) => void;\n}\n\nfunction hasFiles(event: DragEvent): boolean {\n return Array.from(event.dataTransfer.types).includes('Files');\n}\n\n/** True when the drag is leaving the element entirely (not into a child). */\nfunction leftElement(event: DragEvent): boolean {\n const related = event.relatedTarget as Node | null;\n return !(related && event.currentTarget.contains(related));\n}\n\n/**\n * Drag-and-drop wiring for the AssetBrowser: internal item moves (gated by\n * `onItemsMove`) and external file import (gated by `onFilesImport`). Every\n * handler has a stable identity (`useCallback`) and reads the latest props\n * through `useLatest` refs, matching `component-patterns.md` rules #3/#11.\n */\nexport function useAssetDnd(options: UseAssetDndOptions): AssetDndContext {\n const {\n store,\n mime,\n items,\n selection,\n currentFolderId,\n getDragData,\n onItemDragStart: cbItemDragStart,\n onItemDragEnd: cbItemDragEnd,\n onItemsMove,\n onFilesImport,\n } = options;\n\n const internalEnabled = onItemsMove !== undefined;\n const externalEnabled = onFilesImport !== undefined;\n\n const mimeRef = useLatest(mime);\n const itemsRef = useLatest(items);\n const selectionRef = useLatest(selection);\n const currentFolderIdRef = useLatest(currentFolderId);\n const getDragDataRef = useLatest(getDragData);\n const cbItemDragStartRef = useLatest(cbItemDragStart);\n const cbItemDragEndRef = useLatest(cbItemDragEnd);\n const onItemsMoveRef = useLatest(onItemsMove);\n const onFilesImportRef = useLatest(onFilesImport);\n\n const resolveItems = useCallback(\n (ids: string[]): AssetItem[] => {\n const map = new Map(itemsRef.current.map(item => [item.id, item]));\n return ids\n .map(id => map.get(id))\n .filter((item): item is AssetItem => item !== undefined);\n },\n [itemsRef]\n );\n\n const onItemDragStart = useCallback(\n (item: AssetItem, event: DragEvent): void => {\n const sel = selectionRef.current;\n const ids = sel.has(item.id) ? Array.from(sel) : [item.id];\n const dragged = resolveItems(ids);\n const payload = getDragDataRef.current?.(dragged) ?? {\n [mimeRef.current]: JSON.stringify(ids),\n };\n for (const [type, value] of Object.entries(payload)) {\n event.dataTransfer.setData(type, value);\n }\n event.dataTransfer.effectAllowed = 'copyMove';\n store.setDrag({\n active: true,\n draggingIds: ids,\n dropTargetId: null,\n externalOver: false,\n });\n cbItemDragStartRef.current?.(dragged, event);\n },\n [\n store,\n resolveItems,\n selectionRef,\n getDragDataRef,\n mimeRef,\n cbItemDragStartRef,\n ]\n );\n\n const onItemDragEnd = useCallback(\n (item: AssetItem, event: DragEvent): void => {\n const ids = store.getDrag().draggingIds;\n const dragged = resolveItems(ids.length > 0 ? ids : [item.id]);\n store.clearDrag();\n cbItemDragEndRef.current?.(dragged, event);\n },\n [store, resolveItems, cbItemDragEndRef]\n );\n\n const onFolderDragOver = useCallback(\n (folderId: string, event: DragEvent): void => {\n const drag = store.getDrag();\n const external =\n onFilesImportRef.current !== undefined && hasFiles(event);\n const internal = onItemsMoveRef.current !== undefined && drag.active;\n if (!external && !internal) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = external ? 'copy' : 'move';\n store.setDrag({\n active: true,\n draggingIds: drag.draggingIds,\n dropTargetId: folderId,\n externalOver: external,\n });\n },\n [store, onFilesImportRef, onItemsMoveRef]\n );\n\n const onFolderDragLeave = useCallback(\n (folderId: string, event: DragEvent): void => {\n if (!leftElement(event)) return;\n const drag = store.getDrag();\n if (drag.dropTargetId !== folderId) return;\n store.setDrag({ ...drag, dropTargetId: null });\n },\n [store]\n );\n\n const onFolderDrop = useCallback(\n (folderId: string, event: DragEvent): void => {\n event.preventDefault();\n const files = Array.from(event.dataTransfer.files);\n const filesImport = onFilesImportRef.current;\n const itemsMove = onItemsMoveRef.current;\n if (files.length > 0 && filesImport) {\n filesImport({ files, targetFolderId: folderId });\n } else if (itemsMove) {\n const drag = store.getDrag();\n let ids = drag.draggingIds;\n if (ids.length === 0) {\n const raw = event.dataTransfer.getData(mimeRef.current);\n if (raw) {\n try {\n ids = JSON.parse(raw) as string[];\n } catch {\n ids = [];\n }\n }\n }\n if (ids.length > 0) {\n itemsMove({ itemIds: ids, targetFolderId: folderId });\n }\n }\n store.clearDrag();\n },\n [store, onFilesImportRef, onItemsMoveRef, mimeRef]\n );\n\n const onSurfaceDragOver = useCallback(\n (event: DragEvent): void => {\n if (onFilesImportRef.current === undefined || !hasFiles(event)) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n const drag = store.getDrag();\n store.setDrag({\n active: true,\n draggingIds: drag.draggingIds,\n dropTargetId: null,\n externalOver: true,\n });\n },\n [store, onFilesImportRef]\n );\n\n const onSurfaceDragLeave = useCallback(\n (event: DragEvent): void => {\n if (!leftElement(event)) return;\n const drag = store.getDrag();\n if (!drag.externalOver) return;\n store.setDrag({ ...drag, externalOver: false });\n },\n [store]\n );\n\n const onSurfaceDrop = useCallback(\n (event: DragEvent): void => {\n const filesImport = onFilesImportRef.current;\n if (!filesImport) return;\n const files = Array.from(event.dataTransfer.files);\n if (files.length === 0) {\n store.clearDrag();\n return;\n }\n event.preventDefault();\n filesImport({\n files,\n targetFolderId: currentFolderIdRef.current ?? null,\n });\n store.clearDrag();\n },\n [store, onFilesImportRef, currentFolderIdRef]\n );\n\n return useMemo<AssetDndContext>(\n () => ({\n internalEnabled,\n externalEnabled,\n onItemDragStart,\n onItemDragEnd,\n onFolderDragOver,\n onFolderDragLeave,\n onFolderDrop,\n onSurfaceDragOver,\n onSurfaceDragLeave,\n onSurfaceDrop,\n }),\n [\n internalEnabled,\n externalEnabled,\n onItemDragStart,\n onItemDragEnd,\n onFolderDragOver,\n onFolderDragLeave,\n onFolderDrop,\n onSurfaceDragOver,\n onSurfaceDragLeave,\n onSurfaceDrop,\n ]\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AA8BA;AACE;AACF;AAEA;AACA;AACE;AACA;AACF;AAEA;;;;;AAKG;AACG;;AAcJ;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;;AAGI;;;AAGF;;AAME;;AAEA;;;;AAIA;;;AAGA;;AAEE;AACA;AACA;AACA;AACD;;AAEH;;;;;;;AAQC;;;;;;;;AAeC;AACA;;AAGA;;;AAEA;;AAEE;;AAEA;AACA;AACD;;;AAOD;;AACA;AACA;;AACA;AACF;;;AAOE;AACA;AACA;;;;;AAIE;AACA;AACA;AACE;;AAEE;AACE;;AACA;;;;;AAKN;;;;;;AASN;;;;AAII;AACA;;AAEE;;AAEA;AACA;AACD;AACH;AAIF;AAEI;;AACA;;;AAEA;AACF;AAIF;AAEI;AACA;;AACA;AACA;;;;;AAKA;;AAEE;AACD;;;AAML;;;;;;;;;;;AAYG;;;;;;;;;;;AAYA;AAEL;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetGridKeyboardNav.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetGridKeyboardNav.js","sources":["src/components/editor/AssetBrowser/useAssetGridKeyboardNav.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo } from 'react';\n\nimport { nextGridIndex } from './assetBrowserKeyboard';\n\nimport type { AssetItem } from './AssetBrowser.types';\nimport type { AssetBrowserStore } from './AssetBrowserStore';\nimport type { AssetGridWindow } from './useAssetGridVirtualizer';\nimport type { KeyboardEvent, RefObject } from 'react';\n\nexport interface UseAssetGridKeyboardNavOptions {\n store: AssetBrowserStore;\n items: readonly AssetItem[];\n /** Current windowed layout (columns, rowHeight). */\n win: AssetGridWindow;\n /** The grid scroller — used to derive `rowsPerPage` from clientHeight. */\n scrollerRef: RefObject<HTMLElement | null>;\n selectionMode: 'single' | 'multiple' | false;\n selectAll: () => void;\n clearSelection: () => void;\n activateItem: (item: AssetItem) => void;\n toggleSelectId: (id: string) => void;\n selectByKeyboard: (index: number, extend: boolean) => void;\n /** Bring the row containing the given item index into view. */\n scrollIndexIntoView: (index: number, w: AssetGridWindow) => void;\n}\n\nexport interface AssetGridKeyboardNav {\n onKeyDown: (event: KeyboardEvent) => void;\n}\n\n/**\n * 2D grid keyboard navigation for `AssetBrowserGrid`. Handles arrows, Home/End,\n * PageUp/PageDown, Enter (activate), Space (toggle), Ctrl/Cmd+A (select all),\n * Escape (clear). `onKeyDown` is a `useCallback` — the selection/navigation\n * callbacks it depends on are themselves stable, and the handler is only spread\n * onto the grid `onKeyDown` so re-attaching on layout changes is free.\n *\n * Alt+ArrowUp is intentionally **not** handled here — it bubbles to the root's\n * \"go to parent\" handler when `history` is on.\n */\nexport function useAssetGridKeyboardNav(\n options: UseAssetGridKeyboardNavOptions\n): AssetGridKeyboardNav {\n const {\n store,\n items,\n win,\n scrollerRef,\n selectionMode,\n selectAll,\n clearSelection,\n activateItem,\n toggleSelectId,\n selectByKeyboard,\n scrollIndexIntoView,\n } = options;\n\n const indexById = useMemo(() => {\n const map = new Map<string, number>();\n items.forEach((item, i) => map.set(item.id, i));\n return map;\n }, [items]);\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent): void => {\n const count = items.length;\n if (count === 0) return;\n const key = event.key;\n // Let Alt+ArrowUp bubble to the root's \"go to parent\" handler.\n if (event.altKey && key === 'ArrowUp') return;\n const focusedId = store.getFocusedId();\n const current = focusedId ? (indexById.get(focusedId) ?? -1) : -1;\n const multiple = selectionMode === 'multiple';\n\n if ((event.ctrlKey || event.metaKey) && (key === 'a' || key === 'A')) {\n event.preventDefault();\n selectAll();\n return;\n }\n if (key === 'Escape') {\n clearSelection();\n return;\n }\n if (key === 'Enter') {\n const item = current >= 0 ? items[current] : undefined;\n if (item) {\n event.preventDefault();\n activateItem(item);\n }\n return;\n }\n if (key === ' ') {\n const item = current >= 0 ? items[current] : undefined;\n if (item) {\n event.preventDefault();\n toggleSelectId(item.id);\n }\n return;\n }\n\n const rowsPerPage = Math.max(\n 1,\n Math.floor(\n (scrollerRef.current?.clientHeight ?? win.rowHeight) / win.rowHeight\n )\n );\n const next = nextGridIndex(current, key, {\n columns: win.columns,\n count,\n rowsPerPage,\n });\n const target = next >= 0 ? items[next] : undefined;\n if (next !== current && target) {\n event.preventDefault();\n store.setFocusedId(target.id);\n scrollIndexIntoView(next, win);\n if (selectionMode !== false) {\n selectByKeyboard(next, multiple && event.shiftKey);\n }\n }\n },\n [\n store,\n items,\n win,\n scrollerRef,\n selectionMode,\n indexById,\n selectAll,\n clearSelection,\n activateItem,\n toggleSelectId,\n selectByKeyboard,\n scrollIndexIntoView,\n ]\n );\n\n return { onKeyDown };\n}\n"],"names":[],"mappings":";;;;AAgCA;;;;;;;;;AASG;AACG;;AAiBJ;AACE;;AAEA;AACF;AAEA;AAEI;;;AAEA;;AAEA;;AACA;;AAEA;;;AAIE;;;AAGF;AACE;;;AAGF;AACE;;;;;;;AAOF;AACE;;;AAGE;;;;AAKJ;AAMA;;;;AAIC;AACD;AACA;;AAEE;AACA;AACA;;;;AAIJ;;;;;;;;;;;;;AAcC;;AAIL;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useResizeObserver } from '../../../hooks/useResizeObserver/useResizeObserver.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetGridVirtualizer.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetGridVirtualizer.js","sources":["src/components/editor/AssetBrowser/useAssetGridVirtualizer.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { useResizeObserver } from '@/hooks';\n\nimport { columnsFor, rowHeight as rowHeightFor } from './assetBrowserGeometry';\n\nimport type { RefObject } from 'react';\n\nexport interface UseAssetGridVirtualizerOptions {\n containerRef: RefObject<HTMLElement | null>;\n count: number;\n thumbPx: number;\n overscanRows: number;\n /** When false, the window spans the whole list (no virtualization). */\n enabled: boolean;\n}\n\nexport interface AssetGridWindow {\n columns: number;\n rowHeight: number;\n totalRows: number;\n totalHeight: number;\n /** First rendered item index (row-aligned). */\n startIndex: number;\n /** One past the last rendered item index. */\n endIndex: number;\n /** Pixel offset of the rendered window from the top. */\n offsetY: number;\n /** Whether windowing is currently active. */\n windowed: boolean;\n}\n\n/**\n * Windowed grid math. Tracks container width + height via `useResizeObserver`\n * and scroll position via a throttled (rAF) scroll listener, then derives the\n * row-aligned slice of items to render.\n *\n * When `enabled` is false it still reports `columns`/`rowHeight` (needed for\n * keyboard navigation) but renders the whole list.\n */\nexport function useAssetGridVirtualizer(\n options: UseAssetGridVirtualizerOptions\n): AssetGridWindow {\n const { containerRef, count, thumbPx, overscanRows, enabled } = options;\n const [size, setSize] = useState({ width: 0, height: 0 });\n const [scrollTop, setScrollTop] = useState(0);\n\n useResizeObserver(containerRef, entry => {\n setSize({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n });\n });\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el || !enabled) return;\n let raf = 0;\n const onScroll = (): void => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n setScrollTop(el.scrollTop);\n });\n };\n el.addEventListener('scroll', onScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', onScroll);\n cancelAnimationFrame(raf);\n };\n }, [containerRef, enabled]);\n\n return useMemo<AssetGridWindow>(() => {\n const columns = columnsFor(size.width, thumbPx);\n const rh = rowHeightFor(thumbPx);\n const totalRows = Math.ceil(count / columns);\n const totalHeight = totalRows * rh;\n\n if (!enabled) {\n return {\n columns,\n rowHeight: rh,\n totalRows,\n totalHeight,\n startIndex: 0,\n endIndex: count,\n offsetY: 0,\n windowed: false,\n };\n }\n\n const startRow = Math.max(0, Math.floor(scrollTop / rh) - overscanRows);\n const viewportRows = Math.ceil((size.height || rh) / rh);\n const endRow = Math.min(\n totalRows,\n startRow + viewportRows + overscanRows * 2\n );\n\n return {\n columns,\n rowHeight: rh,\n totalRows,\n totalHeight,\n startIndex: startRow * columns,\n endIndex: Math.min(count, endRow * columns),\n offsetY: startRow * rh,\n windowed: true,\n };\n }, [\n size.width,\n size.height,\n scrollTop,\n count,\n thumbPx,\n overscanRows,\n enabled,\n ]);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAkCA;;;;;;;AAOG;AACG;AAGJ;AACA;;AAGA;AACE;AACE;AACA;AACD;AACH;;AAGE;AACA;;;;;AAIE;AACE;AACF;AACF;AACA;AACA;AACE;;AAEF;AACF;;;AAIE;;AAEA;;;;AAKI;;;AAGA;AACA;AACA;AACA;;;AAIJ;AACA;AACA;;;AAOE;;;;;;AAMA;;AAEJ;AACE;AACA;;;;;;AAMD;AACH;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetMarqueeGesture.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetMarqueeGesture.js","sources":["src/components/editor/AssetBrowser/useAssetMarqueeGesture.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport { useAssetBrowserStore } from './AssetBrowserContext';\nimport {\n itemRect,\n rectFromPoints,\n rectsIntersect,\n} from './assetBrowserGeometry';\n\nimport type { AssetItem } from './AssetBrowser.types';\nimport type { PointerEvent, RefObject } from 'react';\n\nexport interface UseAssetMarqueeGestureOptions {\n /** The scroll container — also the pointer-capture target and coordinate origin. */\n scrollerRef: RefObject<HTMLElement | null>;\n /** When false, pointer-down is ignored. */\n enabled: boolean;\n /** Currently displayed items, in display order. */\n items: readonly AssetItem[];\n /** Current grid column count (from the virtualizer). */\n columns: number;\n /** Current thumbnail pixel size. */\n thumbPx: number;\n /** Called once on pointer-up with the items that intersect the marquee rect. */\n commitMarquee: (ids: string[], additive: boolean) => void;\n}\n\nexport interface AssetMarqueeGestureHandlers {\n onPointerDown: (event: PointerEvent) => void;\n onPointerMove: (event: PointerEvent) => void;\n onPointerUp: (event: PointerEvent) => void;\n /** Abort an in-flight marquee (system gesture cancel, touch interruption). */\n onPointerCancel: (event: PointerEvent) => void;\n}\n\ninterface MarqueeDrag {\n startX: number;\n startY: number;\n additive: boolean;\n moved: boolean;\n}\n\n/**\n * Pointer-driven rubber-band selection for the grid. The active rect lives in\n * the AssetBrowser store (so the marquee overlay can subscribe via its own\n * slice), while pointer-move updates are RAF-throttled. The hit-test runs once\n * on pointer-up and reports through `commitMarquee`.\n *\n * Handlers have stable identities (`useCallback`) and read the latest props\n * through `useLatest` refs, matching `component-patterns.md` rules #3/#11.\n */\nexport function useAssetMarqueeGesture(\n options: UseAssetMarqueeGestureOptions\n): AssetMarqueeGestureHandlers {\n const { scrollerRef, enabled, items, columns, thumbPx, commitMarquee } =\n options;\n const store = useAssetBrowserStore();\n\n const dragRef = useRef<MarqueeDrag | null>(null);\n const rafRef = useRef(0);\n\n const enabledRef = useLatest(enabled);\n const itemsRef = useLatest(items);\n const columnsRef = useLatest(columns);\n const thumbPxRef = useLatest(thumbPx);\n const commitMarqueeRef = useLatest(commitMarquee);\n\n const contentPoint = useCallback(\n (event: PointerEvent): { x: number; y: number } => {\n const el = scrollerRef.current;\n if (!el) return { x: 0, y: 0 };\n const rect = el.getBoundingClientRect();\n return {\n x: event.clientX - rect.left + el.scrollLeft,\n y: event.clientY - rect.top + el.scrollTop,\n };\n },\n [scrollerRef]\n );\n\n const onPointerDown = useCallback(\n (event: PointerEvent): void => {\n if (event.button !== 0 || !enabledRef.current) return;\n // Started on an item, not empty space — let the item handle the click.\n if (event.target !== event.currentTarget) return;\n const p = contentPoint(event);\n dragRef.current = {\n startX: p.x,\n startY: p.y,\n additive: event.ctrlKey || event.metaKey,\n moved: false,\n };\n scrollerRef.current?.setPointerCapture(event.pointerId);\n store.setMarquee({\n active: true,\n rect: { x: p.x, y: p.y, width: 0, height: 0 },\n additive: dragRef.current.additive,\n });\n },\n [store, scrollerRef, contentPoint, enabledRef]\n );\n\n const onPointerMove = useCallback(\n (event: PointerEvent): void => {\n const drag = dragRef.current;\n if (!drag) return;\n drag.moved = true;\n cancelAnimationFrame(rafRef.current);\n const p = contentPoint(event);\n rafRef.current = requestAnimationFrame(() => {\n store.setMarquee({\n active: true,\n rect: rectFromPoints(drag.startX, drag.startY, p.x, p.y),\n additive: drag.additive,\n });\n });\n },\n [store, contentPoint]\n );\n\n const onPointerUp = useCallback(\n (event: PointerEvent): void => {\n const drag = dragRef.current;\n if (!drag) return;\n cancelAnimationFrame(rafRef.current);\n dragRef.current = null;\n scrollerRef.current?.releasePointerCapture(event.pointerId);\n const p = contentPoint(event);\n const rect = rectFromPoints(drag.startX, drag.startY, p.x, p.y);\n const ids: string[] = [];\n const currentItems = itemsRef.current;\n for (let i = 0; i < currentItems.length; i += 1) {\n const item = currentItems[i];\n if (!item || item.selectable === false) continue;\n if (\n rectsIntersect(\n rect,\n itemRect(i, columnsRef.current, thumbPxRef.current)\n )\n ) {\n ids.push(item.id);\n }\n }\n commitMarqueeRef.current(ids, drag.additive);\n store.clearMarquee();\n },\n [\n store,\n scrollerRef,\n contentPoint,\n itemsRef,\n columnsRef,\n thumbPxRef,\n commitMarqueeRef,\n ]\n );\n\n // Abort an in-flight marquee without committing a selection. Fires on a\n // system/touch `pointercancel`, which would otherwise leave `dragRef` set and\n // the marquee rect stuck active in the store until the next pointer-down.\n const onPointerCancel = useCallback(\n (event: PointerEvent): void => {\n if (!dragRef.current) return;\n cancelAnimationFrame(rafRef.current);\n dragRef.current = null;\n scrollerRef.current?.releasePointerCapture(event.pointerId);\n store.clearMarquee();\n },\n [store, scrollerRef]\n );\n\n // Cancel any in-flight RAF on unmount.\n useEffect(\n () => () => {\n cancelAnimationFrame(rafRef.current);\n },\n []\n );\n\n return { onPointerDown, onPointerMove, onPointerUp, onPointerCancel };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA8CA;;;;;;;;AAQG;AACG;AAGJ;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEI;AACA;;AACA;;;;;AAKF;AAIF;;;;AAII;;AACA;;;;AAIE;AACA;;;;AAIA;;AAEA;AACD;;AAKL;AAEI;AACA;;AACA;AACA;AACA;AACA;;AAEI;AACA;;AAED;AACH;AACF;AAIF;AAEI;AACA;;AACA;AACA;;AAEA;;;AAGA;AACA;AACE;AACA;;AACA;AAME;;;;;AAKN;;;;;;;;AASC;;;;AAMH;;;AAGI;AACA;;;AAGF;;AAKF;AAEI;;;AAMN;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetMutationKeyboard.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetMutationKeyboard.js","sources":["src/components/editor/AssetBrowser/useAssetMutationKeyboard.ts"],"sourcesContent":["'use client';\n\nimport { useCallback } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport type { AssetBrowserStore } from './AssetBrowserStore';\nimport type { AssetMutationsApi } from './useAssetMutations';\nimport type { KeyboardEvent } from 'react';\n\nexport interface UseAssetMutationKeyboardOptions {\n store: AssetBrowserStore;\n mutations: AssetMutationsApi;\n /** Live selection set — the F2 rename target falls back to a single selection. */\n selection: ReadonlySet<string>;\n}\n\nexport interface AssetMutationKeyboard {\n /** Attach to the AssetBrowser root: F2 / Delete / Ctrl+D, view-agnostic. */\n onKeyDown: (event: KeyboardEvent) => void;\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n );\n}\n\n/**\n * View-agnostic mutation keyboard shortcuts. The same handler is exposed through\n * context (`mutationKeyDown`) and attached by each view to its own scroller —\n * the grid (merged with its 2D nav) and the list wrapper — so the shortcuts\n * work identically in both without relying on event bubbling to the root.\n *\n * - **F2** — inline-rename the focused item, or the sole selected item (the list\n * has no store roving-focus, so it falls back to a single selection).\n * - **Delete** (and **⌘⌫** on macOS) — delete the selection. Plain `Backspace`\n * stays reserved for the root's \"go to parent\" shortcut.\n * - **Ctrl/⌘+D** — duplicate the selection.\n *\n * Each shortcut is a no-op unless its mutation callback is wired, and all are\n * skipped while the focus is in an editable element (search box, rename field).\n * The handler is `useCallback`-stable; live state is read through `useLatest`.\n */\nexport function useAssetMutationKeyboard(\n options: UseAssetMutationKeyboardOptions\n): AssetMutationKeyboard {\n const { store, mutations } = options;\n const mutationsRef = useLatest(mutations);\n const selectionRef = useLatest(options.selection);\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent): void => {\n if (isEditableTarget(event.target)) return;\n const key = event.key;\n const m = mutationsRef.current;\n\n if (\n (event.ctrlKey || event.metaKey) &&\n (key === 'd' || key === 'D') &&\n m.canDuplicate\n ) {\n event.preventDefault();\n m.duplicateItems();\n return;\n }\n if (key === 'F2' && m.canRename) {\n const focusedId = store.getFocusedId();\n const sel = selectionRef.current;\n const targetId =\n focusedId ?? (sel.size === 1 ? [...sel][0] : undefined);\n if (targetId !== undefined) {\n event.preventDefault();\n m.beginRename(targetId);\n }\n return;\n }\n if (\n (key === 'Delete' || (event.metaKey && key === 'Backspace')) &&\n m.canDelete\n ) {\n event.preventDefault();\n m.deleteItems();\n }\n },\n [store, mutationsRef, selectionRef]\n );\n\n return { onKeyDown };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAsBA;AACE;AAAsC;AACtC;;;AAKF;AAEA;;;;;;;;;;;;;;;AAeG;AACG;AAGJ;AACA;;AAGA;AAEI;;AACA;AACA;;AAIE;;;;;;;AAQA;AACA;;AAGA;;AAEE;;;;AAIJ;;;;;;;AAYN;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetMutations.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetMutations.js","sources":["src/components/editor/AssetBrowser/useAssetMutations.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport type { AssetItem, AssetRenameResult } from './AssetBrowser.types';\nimport type { AssetBrowserStore } from './AssetBrowserStore';\n\nexport interface UseAssetMutationsOptions {\n store: AssetBrowserStore;\n /** Displayed (filtered + sorted) list — used to resolve the focus-after-delete target. */\n displayed: readonly AssetItem[];\n /** Live selection set — delete/duplicate default to acting on it. */\n selection: ReadonlySet<string>;\n currentFolderId: string | undefined;\n onItemRename?: (item: AssetItem, newName: string) => AssetRenameResult;\n onItemsDelete?: (items: AssetItem[]) => void;\n onCreateFolder?: (parentFolderId: string | null) => void;\n onItemsDuplicate?: (items: AssetItem[]) => void;\n}\n\nexport interface AssetMutationsApi {\n /** Whether each operation is enabled (its callback is present). */\n canRename: boolean;\n canDelete: boolean;\n canCreateFolder: boolean;\n canDuplicate: boolean;\n /** Enter inline-rename on `id` (no-op when rename is disabled). */\n beginRename: (id: string) => void;\n /**\n * Commit a rename. Returns whether the editor should close (`true`) or stay\n * open (`false`, e.g. the consumer rejected the name). Empty / unchanged\n * names close without firing the callback.\n */\n commitRename: (item: AssetItem, newName: string) => Promise<boolean>;\n /** Leave rename mode without committing. */\n cancelRename: () => void;\n /** Delete the given items (defaults to the current selection when omitted). */\n deleteItems: (items?: readonly AssetItem[]) => void;\n /** Create a folder in the current folder. */\n createFolder: () => void;\n /** Duplicate the given items (defaults to the current selection when omitted). */\n duplicateItems: (items?: readonly AssetItem[]) => void;\n}\n\n/**\n * Owns the mutation intents — inline rename (begin/commit/cancel), delete,\n * create-folder, duplicate — for `AssetBrowser`. AssetBrowser is presentational:\n * these report intent through the consumer's callbacks and never touch `items`.\n *\n * The \"which cell is editing\" flag lives in the store (so rename can be started\n * from the keyboard, a menu, or the imperative handle — all outside the cell);\n * the transient text buffer is local to the rename field. Every handler has a\n * stable identity (`useCallback`) and reads the latest props through `useLatest`\n * refs, matching `component-patterns.md` rules #3/#11.\n */\nexport function useAssetMutations(\n options: UseAssetMutationsOptions\n): AssetMutationsApi {\n const { store } = options;\n\n const canRename = options.onItemRename !== undefined;\n const canDelete = options.onItemsDelete !== undefined;\n const canCreateFolder = options.onCreateFolder !== undefined;\n const canDuplicate = options.onItemsDuplicate !== undefined;\n\n const displayedRef = useLatest(options.displayed);\n const selectionRef = useLatest(options.selection);\n const currentFolderIdRef = useLatest(options.currentFolderId);\n const onItemRenameRef = useLatest(options.onItemRename);\n const onItemsDeleteRef = useLatest(options.onItemsDelete);\n const onCreateFolderRef = useLatest(options.onCreateFolder);\n const onItemsDuplicateRef = useLatest(options.onItemsDuplicate);\n\n /** Resolve the items an operation targets: the explicit arg, else the selection. */\n const resolveTargets = useCallback(\n (items?: readonly AssetItem[]): AssetItem[] => {\n if (items) return [...items];\n const sel = selectionRef.current;\n return displayedRef.current.filter(it => sel.has(it.id));\n },\n [displayedRef, selectionRef]\n );\n\n const beginRename = useCallback(\n (id: string): void => {\n if (onItemRenameRef.current === undefined) return;\n store.setFocusedId(id);\n store.setEditingId(id);\n },\n [store, onItemRenameRef]\n );\n\n const cancelRename = useCallback((): void => {\n store.setEditingId(null);\n }, [store]);\n\n const commitRename = useCallback(\n async (item: AssetItem, newName: string): Promise<boolean> => {\n const trimmed = newName.trim();\n const cb = onItemRenameRef.current;\n // Empty or unchanged → close silently without firing the callback.\n if (cb === undefined || trimmed === '' || trimmed === item.name) {\n store.setEditingId(null);\n return true;\n }\n const result = await cb(item, trimmed);\n // Only an explicit `false` keeps the editor open (rejected name).\n const accepted = result !== false;\n if (accepted) store.setEditingId(null);\n return accepted;\n },\n [store, onItemRenameRef]\n );\n\n const deleteItems = useCallback(\n (items?: readonly AssetItem[]): void => {\n const cb = onItemsDeleteRef.current;\n if (cb === undefined) return;\n const targets = resolveTargets(items);\n if (targets.length === 0) return;\n // Move roving focus to a survivor before the data updates, so focus\n // doesn't vanish when the deleted cells unmount.\n const list = displayedRef.current;\n const doomed = new Set(targets.map(it => it.id));\n const focusedId = store.getFocusedId();\n if (focusedId !== null && doomed.has(focusedId)) {\n const from = list.findIndex(it => it.id === focusedId);\n let survivor: string | null = null;\n for (let i = from + 1; i < list.length; i += 1) {\n const it = list[i];\n if (it && !doomed.has(it.id)) {\n survivor = it.id;\n break;\n }\n }\n if (survivor === null) {\n for (let i = from - 1; i >= 0; i -= 1) {\n const it = list[i];\n if (it && !doomed.has(it.id)) {\n survivor = it.id;\n break;\n }\n }\n }\n store.setFocusedId(survivor);\n }\n cb(targets);\n },\n [store, resolveTargets, displayedRef, onItemsDeleteRef]\n );\n\n const createFolder = useCallback((): void => {\n onCreateFolderRef.current?.(currentFolderIdRef.current ?? null);\n }, [onCreateFolderRef, currentFolderIdRef]);\n\n const duplicateItems = useCallback(\n (items?: readonly AssetItem[]): void => {\n const cb = onItemsDuplicateRef.current;\n if (cb === undefined) return;\n const targets = resolveTargets(items);\n if (targets.length === 0) return;\n cb(targets);\n },\n [resolveTargets, onItemsDuplicateRef]\n );\n\n return useMemo<AssetMutationsApi>(\n () => ({\n canRename,\n canDelete,\n canCreateFolder,\n canDuplicate,\n beginRename,\n commitRename,\n cancelRename,\n deleteItems,\n createFolder,\n duplicateItems,\n }),\n [\n canRename,\n canDelete,\n canCreateFolder,\n canDuplicate,\n beginRename,\n commitRename,\n cancelRename,\n deleteItems,\n createFolder,\n duplicateItems,\n ]\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AA8CA;;;;;;;;;;AAUG;AACG;AAGJ;AAEA;AACA;AACA;AACA;;;;;;;;;AAWA;AAEI;AAAW;AACX;AACA;AACF;AAIF;AAEI;;AACA;AACA;AACF;AAIF;AACE;AACF;;AAII;AACA;;AAEA;AACE;AACA;;;;AAIF;AACA;AAAc;AACd;AACF;AAIF;AAEI;;;AAEA;AACA;;;;AAGA;AACA;AACA;;AAEE;;AAEA;AACE;AACA;AACE;;;;AAIJ;AACE;AACE;AACA;AACE;;;;;AAKN;;;;AAON;;AAEA;AAEA;AAEI;;;AAEA;AACA;;;AAEF;AAIF;;;;;;;;;;;AAYG;;;;;;;;;;;AAYA;AAEL;;"}
|
|
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
|
|
|
4
4
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
5
5
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
6
6
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
7
|
-
import '
|
|
7
|
+
import '@vanilla-extract/css';
|
|
8
8
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetNavigation.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetNavigation.js","sources":["src/components/editor/AssetBrowser/useAssetNavigation.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo } from 'react';\n\nimport { useLatest, useNavigationHistory } from '@/hooks';\n\nimport type {\n AssetItem,\n AssetNavigationSource,\n AssetPathSegment,\n} from './AssetBrowser.types';\nimport type { KeyboardEvent } from 'react';\n\nexport interface UseAssetNavigationOptions {\n /** Enables Back/Forward + parent-nav. When false, the hook is a thin pass-through. */\n history: boolean;\n /** Current location (oldest → newest). Used to resolve \"go to parent\". */\n path: readonly AssetPathSegment[];\n /** Seeds the history stack on mount. */\n currentFolderId: string | undefined;\n onNavigate?: (folderId: string, source: AssetNavigationSource) => void;\n onItemOpen?: (item: AssetItem) => void;\n}\n\nexport interface AssetNavigationApi {\n /** Pass-through for navigation (breadcrumb / sidebar / folder open). Pushes onto history. */\n navigate: (folderId: string, source: AssetNavigationSource) => void;\n /** Open a file or enter a folder (file → onItemOpen; folder → navigate). */\n activateItem: (item: AssetItem) => void;\n goBack: () => void;\n goForward: () => void;\n canGoBack: boolean;\n canGoForward: boolean;\n /** Pass-through of the prop so consumers can gate UI on it. */\n history: boolean;\n /** Attach to the AssetBrowser root: Backspace / Alt+ArrowUp → parent folder. */\n handleRootKeyDown: (event: KeyboardEvent) => void;\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n );\n}\n\n/**\n * Folder navigation + back/forward stack + \"go to parent\" keyboard shortcuts,\n * built on top of the library's `useNavigationHistory` primitive. Every handler\n * has a stable identity (`useCallback`) and reads the latest props through\n * `useLatest` refs, matching `component-patterns.md` rules #3/#11.\n */\nexport function useAssetNavigation(\n options: UseAssetNavigationOptions\n): AssetNavigationApi {\n const { history, path, onNavigate, onItemOpen, currentFolderId } = options;\n\n const histApi = useNavigationHistory({\n initial: currentFolderId,\n enabled: history,\n });\n const { push, canGoBack, canGoForward } = histApi;\n const histGoBack = histApi.goBack;\n const histGoForward = histApi.goForward;\n\n // Keep the back/forward stack in sync with the controlled `currentFolderId`.\n // `useNavigationHistory` only seeds `initial` once on mount, so an out-of-band\n // change (deep link, \"reveal in browser\", or a parent that updates\n // `currentFolderId` without routing through `navigate`) would otherwise leave\n // the stack — and `canGoBack`/`canGoForward` — stale. `push` no-ops when the\n // entry already equals the current one, so navigate/back/forward (which leave\n // `current === currentFolderId`) don't double-push and the forward branch\n // survives; only a genuine external change advances the stack. This is the\n // \"mirror React state into an external store\" bridge that component-patterns.md\n // §2 lists as a legitimate `useEffect` use.\n useEffect(() => {\n if (!history || currentFolderId === undefined) return;\n push(currentFolderId);\n }, [history, currentFolderId, push]);\n\n const onNavigateRef = useLatest(onNavigate);\n const onItemOpenRef = useLatest(onItemOpen);\n const historyRef = useLatest(history);\n const pathRef = useLatest(path);\n\n const navigate = useCallback(\n (folderId: string, source: AssetNavigationSource): void => {\n push(folderId);\n onNavigateRef.current?.(folderId, source);\n },\n [push, onNavigateRef]\n );\n\n const goBack = useCallback((): void => {\n const target = histGoBack();\n if (target === undefined) return;\n onNavigateRef.current?.(target, 'back');\n }, [histGoBack, onNavigateRef]);\n\n const goForward = useCallback((): void => {\n const target = histGoForward();\n if (target === undefined) return;\n onNavigateRef.current?.(target, 'forward');\n }, [histGoForward, onNavigateRef]);\n\n const activateItem = useCallback(\n (item: AssetItem): void => {\n if (item.kind === 'folder') navigate(item.id, 'open');\n else onItemOpenRef.current?.(item);\n },\n [navigate, onItemOpenRef]\n );\n\n const handleRootKeyDown = useCallback(\n (event: KeyboardEvent): void => {\n if (!historyRef.current) return;\n if (isEditableTarget(event.target)) return;\n const goToParent =\n event.key === 'Backspace' || (event.altKey && event.key === 'ArrowUp');\n if (!goToParent) return;\n const currentPath = pathRef.current;\n const parent = currentPath[currentPath.length - 2];\n if (parent) {\n event.preventDefault();\n navigate(parent.id, 'breadcrumb');\n }\n },\n [navigate, historyRef, pathRef]\n );\n\n return useMemo(\n () => ({\n navigate,\n activateItem,\n goBack,\n goForward,\n canGoBack,\n canGoForward,\n history,\n handleRootKeyDown,\n }),\n [\n navigate,\n activateItem,\n goBack,\n goForward,\n canGoBack,\n canGoForward,\n history,\n handleRootKeyDown,\n ]\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAuCA;AACE;AAAsC;AACtC;;;AAKF;AAEA;;;;;AAKG;AACG;AAGJ;;AAGE;AACA;AACD;;AAED;AACA;;;;;;;;;;;;AAaE;;;;AAIF;AACA;AACA;AACA;;;;AAME;AAIF;AACE;;;;AAGF;AAEA;AACE;;;;AAGF;AAEA;AAEI;AAA4B;;AACvB;AACP;AAIF;;;AAGI;;AACA;AAEA;;AACA;;;;AAIE;;;AAMN;;;;;;;;;AAUG;;;;;;;;;AAUA;AAEL;;"}
|
|
@@ -5,7 +5,7 @@ import { useControlledState } from '../../../hooks/useControlledState/useControl
|
|
|
5
5
|
import { useLatest } from '../../../hooks/useLatest/useLatest.js';
|
|
6
6
|
import '../../../hooks/useBreakpoint/useBreakpoint.js';
|
|
7
7
|
import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
|
|
8
|
-
import '
|
|
8
|
+
import '@vanilla-extract/css';
|
|
9
9
|
import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
|
|
10
10
|
import 'react/jsx-runtime';
|
|
11
11
|
import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetSelectionController.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAssetSelectionController.js","sources":["src/components/editor/AssetBrowser/useAssetSelectionController.ts"],"sourcesContent":["'use client';\n\nimport {\n useCallback,\n useLayoutEffect,\n useMemo,\n useRef,\n useTransition,\n} from 'react';\n\nimport { useControlledState, useLatest } from '@/hooks';\n\nimport { indexRange } from './assetBrowserKeyboard';\n\nimport type { AssetItem, AssetSelectionReason } from './AssetBrowser.types';\nimport type { AssetBrowserStore } from './AssetBrowserStore';\nimport type { MouseEvent } from 'react';\n\nexport interface UseAssetSelectionControllerOptions {\n store: AssetBrowserStore;\n /** The filtered + sorted list, in display order (anchor ranges run over it). */\n displayed: readonly AssetItem[];\n selectionMode: 'single' | 'multiple' | false;\n selection?: readonly string[];\n defaultSelection?: readonly string[];\n onSelectionChange?: (\n ids: string[],\n meta: { reason: AssetSelectionReason }\n ) => void;\n}\n\nexport interface AssetSelectionHandlers {\n handleItemClick: (item: AssetItem, index: number, event: MouseEvent) => void;\n selectByKeyboard: (index: number, extend: boolean) => void;\n toggleSelectId: (id: string) => void;\n setSelectionIds: (ids: string[], reason: AssetSelectionReason) => void;\n commitMarquee: (ids: string[], additive: boolean) => void;\n selectAll: () => void;\n clearSelection: () => void;\n contextMenuSelect: (item: AssetItem) => void;\n}\n\nexport interface AssetSelectionController {\n selectionSet: ReadonlySet<string>;\n /** Stable identity — the handlers never change, so they're safe context deps. */\n handlers: AssetSelectionHandlers;\n}\n\nfunction selectableIds(list: readonly AssetItem[]): string[] {\n return list.filter(it => it.selectable !== false).map(it => it.id);\n}\n\n/**\n * Owns selection state and the click/keyboard/marquee gestures that mutate it.\n *\n * Selection stays in React state (so the controlled `selection` prop and\n * `onSelectionChange` work) but is mirrored into the store on commit, letting\n * each cell subscribe to its own `useAssetSelected(id)` slice instead of\n * re-rendering the whole grid. The anchor is tracked by **id**, not index, so\n * shift-ranges survive a re-sort or re-filter between clicks. All handlers have\n * stable identities (`useCallback`) and read the latest props/state through\n * `useLatest` refs, matching `component-patterns.md` rules #3/#11.\n */\nexport function useAssetSelectionController(\n options: UseAssetSelectionControllerOptions\n): AssetSelectionController {\n const { store, displayed, selectionMode, onSelectionChange } = options;\n const [, startTransition] = useTransition();\n\n const [selectionArr, setSelectionArr] = useControlledState<readonly string[]>(\n {\n value: options.selection,\n defaultValue: options.defaultSelection,\n fallback: [],\n }\n );\n\n const selectionSet = useMemo(() => new Set(selectionArr), [selectionArr]);\n\n // Mirror into the store so per-id slices stay in sync. useLayoutEffect runs\n // before paint, so initially-selected items never flash unselected.\n useLayoutEffect(() => {\n store.setSelection(selectionSet);\n }, [store, selectionSet]);\n\n const anchorRef = useRef<string | null>(null);\n\n // Live props/state read inside the stable handlers below.\n const displayedRef = useLatest(displayed);\n const selectionModeRef = useLatest(selectionMode);\n const selectionSetRef = useLatest(selectionSet);\n const onSelectionChangeRef = useLatest(onSelectionChange);\n\n /** Resolve the anchor id to its current position in the displayed list. */\n const anchorIndex = useCallback((): number => {\n if (anchorRef.current === null) return -1;\n return displayedRef.current.findIndex(it => it.id === anchorRef.current);\n }, [displayedRef]);\n\n const commitSelection = useCallback(\n (ids: string[], reason: AssetSelectionReason): void => {\n setSelectionArr(ids);\n onSelectionChangeRef.current?.(ids, { reason });\n },\n [setSelectionArr, onSelectionChangeRef]\n );\n\n const handleItemClick = useCallback(\n (item: AssetItem, index: number, event: MouseEvent): void => {\n store.setFocusedId(item.id);\n if (\n selectionModeRef.current === false ||\n item.selectable === false ||\n item.disabled\n ) {\n return;\n }\n if (selectionModeRef.current === 'single') {\n commitSelection([item.id], 'click');\n anchorRef.current = item.id;\n return;\n }\n if (event.shiftKey) {\n const a = anchorIndex();\n if (a !== -1) {\n const [from, to] = indexRange(a, index);\n commitSelection(\n selectableIds(displayedRef.current.slice(from, to + 1)),\n 'click'\n );\n return;\n }\n }\n if (event.ctrlKey || event.metaKey) {\n const next = new Set(selectionSetRef.current);\n if (next.has(item.id)) next.delete(item.id);\n else next.add(item.id);\n commitSelection(Array.from(next), 'click');\n anchorRef.current = item.id;\n return;\n }\n commitSelection([item.id], 'click');\n anchorRef.current = item.id;\n },\n [\n store,\n commitSelection,\n anchorIndex,\n selectionModeRef,\n displayedRef,\n selectionSetRef,\n ]\n );\n\n const selectByKeyboard = useCallback(\n (index: number, extend: boolean): void => {\n const item = displayedRef.current[index];\n if (!item) return;\n if (extend) {\n const a = anchorIndex();\n if (a !== -1) {\n const [from, to] = indexRange(a, index);\n commitSelection(\n selectableIds(displayedRef.current.slice(from, to + 1)),\n 'keyboard'\n );\n return;\n }\n }\n commitSelection(item.selectable === false ? [] : [item.id], 'keyboard');\n anchorRef.current = item.id;\n },\n [commitSelection, anchorIndex, displayedRef]\n );\n\n const toggleSelectId = useCallback(\n (id: string): void => {\n const next = new Set(selectionSetRef.current);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n commitSelection(Array.from(next), 'keyboard');\n },\n [commitSelection, selectionSetRef]\n );\n\n const setSelectionIds = useCallback(\n (ids: string[], reason: AssetSelectionReason): void => {\n commitSelection(ids, reason);\n },\n [commitSelection]\n );\n\n const commitMarquee = useCallback(\n (ids: string[], additive: boolean): void => {\n startTransition(() => {\n if (additive) {\n const next = new Set(selectionSetRef.current);\n ids.forEach(id => next.add(id));\n commitSelection(Array.from(next), 'marquee');\n return;\n }\n commitSelection(ids, 'marquee');\n });\n },\n [commitSelection, selectionSetRef]\n );\n\n const selectAll = useCallback((): void => {\n startTransition(() => {\n commitSelection(selectableIds(displayedRef.current), 'selectAll');\n });\n }, [commitSelection, displayedRef]);\n\n const clearSelection = useCallback((): void => {\n commitSelection([], 'clear');\n }, [commitSelection]);\n\n const contextMenuSelect = useCallback(\n (item: AssetItem): void => {\n store.setFocusedId(item.id);\n if (!selectionSetRef.current.has(item.id) && item.selectable !== false) {\n commitSelection([item.id], 'contextMenu');\n }\n anchorRef.current = item.id;\n },\n [store, commitSelection, selectionSetRef]\n );\n\n const handlers = useMemo<AssetSelectionHandlers>(\n () => ({\n handleItemClick,\n selectByKeyboard,\n toggleSelectId,\n setSelectionIds,\n commitMarquee,\n selectAll,\n clearSelection,\n contextMenuSelect,\n }),\n [\n handleItemClick,\n selectByKeyboard,\n toggleSelectId,\n setSelectionIds,\n commitMarquee,\n selectAll,\n clearSelection,\n contextMenuSelect,\n ]\n );\n\n return { selectionSet, handlers };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAgDA;;AAEA;AAEA;;;;;;;;;;AAUG;AACG;;AAIJ;AAEA;;;AAII;AACD;AAGH;;;;AAKE;AACF;AAEA;;AAGA;AACA;AACA;AACA;;AAGA;AACE;;AACA;AACF;;;;AAME;;AAME;AACA;;;;;AAOA;;AAEE;;;AAGF;AACE;AACA;AACE;AACA;;;;;;AASF;AAAuB;;AAClB;;AAEL;;;;AAIF;AACF;;;;;;;AAQC;;;AAMC;;;AAEE;AACA;AACE;AACA;;;;;AAQJ;;AAKJ;;AAGI;AAAkB;;AACb;;AAEP;;AAME;AACF;;;;;AASM;;;;AAIF;AACF;AACF;AAIF;;;AAGE;AACF;AAEA;AACE;AACF;AAEA;AAEI;AACA;;;AAGA;;AAKJ;;;;;;;;;AAUG;;;;;;;;;AAUA;AAGH;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatActionBar.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatActionBar.js","sources":["src/components/editor/ChatPanel/ChatActionBar.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { actionBarStyle } from './ChatPanel.css';\n\nimport type { ChatActionBarProps } from './ChatPanel.types';\n\nexport const ChatActionBar = /*#__PURE__*/ React.memo<ChatActionBarProps>(\n ({ children, className, style, testId, ref, ...rest }) => {\n return (\n <div\n ref={ref}\n className={cx(actionBarStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n );\n }\n);\n\nChatActionBar.displayName = 'ChatActionBar';\n"],"names":[],"mappings":";;;;;;AAUO;;AAaL;AAGF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatAttachment.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatAttachment.js","sources":["src/components/editor/ChatPanel/ChatAttachment.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n MiniCloseIcon,\n MiniFileIcon,\n MiniImageIcon,\n MiniCodeIcon,\n MiniSelectionIcon,\n} from './ChatIcons';\nimport {\n attachmentChipStyle,\n attachmentChipIconStyle,\n attachmentChipNameStyle,\n attachmentChipRemoveStyle,\n attachmentThumbnailStyle,\n} from './ChatPanel.css';\n\nimport type { ChatAttachmentChipProps } from './ChatPanel.types';\n\nconst TYPE_ICONS: Record<string, React.FC> = {\n file: MiniFileIcon,\n image: MiniImageIcon,\n code: MiniCodeIcon,\n selection: MiniSelectionIcon,\n};\n\n// ─── Component ───────────────────────────────────────────────────\n\nexport const ChatAttachmentChip =\n /*#__PURE__*/ React.memo<ChatAttachmentChipProps>(\n ({\n attachment,\n onRemove,\n onClick,\n removable = false,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const handleClick = useCallback(() => {\n onClick?.(attachment);\n }, [onClick, attachment]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.(attachment);\n }\n },\n [onClick, attachment]\n );\n\n const handleRemove = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemove?.(attachment.id);\n },\n [onRemove, attachment.id]\n );\n\n const TypeIcon = TYPE_ICONS[attachment.type] ?? MiniFileIcon;\n const isClickable = !!onClick;\n\n return (\n <div\n ref={ref}\n className={cx(attachmentChipStyle, className)}\n style={style}\n data-testid={testId}\n data-clickable={isClickable || undefined}\n onClick={isClickable ? handleClick : undefined}\n onKeyDown={isClickable ? handleKeyDown : undefined}\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n {...rest}\n >\n {attachment.type === 'image' && attachment.thumbnailUrl ? (\n <img\n src={attachment.thumbnailUrl}\n alt={attachment.name}\n className={attachmentThumbnailStyle}\n />\n ) : (\n <span className={attachmentChipIconStyle}>\n <TypeIcon />\n </span>\n )}\n\n <span className={attachmentChipNameStyle}>{attachment.name}</span>\n\n {removable && (\n <button\n type=\"button\"\n className={attachmentChipRemoveStyle}\n onClick={handleRemove}\n aria-label={`Remove ${attachment.name}`}\n >\n <MiniCloseIcon />\n </button>\n )}\n </div>\n );\n }\n );\n\nChatAttachmentChip.displayName = 'ChatAttachmentChip';\n"],"names":[],"mappings":";;;;;;;AAuBA;AACE;AACA;AACA;AACA;;AAGF;;AAGE;AAYI;AACE;AACF;AAEA;AAEI;;AAEE;;AAEJ;AAIF;;AAGI;;;AAMJ;AAEA;AAuCF;AAGJ;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatBubble.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatBubble.js","sources":["src/components/editor/ChatPanel/ChatBubble.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { bubbleRecipe } from './ChatPanel.css';\n\nimport type { ChatBubbleProps } from './ChatPanel.types';\n\nexport const ChatBubble = /*#__PURE__*/ React.memo<ChatBubbleProps>(\n ({\n role = 'assistant',\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n return (\n <div\n ref={ref}\n className={cx(bubbleRecipe({ role }), className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n );\n }\n);\n\nChatBubble.displayName = 'ChatBubble';\n"],"names":[],"mappings":";;;;;;AAUO;AAUH;AAWF;AAGF;;"}
|
|
@@ -89,6 +89,12 @@ import '../../Icons/GitBranchIcon.js';
|
|
|
89
89
|
import '../../Icons/BugIcon.js';
|
|
90
90
|
import '../../Icons/MinusIcon.js';
|
|
91
91
|
import '../../Icons/PinIcon.js';
|
|
92
|
+
import '../../Icons/OrbitIcon.js';
|
|
93
|
+
import '../../Icons/RotateIcon.js';
|
|
94
|
+
import '../../Icons/SpinIcon.js';
|
|
95
|
+
import '../../Icons/CameraIcon.js';
|
|
96
|
+
import '../../Icons/CubeIcon.js';
|
|
97
|
+
import '../../Icons/ZoomFitIcon.js';
|
|
92
98
|
import { useIsMounted } from '../../../hooks/useIsMounted/useIsMounted.js';
|
|
93
99
|
import { cx } from '../../../utils/cx.js';
|
|
94
100
|
import { codeBlockHeaderStyle, codeBlockLanguageStyle, codeBlockActionsStyle, codeBlockCopyButtonStyle, codeBlockLineNumbersColumnStyle, codeBlockPreStyle, codeBlockMaxHeightVar, codeBlockContentWithLineNumbersStyle, codeBlockContentStyle, codeBlockContainerStyle } from './ChatPanel.css.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatCodeBlock.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatCodeBlock.js","sources":["src/components/editor/ChatPanel/ChatCodeBlock.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useState, useCallback } from 'react';\n\nimport { CheckIcon, CopyIcon } from '@/components/Icons';\nimport { useIsMounted } from '@/hooks/useIsMounted';\nimport { cx } from '@/utils/cx';\n\nimport {\n codeBlockContainerStyle,\n codeBlockHeaderStyle,\n codeBlockLanguageStyle,\n codeBlockActionsStyle,\n codeBlockCopyButtonStyle,\n codeBlockContentStyle,\n codeBlockContentWithLineNumbersStyle,\n codeBlockLineNumbersColumnStyle,\n codeBlockPreStyle,\n codeBlockMaxHeightVar,\n} from './ChatPanel.css';\n\nimport type { ChatCodeBlockProps } from './ChatPanel.types';\n\nexport const ChatCodeBlock = /*#__PURE__*/ React.memo<ChatCodeBlockProps>(\n ({\n code,\n language,\n copyable = true,\n lineNumbers = false,\n maxHeight = 400,\n actions,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const [copied, setCopied] = useState(false);\n const isMounted = useIsMounted();\n\n const handleCopy = useCallback(() => {\n navigator.clipboard\n .writeText(code)\n .then(() => {\n // clipboard.writeText can't be cancelled, so guard the state writes:\n // the block may unmount before it resolves, or within the 2s reset.\n if (!isMounted()) return;\n setCopied(true);\n setTimeout(() => {\n if (isMounted()) setCopied(false);\n }, 2000);\n })\n .catch(() => {\n // Fallback: older browsers — no-op\n });\n }, [code, isMounted]);\n\n const lines = code.split('\\n');\n const showHeader = language != null || copyable || actions != null;\n\n return (\n <div\n ref={ref}\n className={cx(codeBlockContainerStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {showHeader && (\n <div className={codeBlockHeaderStyle}>\n {language != null && (\n <span className={codeBlockLanguageStyle}>{language}</span>\n )}\n <div className={codeBlockActionsStyle}>\n {actions}\n {copyable && (\n <button\n type=\"button\"\n className={codeBlockCopyButtonStyle}\n onClick={handleCopy}\n aria-label={copied ? 'Copied' : 'Copy code'}\n >\n {copied ? (\n <CheckIcon size={12} decorative />\n ) : (\n <CopyIcon size={12} decorative />\n )}\n </button>\n )}\n </div>\n </div>\n )}\n\n <div\n className={cx(\n codeBlockContentStyle,\n lineNumbers && codeBlockContentWithLineNumbersStyle\n )}\n style={assignInlineVars({\n [codeBlockMaxHeightVar]: `${maxHeight}px`,\n })}\n data-testid={testId ? `${testId}-content` : undefined}\n >\n {lineNumbers && (\n <div\n className={codeBlockLineNumbersColumnStyle}\n aria-hidden=\"true\"\n data-testid={testId ? `${testId}-line-numbers` : undefined}\n >\n {lines.map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n )}\n <pre className={codeBlockPreStyle}>\n <code>{code}</code>\n </pre>\n </div>\n </div>\n );\n }\n);\n\nChatCodeBlock.displayName = 'ChatCodeBlock';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO;;AAeH;AAEA;AACE;;;;;;;;;AAQM;;;AAEJ;;;AAGA;AACJ;;;AAKA;AAuCQ;AACD;AAoBT;AAGF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatContextChip.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatContextChip.js","sources":["src/components/editor/ChatPanel/ChatContextChip.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { MiniCloseIcon } from './ChatIcons';\nimport {\n contextChipStyle,\n contextChipIconStyle,\n contextChipLabelStyle,\n contextChipItemsStyle,\n contextChipDismissStyle,\n} from './ChatPanel.css';\n\nimport type { ChatContextChipProps } from './ChatPanel.types';\n\nexport const ChatContextChip = /*#__PURE__*/ React.memo<ChatContextChipProps>(\n ({\n label,\n items,\n icon,\n onDismiss,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n return (\n <div\n ref={ref}\n className={cx(contextChipStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {icon && <span className={contextChipIconStyle}>{icon}</span>}\n <span className={contextChipLabelStyle}>{label}:</span>\n <span className={contextChipItemsStyle}>{items.join(', ')}</span>\n {onDismiss && (\n <button\n type=\"button\"\n className={contextChipDismissStyle}\n onClick={onDismiss}\n aria-label={`Dismiss ${label}`}\n >\n <MiniCloseIcon />\n </button>\n )}\n </div>\n );\n }\n);\n\nChatContextChip.displayName = 'ChatContextChip';\n"],"names":[],"mappings":";;;;;;;AAiBO;AAYH;AAuBF;AAGF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatEmptyState.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatEmptyState.js","sources":["src/components/editor/ChatPanel/ChatEmptyState.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n emptyStateStyle,\n emptyStateIconStyle,\n emptyStateTitleStyle,\n emptyStateDescriptionStyle,\n emptyStateSuggestionsStyle,\n emptyStateSuggestionStyle,\n} from './ChatPanel.css';\n\nimport type { ChatEmptyStateProps } from './ChatPanel.types';\n\nexport const ChatEmptyState = /*#__PURE__*/ React.memo<ChatEmptyStateProps>(\n ({\n title,\n description,\n icon,\n suggestions,\n onSuggestionClick,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const handleSuggestionClick = useCallback(\n (suggestion: string) => {\n onSuggestionClick?.(suggestion);\n },\n [onSuggestionClick]\n );\n\n return (\n <div\n ref={ref}\n className={cx(emptyStateStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {icon && <div className={emptyStateIconStyle}>{icon}</div>}\n {title && <div className={emptyStateTitleStyle}>{title}</div>}\n {description && (\n <div className={emptyStateDescriptionStyle}>{description}</div>\n )}\n {suggestions && suggestions.length > 0 && (\n <div className={emptyStateSuggestionsStyle}>\n {suggestions.map(suggestion => (\n <button\n key={suggestion}\n type=\"button\"\n className={emptyStateSuggestionStyle}\n onClick={() => {\n handleSuggestionClick(suggestion);\n }}\n >\n {suggestion}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n }\n);\n\nChatEmptyState.displayName = 'ChatEmptyState';\n"],"names":[],"mappings":";;;;;;AAiBO;AAaH;AAEI;AACF;AAIF;;;AA+BF;AAGF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatIcons.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatIcons.js","sources":["src/components/editor/ChatPanel/ChatIcons.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\n/**\n * Shared mini-icons for Chat components.\n * These use smaller viewBoxes (8x8, 16x16) than the library's Icon system (24x24)\n * and are designed for inline use in compact chat UI elements.\n */\n\nexport const MiniCloseIcon: React.FC = () => (\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M1 1l6 6M7 1L1 7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport const MiniFileIcon: React.FC = () => (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M9 2H4.5A1.5 1.5 0 003 3.5v9A1.5 1.5 0 004.5 14h7a1.5 1.5 0 001.5-1.5V6L9 2z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M9 2v4h4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const MiniImageIcon: React.FC = () => (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"2\"\n y=\"2\"\n width=\"12\"\n height=\"12\"\n rx=\"1.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <circle cx=\"5.5\" cy=\"5.5\" r=\"1.5\" fill=\"currentColor\" />\n <path\n d=\"M2 11l3-3 2 2 3-3 4 4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const MiniCodeIcon: React.FC = () => (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5 4L1 8l4 4M11 4l4 4-4 4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const MiniSelectionIcon: React.FC = () => (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"2\"\n y=\"2\"\n width=\"5\"\n height=\"5\"\n rx=\"0.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <rect\n x=\"9\"\n y=\"9\"\n width=\"5\"\n height=\"5\"\n rx=\"0.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </svg>\n);\n\nexport const MiniWrenchIcon: React.FC = () => (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M14.25 1.75L12.5 3.5L13 5L11.5 6.5L10.5 5.5L5.5 10.5L6.5 11.5L5 13L3.5 12.5L1.75 14.25\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M8.5 2.5L10 4L8 6L6.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const MiniChevronIcon: React.FC<{ size?: number }> = ({ size = 10 }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n"],"names":[],"mappings":";;;AAIA;;;;AAIG;;AAaI;;;AAqEA;AA6BA;AAyBA;;"}
|
|
@@ -89,6 +89,12 @@ import '../../Icons/GitBranchIcon.js';
|
|
|
89
89
|
import '../../Icons/BugIcon.js';
|
|
90
90
|
import '../../Icons/MinusIcon.js';
|
|
91
91
|
import '../../Icons/PinIcon.js';
|
|
92
|
+
import '../../Icons/OrbitIcon.js';
|
|
93
|
+
import '../../Icons/RotateIcon.js';
|
|
94
|
+
import '../../Icons/SpinIcon.js';
|
|
95
|
+
import '../../Icons/CameraIcon.js';
|
|
96
|
+
import '../../Icons/CubeIcon.js';
|
|
97
|
+
import '../../Icons/ZoomFitIcon.js';
|
|
92
98
|
import { cx } from '../../../utils/cx.js';
|
|
93
99
|
import { ChatAttachmentChip } from './ChatAttachment.js';
|
|
94
100
|
import { inputPrefixStyle, inputAttachmentsStyle, inputWrapperStyle, inputTextareaStyle, inputMaxHeightVar, inputBottomBarStyle, inputStopButtonStyle, inputButtonStyle, inputContainerStyle } from './ChatPanel.css.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInput.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatInput.js","sources":["src/components/editor/ChatPanel/ChatInput.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useCallback, useId } from 'react';\n\nimport { SendIcon, StopIcon } from '@/components/Icons';\nimport { cx } from '@/utils/cx';\n\nimport { ChatAttachmentChip } from './ChatAttachment';\nimport {\n inputContainerStyle,\n inputAttachmentsStyle,\n inputPrefixStyle,\n inputWrapperStyle,\n inputTextareaStyle,\n inputButtonStyle,\n inputStopButtonStyle,\n inputMaxHeightVar,\n inputBottomBarStyle,\n} from './ChatPanel.css';\nimport { useChatInput } from './useChatInput';\n\nimport type { ChatInputProps } from './ChatPanel.types';\n\nexport const ChatInput = /*#__PURE__*/ React.memo<ChatInputProps>(\n ({\n value: controlledValue,\n onChange: controlledOnChange,\n onSubmit,\n onStop,\n placeholder = 'Type a message...',\n streaming = false,\n disabled = false,\n submitKey = 'enter',\n maxLines = 6,\n attachments,\n onRemoveAttachment,\n prefix,\n suffix,\n toolbar,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n const inputId = useId();\n\n const handleSubmit = useCallback(\n (text: string) => {\n onSubmit?.(text, attachments ?? []);\n },\n [onSubmit, attachments]\n );\n\n const chatInput = useChatInput({\n submitKey,\n onSubmit: handleSubmit,\n maxLines,\n attachmentsCount: attachments?.length ?? 0,\n });\n\n // Support controlled mode\n const currentValue = controlledValue ?? chatInput.value;\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (controlledOnChange) {\n controlledOnChange(e.target.value);\n }\n chatInput.handleChange(e);\n },\n [controlledOnChange, chatInput]\n );\n\n const attachmentsCount = attachments?.length ?? 0;\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // In controlled mode, override the internal value check\n if (controlledValue !== undefined) {\n const isSubmitKey =\n submitKey === 'enter'\n ? e.key === 'Enter' && !e.shiftKey\n : e.key === 'Enter' && (e.ctrlKey || e.metaKey);\n\n if (isSubmitKey && (controlledValue.trim() || attachmentsCount > 0)) {\n e.preventDefault();\n onSubmit?.(controlledValue.trim(), attachments ?? []);\n return;\n }\n }\n chatInput.handleKeyDown(e);\n },\n [\n controlledValue,\n submitKey,\n onSubmit,\n attachments,\n attachmentsCount,\n chatInput,\n ]\n );\n\n const handleSendClick = useCallback(() => {\n const val = controlledValue ?? chatInput.value;\n const canSubmit = val.trim() || attachmentsCount > 0;\n if (canSubmit) {\n onSubmit?.(val.trim(), attachments ?? []);\n if (controlledValue === undefined) {\n chatInput.clear();\n }\n }\n }, [controlledValue, chatInput, onSubmit, attachments, attachmentsCount]);\n\n const canSubmit =\n (currentValue.trim().length > 0 || attachmentsCount > 0) && !disabled;\n\n const lineHeight = 18; // approximate line-height in px\n const maxHeightPx = `${maxLines * lineHeight}px`;\n\n const shortcutLabel =\n submitKey === 'enter'\n ? 'Enter to send, Shift+Enter for newline'\n : 'Ctrl+Enter to send, Enter for newline';\n\n return (\n <div\n ref={ref}\n className={cx(inputContainerStyle, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {prefix && <div className={inputPrefixStyle}>{prefix}</div>}\n\n {attachments && attachments.length > 0 && (\n <div className={inputAttachmentsStyle}>\n {attachments.map(att => (\n <ChatAttachmentChip\n key={att.id}\n attachment={att}\n removable={!!onRemoveAttachment}\n onRemove={onRemoveAttachment}\n />\n ))}\n </div>\n )}\n\n <div className={inputWrapperStyle}>\n <textarea\n ref={chatInput.textareaRef}\n id={`chat-input-${inputId}`}\n className={inputTextareaStyle}\n style={assignInlineVars({\n [inputMaxHeightVar]: maxHeightPx,\n })}\n value={currentValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n aria-label=\"Chat message input\"\n aria-keyshortcuts={shortcutLabel}\n />\n\n {suffix}\n\n <div className={inputBottomBarStyle}>\n {toolbar}\n\n {streaming ? (\n <button\n type=\"button\"\n className={inputStopButtonStyle}\n onClick={onStop}\n aria-label=\"Stop generating\"\n >\n <StopIcon size={12} decorative />\n </button>\n ) : (\n <button\n type=\"button\"\n className={inputButtonStyle}\n onClick={handleSendClick}\n disabled={!canSubmit}\n aria-label=\"Send message\"\n >\n <SendIcon size={14} decorative />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n }\n);\n\nChatInput.displayName = 'ChatInput';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO;AAsBH;AAEA;;AAGE;;;AAMA;;AAEA;AACD;;AAGD;AAEA;;AAGM;;AAEF;AACF;AAIF;AAEA;;AAGI;AACE;;AAGI;AAEJ;;;;;;AAMF;AACF;;;;;;;AAQC;AAGH;AACE;;;;AAIE;;;;AAIJ;AAEA;AAGA;AACA;AAEA;AAEI;;;;;AAyEN;AAGF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInputToolbar.js","sources":["
|
|
1
|
+
{"version":3,"file":"ChatInputToolbar.js","sources":["src/components/editor/ChatPanel/ChatInputToolbar.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { inputToolbarStyle } from './ChatPanel.css';\n\nimport type { ChatInputToolbarProps } from './ChatPanel.types';\n\nexport const ChatInputToolbar = /*#__PURE__*/ React.memo<ChatInputToolbarProps>(\n ({ children, className, style, testId, ref, ...rest }) => {\n return (\n <div\n ref={ref}\n className={cx(inputToolbarStyle, className)}\n style={style}\n data-testid={testId}\n role=\"toolbar\"\n aria-label=\"Chat input actions\"\n {...rest}\n >\n {children}\n </div>\n );\n }\n);\n\nChatInputToolbar.displayName = 'ChatInputToolbar';\n"],"names":[],"mappings":";;;;;;AAUO;AAEH;AAaF;AAGF;;"}
|