fancy-ui-react 0.2.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/LICENSE +21 -0
- package/PORTING.md +118 -0
- package/README.md +643 -0
- package/dist/cameleon/FancyProvider.d.ts +11 -0
- package/dist/cameleon/FancyProvider.js +42 -0
- package/dist/cameleon/context.d.ts +22 -0
- package/dist/cameleon/context.js +16 -0
- package/dist/cameleon/index.d.ts +31 -0
- package/dist/cameleon/index.js +39 -0
- package/dist/cameleon/primitives/Badge.d.ts +10 -0
- package/dist/cameleon/primitives/Badge.js +12 -0
- package/dist/cameleon/primitives/Button.d.ts +11 -0
- package/dist/cameleon/primitives/Button.js +43 -0
- package/dist/cameleon/primitives/Checkbox.d.ts +10 -0
- package/dist/cameleon/primitives/Checkbox.js +39 -0
- package/dist/cameleon/primitives/Input.d.ts +10 -0
- package/dist/cameleon/primitives/Input.js +13 -0
- package/dist/cameleon/primitives/Radio.d.ts +12 -0
- package/dist/cameleon/primitives/Radio.js +29 -0
- package/dist/cameleon/primitives/Select.d.ts +10 -0
- package/dist/cameleon/primitives/Select.js +27 -0
- package/dist/cameleon/primitives/Slider.d.ts +7 -0
- package/dist/cameleon/primitives/Slider.js +22 -0
- package/dist/cameleon/primitives/Switch.d.ts +9 -0
- package/dist/cameleon/primitives/Switch.js +33 -0
- package/dist/cameleon/primitives/Textarea.d.ts +9 -0
- package/dist/cameleon/primitives/Textarea.js +13 -0
- package/dist/cameleon/primitives/Tooltip.d.ts +14 -0
- package/dist/cameleon/primitives/Tooltip.js +15 -0
- package/dist/cameleon/primitives/index.d.ts +10 -0
- package/dist/cameleon/skins/aurora/index.d.ts +2 -0
- package/dist/cameleon/skins/aurora/index.js +16 -0
- package/dist/cameleon/skins/aurora/meta.d.ts +3 -0
- package/dist/cameleon/skins/aurora/meta.js +61 -0
- package/dist/cameleon/skins/aurora/recipes.d.ts +24 -0
- package/dist/cameleon/skins/aurora/recipes.js +124 -0
- package/dist/cameleon/skins/aurora/tokens.d.ts +6 -0
- package/dist/cameleon/skins/aurora/tokens.js +18 -0
- package/dist/cameleon/skins/brutal/index.d.ts +2 -0
- package/dist/cameleon/skins/brutal/index.js +35 -0
- package/dist/cameleon/skins/brutal/meta.d.ts +3 -0
- package/dist/cameleon/skins/brutal/meta.js +73 -0
- package/dist/cameleon/skins/brutal/ornaments.d.ts +7 -0
- package/dist/cameleon/skins/brutal/ornaments.js +18 -0
- package/dist/cameleon/skins/brutal/recipes.d.ts +23 -0
- package/dist/cameleon/skins/brutal/recipes.js +113 -0
- package/dist/cameleon/skins/brutal/tokens.d.ts +8 -0
- package/dist/cameleon/skins/brutal/tokens.js +23 -0
- package/dist/cameleon/skins/default.d.ts +2 -0
- package/dist/cameleon/skins/default.js +79 -0
- package/dist/cameleon/skins/glass/index.d.ts +2 -0
- package/dist/cameleon/skins/glass/index.js +16 -0
- package/dist/cameleon/skins/glass/meta.d.ts +3 -0
- package/dist/cameleon/skins/glass/meta.js +63 -0
- package/dist/cameleon/skins/glass/recipes.d.ts +24 -0
- package/dist/cameleon/skins/glass/recipes.js +124 -0
- package/dist/cameleon/skins/glass/tokens.d.ts +5 -0
- package/dist/cameleon/skins/glass/tokens.js +18 -0
- package/dist/cameleon/skins/retro-os/index.d.ts +2 -0
- package/dist/cameleon/skins/retro-os/index.js +24 -0
- package/dist/cameleon/skins/retro-os/meta.d.ts +3 -0
- package/dist/cameleon/skins/retro-os/meta.js +61 -0
- package/dist/cameleon/skins/retro-os/ornaments.d.ts +9 -0
- package/dist/cameleon/skins/retro-os/ornaments.js +28 -0
- package/dist/cameleon/skins/retro-os/recipes.d.ts +35 -0
- package/dist/cameleon/skins/retro-os/recipes.js +126 -0
- package/dist/cameleon/skins/retro-os/tokens.d.ts +16 -0
- package/dist/cameleon/skins/retro-os/tokens.js +23 -0
- package/dist/cameleon/skins/terminal/index.d.ts +2 -0
- package/dist/cameleon/skins/terminal/index.js +24 -0
- package/dist/cameleon/skins/terminal/meta.d.ts +3 -0
- package/dist/cameleon/skins/terminal/meta.js +70 -0
- package/dist/cameleon/skins/terminal/ornaments.d.ts +7 -0
- package/dist/cameleon/skins/terminal/ornaments.js +8 -0
- package/dist/cameleon/skins/terminal/recipes.d.ts +25 -0
- package/dist/cameleon/skins/terminal/recipes.js +125 -0
- package/dist/cameleon/skins/terminal/tokens.d.ts +5 -0
- package/dist/cameleon/skins/terminal/tokens.js +18 -0
- package/dist/cameleon/types.d.ts +133 -0
- package/dist/components/agent-plan/AgentPlan.d.ts +25 -0
- package/dist/components/agent-plan/AgentPlan.js +181 -0
- package/dist/components/agent-plan/index.d.ts +2 -0
- package/dist/components/ai-data-table/AiDataTable.d.ts +54 -0
- package/dist/components/ai-data-table/AiDataTable.js +110 -0
- package/dist/components/ai-data-table/index.d.ts +2 -0
- package/dist/components/alert-dialog/AlertDialog.d.ts +35 -0
- package/dist/components/alert-dialog/AlertDialog.js +109 -0
- package/dist/components/alert-dialog/index.d.ts +2 -0
- package/dist/components/animated-beam/AnimatedBeam.d.ts +39 -0
- package/dist/components/animated-beam/AnimatedBeam.js +192 -0
- package/dist/components/animated-beam/index.d.ts +2 -0
- package/dist/components/animated-testimonials/AnimatedTestimonials.d.ts +32 -0
- package/dist/components/animated-testimonials/AnimatedTestimonials.js +172 -0
- package/dist/components/animated-testimonials/index.d.ts +2 -0
- package/dist/components/animated-tooltip/AnimatedTooltip.d.ts +13 -0
- package/dist/components/animated-tooltip/AnimatedTooltip.js +137 -0
- package/dist/components/animated-tooltip/index.d.ts +2 -0
- package/dist/components/apple-card-carousel/AppleCard.d.ts +30 -0
- package/dist/components/apple-card-carousel/AppleCard.js +219 -0
- package/dist/components/apple-card-carousel/AppleCardCarousel.d.ts +14 -0
- package/dist/components/apple-card-carousel/AppleCardCarousel.js +30 -0
- package/dist/components/apple-card-carousel/index.d.ts +4 -0
- package/dist/components/approval-card/ApprovalCard.d.ts +57 -0
- package/dist/components/approval-card/ApprovalCard.js +153 -0
- package/dist/components/approval-card/index.d.ts +2 -0
- package/dist/components/artifact-card/ArtifactCard.d.ts +44 -0
- package/dist/components/artifact-card/ArtifactCard.js +204 -0
- package/dist/components/artifact-card/index.d.ts +2 -0
- package/dist/components/autocomplete/Autocomplete.d.ts +36 -0
- package/dist/components/autocomplete/Autocomplete.js +186 -0
- package/dist/components/autocomplete/AutocompletePanel.d.ts +12 -0
- package/dist/components/autocomplete/AutocompletePanel.js +123 -0
- package/dist/components/autocomplete/index.d.ts +4 -0
- package/dist/components/autocomplete/match.d.ts +6 -0
- package/dist/components/autocomplete/match.js +10 -0
- package/dist/components/autocomplete/types.d.ts +52 -0
- package/dist/components/autocomplete/types.js +6 -0
- package/dist/components/bento-grid/BentoGrid.d.ts +6 -0
- package/dist/components/bento-grid/BentoGrid.js +19 -0
- package/dist/components/bento-grid/BentoGridCard.d.ts +11 -0
- package/dist/components/bento-grid/BentoGridCard.js +49 -0
- package/dist/components/bento-grid/BentoGridItem.d.ts +9 -0
- package/dist/components/bento-grid/BentoGridItem.js +33 -0
- package/dist/components/bento-grid/index.d.ts +6 -0
- package/dist/components/bg-falling-stars/FallingStarsBg.d.ts +24 -0
- package/dist/components/bg-falling-stars/FallingStarsBg.js +134 -0
- package/dist/components/bg-falling-stars/index.d.ts +2 -0
- package/dist/components/bg-stars/StarsBackground.d.ts +40 -0
- package/dist/components/bg-stars/StarsBackground.js +188 -0
- package/dist/components/bg-stars/index.d.ts +2 -0
- package/dist/components/blur-reveal/BlurReveal.d.ts +19 -0
- package/dist/components/blur-reveal/BlurReveal.js +50 -0
- package/dist/components/blur-reveal/index.d.ts +2 -0
- package/dist/components/book/Book.d.ts +13 -0
- package/dist/components/book/Book.js +94 -0
- package/dist/components/book/BookDescription.d.ts +6 -0
- package/dist/components/book/BookDescription.js +9 -0
- package/dist/components/book/BookHeader.d.ts +6 -0
- package/dist/components/book/BookHeader.js +9 -0
- package/dist/components/book/BookTitle.d.ts +6 -0
- package/dist/components/book/BookTitle.js +9 -0
- package/dist/components/book/index.d.ts +132 -0
- package/dist/components/book/index.js +48 -0
- package/dist/components/border-beam/BorderBeam.d.ts +25 -0
- package/dist/components/border-beam/BorderBeam.js +45 -0
- package/dist/components/border-beam/index.d.ts +2 -0
- package/dist/components/box-reveal/BoxReveal.d.ts +20 -0
- package/dist/components/box-reveal/BoxReveal.js +58 -0
- package/dist/components/box-reveal/index.d.ts +2 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts +49 -0
- package/dist/components/breadcrumb/Breadcrumb.js +61 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/button/Button.d.ts +44 -0
- package/dist/components/button/Button.js +120 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/types.d.ts +4 -0
- package/dist/components/button-group/ButtonGroup.d.ts +23 -0
- package/dist/components/button-group/ButtonGroup.js +30 -0
- package/dist/components/button-group/index.d.ts +4 -0
- package/dist/components/button-group/types.d.ts +34 -0
- package/dist/components/button-group/types.js +7 -0
- package/dist/components/card-3d/CardBody.d.ts +8 -0
- package/dist/components/card-3d/CardBody.js +9 -0
- package/dist/components/card-3d/CardContainer.d.ts +19 -0
- package/dist/components/card-3d/CardContainer.js +61 -0
- package/dist/components/card-3d/CardItem.d.ts +22 -0
- package/dist/components/card-3d/CardItem.js +29 -0
- package/dist/components/card-3d/index.d.ts +6 -0
- package/dist/components/card-spotlight/CardSpotlight.d.ts +16 -0
- package/dist/components/card-spotlight/CardSpotlight.js +65 -0
- package/dist/components/card-spotlight/index.d.ts +2 -0
- package/dist/components/chat-error/ChatError.d.ts +32 -0
- package/dist/components/chat-error/ChatError.js +75 -0
- package/dist/components/chat-error/index.d.ts +2 -0
- package/dist/components/chat-message/ChatMessage.d.ts +43 -0
- package/dist/components/chat-message/ChatMessage.js +127 -0
- package/dist/components/chat-message/ChatMessageAction.d.ts +20 -0
- package/dist/components/chat-message/ChatMessageAction.js +58 -0
- package/dist/components/chat-message/ChatMessageActions.d.ts +14 -0
- package/dist/components/chat-message/ChatMessageActions.js +30 -0
- package/dist/components/chat-message/ChatMessageBranches.d.ts +15 -0
- package/dist/components/chat-message/ChatMessageBranches.js +93 -0
- package/dist/components/chat-message/index.d.ts +10 -0
- package/dist/components/chat-message/types.d.ts +38 -0
- package/dist/components/chat-message/types.js +7 -0
- package/dist/components/chat-panel/ChatEmptyState.d.ts +17 -0
- package/dist/components/chat-panel/ChatEmptyState.js +42 -0
- package/dist/components/chat-panel/ChatPanel.d.ts +31 -0
- package/dist/components/chat-panel/ChatPanel.js +163 -0
- package/dist/components/chat-panel/index.d.ts +4 -0
- package/dist/components/checkbox/Checkbox.d.ts +64 -0
- package/dist/components/checkbox/Checkbox.js +123 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/code-diff/CodeDiff.d.ts +39 -0
- package/dist/components/code-diff/CodeDiff.js +213 -0
- package/dist/components/code-diff/index.d.ts +2 -0
- package/dist/components/colourful-text/ColourfulText.d.ts +28 -0
- package/dist/components/colourful-text/ColourfulText.js +73 -0
- package/dist/components/colourful-text/index.d.ts +2 -0
- package/dist/components/combobox/Combobox.d.ts +53 -0
- package/dist/components/combobox/Combobox.js +248 -0
- package/dist/components/combobox/ComboboxPanel.d.ts +28 -0
- package/dist/components/combobox/ComboboxPanel.js +110 -0
- package/dist/components/combobox/index.d.ts +4 -0
- package/dist/components/combobox/match.d.ts +15 -0
- package/dist/components/combobox/match.js +14 -0
- package/dist/components/combobox/types.d.ts +60 -0
- package/dist/components/combobox/types.js +6 -0
- package/dist/components/command-menu/CommandMenu.d.ts +37 -0
- package/dist/components/command-menu/CommandMenu.js +386 -0
- package/dist/components/command-menu/index.d.ts +3 -0
- package/dist/components/command-menu/match.d.ts +19 -0
- package/dist/components/command-menu/match.js +45 -0
- package/dist/components/command-menu/types.d.ts +19 -0
- package/dist/components/compare/Compare.d.ts +31 -0
- package/dist/components/compare/Compare.js +300 -0
- package/dist/components/compare/StarField.d.ts +22 -0
- package/dist/components/compare/StarField.js +66 -0
- package/dist/components/compare/index.d.ts +4 -0
- package/dist/components/composer/Composer.d.ts +56 -0
- package/dist/components/composer/Composer.js +155 -0
- package/dist/components/composer/ComposerAttachment.d.ts +14 -0
- package/dist/components/composer/ComposerAttachment.js +127 -0
- package/dist/components/composer/ComposerAttachments.d.ts +18 -0
- package/dist/components/composer/ComposerAttachments.js +85 -0
- package/dist/components/composer/ComposerCommandMenu.d.ts +37 -0
- package/dist/components/composer/ComposerCommandMenu.js +208 -0
- package/dist/components/composer/ComposerInput.d.ts +22 -0
- package/dist/components/composer/ComposerInput.js +96 -0
- package/dist/components/composer/ComposerModelPicker.d.ts +32 -0
- package/dist/components/composer/ComposerModelPicker.js +223 -0
- package/dist/components/composer/ComposerSubmit.d.ts +16 -0
- package/dist/components/composer/ComposerSubmit.js +52 -0
- package/dist/components/composer/ComposerToolbar.d.ts +38 -0
- package/dist/components/composer/ComposerToolbar.js +9 -0
- package/dist/components/composer/caret.d.ts +69 -0
- package/dist/components/composer/caret.js +112 -0
- package/dist/components/composer/index.d.ts +18 -0
- package/dist/components/composer/types.d.ts +86 -0
- package/dist/components/composer/types.js +7 -0
- package/dist/components/confetti/Confetti.d.ts +37 -0
- package/dist/components/confetti/Confetti.js +45 -0
- package/dist/components/confetti/ConfettiButton.d.ts +23 -0
- package/dist/components/confetti/ConfettiButton.js +29 -0
- package/dist/components/confetti/context.d.ts +21 -0
- package/dist/components/confetti/context.js +6 -0
- package/dist/components/confetti/index.d.ts +4 -0
- package/dist/components/container-scroll/ContainerScroll.d.ts +10 -0
- package/dist/components/container-scroll/ContainerScroll.js +74 -0
- package/dist/components/container-scroll/index.d.ts +2 -0
- package/dist/components/container-text-flip/ContainerTextFlip.d.ts +9 -0
- package/dist/components/container-text-flip/ContainerTextFlip.js +58 -0
- package/dist/components/container-text-flip/index.d.ts +2 -0
- package/dist/components/context-menu/ContextMenu.d.ts +39 -0
- package/dist/components/context-menu/ContextMenu.js +105 -0
- package/dist/components/context-menu/ContextMenuContent.d.ts +27 -0
- package/dist/components/context-menu/ContextMenuContent.js +97 -0
- package/dist/components/context-menu/ContextMenuTrigger.d.ts +26 -0
- package/dist/components/context-menu/ContextMenuTrigger.js +37 -0
- package/dist/components/context-menu/index.d.ts +20 -0
- package/dist/components/context-menu/types.d.ts +52 -0
- package/dist/components/context-menu/types.js +17 -0
- package/dist/components/context-ring/ContextRing.d.ts +33 -0
- package/dist/components/context-ring/ContextRing.js +257 -0
- package/dist/components/context-ring/index.d.ts +2 -0
- package/dist/components/copy-button/CopyButton.d.ts +39 -0
- package/dist/components/copy-button/CopyButton.js +124 -0
- package/dist/components/copy-button/index.d.ts +2 -0
- package/dist/components/date-picker/DatePicker.d.ts +58 -0
- package/dist/components/date-picker/DatePicker.js +331 -0
- package/dist/components/date-picker/date-utils.d.ts +39 -0
- package/dist/components/date-picker/date-utils.js +85 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/dialog/Dialog.d.ts +29 -0
- package/dist/components/dialog/Dialog.js +105 -0
- package/dist/components/dialog/DialogSurface.d.ts +2 -0
- package/dist/components/dialog/DialogSurface.js +98 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/types.d.ts +61 -0
- package/dist/components/dim-siblings/DimSiblings.d.ts +30 -0
- package/dist/components/dim-siblings/DimSiblings.js +47 -0
- package/dist/components/dim-siblings/index.d.ts +2 -0
- package/dist/components/direction-aware-hover/DirectionAwareHover.d.ts +10 -0
- package/dist/components/direction-aware-hover/DirectionAwareHover.js +185 -0
- package/dist/components/direction-aware-hover/index.d.ts +2 -0
- package/dist/components/displacement-text/DisplacementText.d.ts +26 -0
- package/dist/components/displacement-text/DisplacementText.js +185 -0
- package/dist/components/displacement-text/index.d.ts +2 -0
- package/dist/components/dock/Dock.d.ts +28 -0
- package/dist/components/dock/Dock.js +80 -0
- package/dist/components/dock/DockIcon.d.ts +17 -0
- package/dist/components/dock/DockIcon.js +38 -0
- package/dist/components/dock/DockSeparator.d.ts +6 -0
- package/dist/components/dock/DockSeparator.js +20 -0
- package/dist/components/dock/index.d.ts +7 -0
- package/dist/components/dock/types.d.ts +47 -0
- package/dist/components/dock/types.js +15 -0
- package/dist/components/drawer/Drawer.d.ts +34 -0
- package/dist/components/drawer/Drawer.js +237 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +38 -0
- package/dist/components/dropdown-menu/DropdownMenu.js +99 -0
- package/dist/components/dropdown-menu/DropdownMenuContent.d.ts +15 -0
- package/dist/components/dropdown-menu/DropdownMenuContent.js +111 -0
- package/dist/components/dropdown-menu/DropdownMenuItem.d.ts +26 -0
- package/dist/components/dropdown-menu/DropdownMenuItem.js +74 -0
- package/dist/components/dropdown-menu/DropdownMenuLabel.d.ts +15 -0
- package/dist/components/dropdown-menu/DropdownMenuLabel.js +18 -0
- package/dist/components/dropdown-menu/DropdownMenuSeparator.d.ts +6 -0
- package/dist/components/dropdown-menu/DropdownMenuSeparator.js +15 -0
- package/dist/components/dropdown-menu/DropdownMenuSub.d.ts +10 -0
- package/dist/components/dropdown-menu/DropdownMenuSub.js +110 -0
- package/dist/components/dropdown-menu/DropdownMenuSubContent.d.ts +15 -0
- package/dist/components/dropdown-menu/DropdownMenuSubContent.js +139 -0
- package/dist/components/dropdown-menu/DropdownMenuSubTrigger.d.ts +17 -0
- package/dist/components/dropdown-menu/DropdownMenuSubTrigger.js +104 -0
- package/dist/components/dropdown-menu/DropdownMenuTrigger.d.ts +16 -0
- package/dist/components/dropdown-menu/DropdownMenuTrigger.js +67 -0
- package/dist/components/dropdown-menu/index.d.ts +20 -0
- package/dist/components/dropdown-menu/menu-shared.d.ts +39 -0
- package/dist/components/dropdown-menu/menu-shared.js +48 -0
- package/dist/components/dropdown-menu/types.d.ts +159 -0
- package/dist/components/dropdown-menu/types.js +32 -0
- package/dist/components/editorial-engine/EditorialEngine.d.ts +21 -0
- package/dist/components/editorial-engine/EditorialEngine.js +68 -0
- package/dist/components/editorial-engine/engine.d.ts +7 -0
- package/dist/components/editorial-engine/engine.js +558 -0
- package/dist/components/editorial-engine/index.d.ts +2 -0
- package/dist/components/file-upload/FileUpload.d.ts +63 -0
- package/dist/components/file-upload/FileUpload.js +438 -0
- package/dist/components/file-upload/index.d.ts +2 -0
- package/dist/components/fireworks-hdr/FireworksHdr.d.ts +56 -0
- package/dist/components/fireworks-hdr/FireworksHdr.js +426 -0
- package/dist/components/fireworks-hdr/dev.d.ts +1 -0
- package/dist/components/fireworks-hdr/dev.js +8 -0
- package/dist/components/fireworks-hdr/fireworks-shared.d.ts +444 -0
- package/dist/components/fireworks-hdr/fireworks-shared.js +1205 -0
- package/dist/components/fireworks-hdr/index.d.ts +4 -0
- package/dist/components/fireworks-hdr/webgl2-renderer.d.ts +20 -0
- package/dist/components/fireworks-hdr/webgl2-renderer.js +517 -0
- package/dist/components/fireworks-hdr/webgpu-renderer.d.ts +51 -0
- package/dist/components/fireworks-hdr/webgpu-renderer.js +461 -0
- package/dist/components/fireworks-hdr/webgpu-types.d.ts +159 -0
- package/dist/components/flickering-grid/FlickeringGrid.d.ts +33 -0
- package/dist/components/flickering-grid/FlickeringGrid.js +154 -0
- package/dist/components/flickering-grid/index.d.ts +2 -0
- package/dist/components/flip-card/FlipCard.d.ts +8 -0
- package/dist/components/flip-card/FlipCard.js +35 -0
- package/dist/components/flip-card/index.d.ts +2 -0
- package/dist/components/flip-words/FlipWords.d.ts +16 -0
- package/dist/components/flip-words/FlipWords.js +82 -0
- package/dist/components/flip-words/index.d.ts +2 -0
- package/dist/components/fluid-cursor/FluidCursor.d.ts +61 -0
- package/dist/components/fluid-cursor/FluidCursor.js +1479 -0
- package/dist/components/fluid-cursor/fluid-shared.d.ts +74 -0
- package/dist/components/fluid-cursor/fluid-shared.js +120 -0
- package/dist/components/fluid-cursor/index.d.ts +8 -0
- package/dist/components/fluid-cursor/webgpu-engine.d.ts +36 -0
- package/dist/components/fluid-cursor/webgpu-engine.js +922 -0
- package/dist/components/focus/Focus.d.ts +24 -0
- package/dist/components/focus/Focus.js +103 -0
- package/dist/components/focus/index.d.ts +2 -0
- package/dist/components/form-field/FormField.d.ts +46 -0
- package/dist/components/form-field/FormField.js +151 -0
- package/dist/components/form-field/index.d.ts +2 -0
- package/dist/components/frosted-glass/FrostedGlass.d.ts +48 -0
- package/dist/components/frosted-glass/FrostedGlass.js +89 -0
- package/dist/components/frosted-glass/index.d.ts +2 -0
- package/dist/components/glare-card/GlareCard.d.ts +8 -0
- package/dist/components/glare-card/GlareCard.js +103 -0
- package/dist/components/glare-card/index.d.ts +2 -0
- package/dist/components/glow-border/GlowBorder.d.ts +8 -0
- package/dist/components/glow-border/GlowBorder.js +39 -0
- package/dist/components/glow-border/index.d.ts +2 -0
- package/dist/components/glowing-effect/GlowingEffect.d.ts +23 -0
- package/dist/components/glowing-effect/GlowingEffect.js +157 -0
- package/dist/components/glowing-effect/index.d.ts +2 -0
- package/dist/components/gradient-button/GradientButton.d.ts +28 -0
- package/dist/components/gradient-button/GradientButton.js +66 -0
- package/dist/components/gradient-button/index.d.ts +2 -0
- package/dist/components/hover-card/HoverCard.d.ts +57 -0
- package/dist/components/hover-card/HoverCard.js +139 -0
- package/dist/components/hover-card/index.d.ts +2 -0
- package/dist/components/hyper-text/HyperText.d.ts +25 -0
- package/dist/components/hyper-text/HyperText.js +102 -0
- package/dist/components/hyper-text/index.d.ts +2 -0
- package/dist/components/icon-button/IconButton.d.ts +46 -0
- package/dist/components/icon-button/IconButton.js +62 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/image-generation/ImageGeneration.d.ts +33 -0
- package/dist/components/image-generation/ImageGeneration.js +131 -0
- package/dist/components/image-generation/index.d.ts +2 -0
- package/dist/components/image-trail-cursor/ImageTrailCursor.d.ts +15 -0
- package/dist/components/image-trail-cursor/ImageTrailCursor.js +75 -0
- package/dist/components/image-trail-cursor/index.d.ts +3 -0
- package/dist/components/image-trail-cursor/trail-variants.d.ts +112 -0
- package/dist/components/image-trail-cursor/trail-variants.js +787 -0
- package/dist/components/inline-citation/InlineCitation.d.ts +23 -0
- package/dist/components/inline-citation/InlineCitation.js +179 -0
- package/dist/components/inline-citation/index.d.ts +2 -0
- package/dist/components/input/Input.d.ts +41 -0
- package/dist/components/input/Input.js +74 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/interactive-grid-pattern/InteractiveGridPattern.d.ts +17 -0
- package/dist/components/interactive-grid-pattern/InteractiveGridPattern.js +89 -0
- package/dist/components/interactive-grid-pattern/index.d.ts +2 -0
- package/dist/components/interactive-hover-button/InteractiveHoverButton.d.ts +18 -0
- package/dist/components/interactive-hover-button/InteractiveHoverButton.js +66 -0
- package/dist/components/interactive-hover-button/index.d.ts +2 -0
- package/dist/components/label/Label.d.ts +18 -0
- package/dist/components/label/Label.js +28 -0
- package/dist/components/label/index.d.ts +2 -0
- package/dist/components/letter-pullup/LetterPullup.d.ts +16 -0
- package/dist/components/letter-pullup/LetterPullup.js +27 -0
- package/dist/components/letter-pullup/index.d.ts +2 -0
- package/dist/components/line-hover-link/LineHoverLink.d.ts +33 -0
- package/dist/components/line-hover-link/LineHoverLink.js +69 -0
- package/dist/components/line-hover-link/index.d.ts +2 -0
- package/dist/components/line-reveal/LineReveal.d.ts +31 -0
- package/dist/components/line-reveal/LineReveal.js +117 -0
- package/dist/components/line-reveal/index.d.ts +2 -0
- package/dist/components/line-shadow-text/LineShadowText.d.ts +18 -0
- package/dist/components/line-shadow-text/LineShadowText.js +26 -0
- package/dist/components/line-shadow-text/index.d.ts +2 -0
- package/dist/components/link/Link.d.ts +30 -0
- package/dist/components/link/Link.js +82 -0
- package/dist/components/link/index.d.ts +2 -0
- package/dist/components/liquid-glass/LiquidGlass.d.ts +49 -0
- package/dist/components/liquid-glass/LiquidGlass.js +165 -0
- package/dist/components/liquid-glass/index.d.ts +2 -0
- package/dist/components/liquid-text/LiquidText.d.ts +35 -0
- package/dist/components/liquid-text/LiquidText.js +882 -0
- package/dist/components/liquid-text/index.d.ts +2 -0
- package/dist/components/logo-cloud/AnimatedLogoCloud.d.ts +13 -0
- package/dist/components/logo-cloud/AnimatedLogoCloud.js +38 -0
- package/dist/components/logo-cloud/IconLogoCloud.d.ts +10 -0
- package/dist/components/logo-cloud/IconLogoCloud.js +20 -0
- package/dist/components/logo-cloud/StaticLogoCloud.d.ts +28 -0
- package/dist/components/logo-cloud/StaticLogoCloud.js +45 -0
- package/dist/components/logo-cloud/index.d.ts +6 -0
- package/dist/components/magnetic/Magnetic.d.ts +35 -0
- package/dist/components/magnetic/Magnetic.js +113 -0
- package/dist/components/magnetic/index.d.ts +2 -0
- package/dist/components/marquee/Marquee.d.ts +16 -0
- package/dist/components/marquee/Marquee.js +39 -0
- package/dist/components/marquee/ReviewCard.d.ts +8 -0
- package/dist/components/marquee/ReviewCard.js +17 -0
- package/dist/components/marquee/index.d.ts +4 -0
- package/dist/components/matrix-rain/MatrixRain.d.ts +35 -0
- package/dist/components/matrix-rain/MatrixRain.js +130 -0
- package/dist/components/matrix-rain/index.d.ts +2 -0
- package/dist/components/meteors/Meteors.d.ts +21 -0
- package/dist/components/meteors/Meteors.js +45 -0
- package/dist/components/meteors/index.d.ts +2 -0
- package/dist/components/mosaic-glow/MosaicGlow.d.ts +47 -0
- package/dist/components/mosaic-glow/MosaicGlow.js +438 -0
- package/dist/components/mosaic-glow/index.d.ts +2 -0
- package/dist/components/mosaic-glow/mosaic-glow-core.d.ts +94 -0
- package/dist/components/mosaic-glow/mosaic-glow-core.js +190 -0
- package/dist/components/navbar/Navbar.d.ts +25 -0
- package/dist/components/navbar/Navbar.js +27 -0
- package/dist/components/navbar/NavbarLink.d.ts +37 -0
- package/dist/components/navbar/NavbarLink.js +48 -0
- package/dist/components/navbar/index.d.ts +4 -0
- package/dist/components/navigation-menu/NavigationMenu.d.ts +28 -0
- package/dist/components/navigation-menu/NavigationMenu.js +202 -0
- package/dist/components/navigation-menu/NavigationMenuContent.d.ts +8 -0
- package/dist/components/navigation-menu/NavigationMenuContent.js +77 -0
- package/dist/components/navigation-menu/NavigationMenuItem.d.ts +20 -0
- package/dist/components/navigation-menu/NavigationMenuItem.js +18 -0
- package/dist/components/navigation-menu/NavigationMenuLink.d.ts +31 -0
- package/dist/components/navigation-menu/NavigationMenuLink.js +41 -0
- package/dist/components/navigation-menu/NavigationMenuList.d.ts +8 -0
- package/dist/components/navigation-menu/NavigationMenuList.js +33 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.d.ts +8 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.js +90 -0
- package/dist/components/navigation-menu/index.d.ts +14 -0
- package/dist/components/navigation-menu/types.d.ts +107 -0
- package/dist/components/navigation-menu/types.js +32 -0
- package/dist/components/neon-border/NeonBorder.d.ts +22 -0
- package/dist/components/neon-border/NeonBorder.js +50 -0
- package/dist/components/neon-border/index.d.ts +2 -0
- package/dist/components/noise-reveal/NoiseReveal.d.ts +29 -0
- package/dist/components/noise-reveal/NoiseReveal.js +329 -0
- package/dist/components/noise-reveal/index.d.ts +2 -0
- package/dist/components/number-input/NumberInput.d.ts +40 -0
- package/dist/components/number-input/NumberInput.js +207 -0
- package/dist/components/number-input/index.d.ts +2 -0
- package/dist/components/number-ticker/NumberTicker.d.ts +22 -0
- package/dist/components/number-ticker/NumberTicker.js +106 -0
- package/dist/components/number-ticker/index.d.ts +2 -0
- package/dist/components/pagination/Pagination.d.ts +43 -0
- package/dist/components/pagination/Pagination.js +156 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/pagination-range.d.ts +11 -0
- package/dist/components/pagination/pagination-range.js +35 -0
- package/dist/components/password-input/PasswordInput.d.ts +56 -0
- package/dist/components/password-input/PasswordInput.js +246 -0
- package/dist/components/password-input/index.d.ts +2 -0
- package/dist/components/pixel-loader/PixelLoader.d.ts +18 -0
- package/dist/components/pixel-loader/PixelLoader.js +56 -0
- package/dist/components/pixel-loader/index.d.ts +2 -0
- package/dist/components/popover/Popover.d.ts +49 -0
- package/dist/components/popover/Popover.js +81 -0
- package/dist/components/popover/PopoverContent.d.ts +21 -0
- package/dist/components/popover/PopoverContent.js +78 -0
- package/dist/components/popover/index.d.ts +6 -0
- package/dist/components/popover/types.d.ts +64 -0
- package/dist/components/popover/types.js +17 -0
- package/dist/components/presence/Presence.d.ts +40 -0
- package/dist/components/presence/Presence.js +49 -0
- package/dist/components/presence/index.d.ts +2 -0
- package/dist/components/pressable/Pressable.d.ts +27 -0
- package/dist/components/pressable/Pressable.js +86 -0
- package/dist/components/pressable/index.d.ts +2 -0
- package/dist/components/prompt-suggestions/PromptSuggestions.d.ts +25 -0
- package/dist/components/prompt-suggestions/PromptSuggestions.js +68 -0
- package/dist/components/prompt-suggestions/index.d.ts +2 -0
- package/dist/components/pulse-beam/PulseBeam.d.ts +44 -0
- package/dist/components/pulse-beam/PulseBeam.js +197 -0
- package/dist/components/pulse-beam/index.d.ts +2 -0
- package/dist/components/pulse-beam/pulse-beam-data.d.ts +81 -0
- package/dist/components/pulse-beam/pulse-beam-data.js +306 -0
- package/dist/components/pulse-beam/pulse-beam-loop.d.ts +26 -0
- package/dist/components/pulse-beam/pulse-beam-loop.js +58 -0
- package/dist/components/radio-group/RadioGroup.d.ts +56 -0
- package/dist/components/radio-group/RadioGroup.js +82 -0
- package/dist/components/radio-group/RadioGroupItem.d.ts +21 -0
- package/dist/components/radio-group/RadioGroupItem.js +47 -0
- package/dist/components/radio-group/index.d.ts +6 -0
- package/dist/components/radio-group/types.d.ts +50 -0
- package/dist/components/radio-group/types.js +7 -0
- package/dist/components/rainbow-button/RainbowButton.d.ts +21 -0
- package/dist/components/rainbow-button/RainbowButton.js +59 -0
- package/dist/components/rainbow-button/index.d.ts +2 -0
- package/dist/components/reasoning-panel/ReasoningPanel.d.ts +38 -0
- package/dist/components/reasoning-panel/ReasoningPanel.js +172 -0
- package/dist/components/reasoning-panel/index.d.ts +2 -0
- package/dist/components/recommendation-card/RecommendationCard.d.ts +53 -0
- package/dist/components/recommendation-card/RecommendationCard.js +234 -0
- package/dist/components/recommendation-card/index.d.ts +2 -0
- package/dist/components/reveal/Reveal.d.ts +36 -0
- package/dist/components/reveal/Reveal.js +138 -0
- package/dist/components/reveal/index.d.ts +2 -0
- package/dist/components/ripple/Ripple.d.ts +11 -0
- package/dist/components/ripple/Ripple.js +45 -0
- package/dist/components/ripple/index.d.ts +2 -0
- package/dist/components/ripple-button/RippleButton.d.ts +17 -0
- package/dist/components/ripple-button/RippleButton.js +77 -0
- package/dist/components/ripple-button/index.d.ts +2 -0
- package/dist/components/scroll-anchor/ScrollAnchor.d.ts +33 -0
- package/dist/components/scroll-anchor/ScrollAnchor.js +99 -0
- package/dist/components/scroll-anchor/index.d.ts +2 -0
- package/dist/components/scroll-progress/ScrollProgress.d.ts +39 -0
- package/dist/components/scroll-progress/ScrollProgress.js +118 -0
- package/dist/components/scroll-progress/index.d.ts +2 -0
- package/dist/components/search-input/SearchInput.d.ts +56 -0
- package/dist/components/search-input/SearchInput.js +192 -0
- package/dist/components/search-input/index.d.ts +2 -0
- package/dist/components/select/Select.d.ts +44 -0
- package/dist/components/select/Select.js +255 -0
- package/dist/components/select/SelectPanel.d.ts +33 -0
- package/dist/components/select/SelectPanel.js +108 -0
- package/dist/components/select/index.d.ts +3 -0
- package/dist/components/select/types.d.ts +83 -0
- package/dist/components/select/types.js +8 -0
- package/dist/components/sheet/Sheet.d.ts +40 -0
- package/dist/components/sheet/Sheet.js +183 -0
- package/dist/components/sheet/index.d.ts +2 -0
- package/dist/components/shimmer-button/ShimmerButton.d.ts +26 -0
- package/dist/components/shimmer-button/ShimmerButton.js +69 -0
- package/dist/components/shimmer-button/index.d.ts +2 -0
- package/dist/components/sidebar/Sidebar.d.ts +17 -0
- package/dist/components/sidebar/Sidebar.js +27 -0
- package/dist/components/sidebar/SidebarFooter.d.ts +10 -0
- package/dist/components/sidebar/SidebarFooter.js +31 -0
- package/dist/components/sidebar/SidebarGroup.d.ts +10 -0
- package/dist/components/sidebar/SidebarGroup.js +28 -0
- package/dist/components/sidebar/SidebarItem.d.ts +33 -0
- package/dist/components/sidebar/SidebarItem.js +81 -0
- package/dist/components/sidebar/SidebarSeparator.d.ts +5 -0
- package/dist/components/sidebar/SidebarSeparator.js +13 -0
- package/dist/components/sidebar/index.d.ts +12 -0
- package/dist/components/sidebar/types.d.ts +36 -0
- package/dist/components/sidebar/types.js +7 -0
- package/dist/components/skeleton/Skeleton.d.ts +35 -0
- package/dist/components/skeleton/Skeleton.js +106 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/slider/Slider.d.ts +32 -0
- package/dist/components/slider/Slider.js +119 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/smooth-cursor/SmoothCursor.d.ts +18 -0
- package/dist/components/smooth-cursor/SmoothCursor.js +186 -0
- package/dist/components/smooth-cursor/index.d.ts +2 -0
- package/dist/components/sources/SourceCard.d.ts +21 -0
- package/dist/components/sources/SourceCard.js +48 -0
- package/dist/components/sources/Sources.d.ts +31 -0
- package/dist/components/sources/Sources.js +39 -0
- package/dist/components/sources/SourcesList.d.ts +13 -0
- package/dist/components/sources/SourcesList.js +42 -0
- package/dist/components/sources/SourcesTrigger.d.ts +11 -0
- package/dist/components/sources/SourcesTrigger.js +50 -0
- package/dist/components/sources/index.d.ts +10 -0
- package/dist/components/sources/types.d.ts +45 -0
- package/dist/components/sources/types.js +7 -0
- package/dist/components/sparkles/Sparkles.d.ts +35 -0
- package/dist/components/sparkles/Sparkles.js +112 -0
- package/dist/components/sparkles/index.d.ts +2 -0
- package/dist/components/sparkles-text/SparklesText.d.ts +28 -0
- package/dist/components/sparkles-text/SparklesText.js +84 -0
- package/dist/components/sparkles-text/index.d.ts +2 -0
- package/dist/components/status-morph/StatusMorph.d.ts +47 -0
- package/dist/components/status-morph/StatusMorph.js +110 -0
- package/dist/components/status-morph/index.d.ts +2 -0
- package/dist/components/stepper/Step.d.ts +24 -0
- package/dist/components/stepper/Step.js +152 -0
- package/dist/components/stepper/Stepper.d.ts +38 -0
- package/dist/components/stepper/Stepper.js +79 -0
- package/dist/components/stepper/index.d.ts +6 -0
- package/dist/components/stepper/types.d.ts +66 -0
- package/dist/components/stepper/types.js +7 -0
- package/dist/components/sticky-scroll/StickyScroll.d.ts +40 -0
- package/dist/components/sticky-scroll/StickyScroll.js +163 -0
- package/dist/components/sticky-scroll/index.d.ts +2 -0
- package/dist/components/streaming-text/StreamingText.d.ts +20 -0
- package/dist/components/streaming-text/StreamingText.js +32 -0
- package/dist/components/streaming-text/index.d.ts +2 -0
- package/dist/components/subagent-list/SubagentList.d.ts +28 -0
- package/dist/components/subagent-list/SubagentList.js +167 -0
- package/dist/components/subagent-list/index.d.ts +2 -0
- package/dist/components/switch/Switch.d.ts +55 -0
- package/dist/components/switch/Switch.js +77 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/tabs/Tabs.d.ts +43 -0
- package/dist/components/tabs/Tabs.js +123 -0
- package/dist/components/tabs/TabsContent.d.ts +26 -0
- package/dist/components/tabs/TabsContent.js +64 -0
- package/dist/components/tabs/TabsList.d.ts +16 -0
- package/dist/components/tabs/TabsList.js +152 -0
- package/dist/components/tabs/TabsTrigger.d.ts +19 -0
- package/dist/components/tabs/TabsTrigger.js +138 -0
- package/dist/components/tabs/index.d.ts +10 -0
- package/dist/components/tabs/types.d.ts +94 -0
- package/dist/components/tabs/types.js +7 -0
- package/dist/components/terminal-block/TerminalBlock.d.ts +27 -0
- package/dist/components/terminal-block/TerminalBlock.js +120 -0
- package/dist/components/terminal-block/ansi.d.ts +30 -0
- package/dist/components/terminal-block/ansi.js +114 -0
- package/dist/components/terminal-block/index.d.ts +2 -0
- package/dist/components/terminal-text/TerminalText.d.ts +11 -0
- package/dist/components/terminal-text/TerminalText.js +140 -0
- package/dist/components/terminal-text/index.d.ts +2 -0
- package/dist/components/text-generate-effect/TextGenerateEffect.d.ts +9 -0
- package/dist/components/text-generate-effect/TextGenerateEffect.js +58 -0
- package/dist/components/text-generate-effect/index.d.ts +2 -0
- package/dist/components/text-reveal-card/TextRevealCard.d.ts +21 -0
- package/dist/components/text-reveal-card/TextRevealCard.js +107 -0
- package/dist/components/text-reveal-card/TextRevealStars.d.ts +25 -0
- package/dist/components/text-reveal-card/TextRevealStars.js +59 -0
- package/dist/components/text-reveal-card/index.d.ts +4 -0
- package/dist/components/text-roll/TextRoll.d.ts +43 -0
- package/dist/components/text-roll/TextRoll.js +242 -0
- package/dist/components/text-roll/index.d.ts +2 -0
- package/dist/components/text-roll/roll-transitions.d.ts +74 -0
- package/dist/components/text-roll/roll-transitions.js +31 -0
- package/dist/components/textarea/Textarea.d.ts +48 -0
- package/dist/components/textarea/Textarea.js +129 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/thinking-indicator/ThinkingIndicator.d.ts +26 -0
- package/dist/components/thinking-indicator/ThinkingIndicator.js +60 -0
- package/dist/components/thinking-indicator/index.d.ts +2 -0
- package/dist/components/thread-list/ThreadList.d.ts +44 -0
- package/dist/components/thread-list/ThreadList.js +178 -0
- package/dist/components/thread-list/index.d.ts +2 -0
- package/dist/components/time-picker/TimePicker.d.ts +44 -0
- package/dist/components/time-picker/TimePicker.js +254 -0
- package/dist/components/time-picker/TimePickerPanel.d.ts +30 -0
- package/dist/components/time-picker/TimePickerPanel.js +94 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/time-utils.d.ts +33 -0
- package/dist/components/time-picker/time-utils.js +65 -0
- package/dist/components/time-picker/types.d.ts +53 -0
- package/dist/components/time-picker/types.js +10 -0
- package/dist/components/timeline/Timeline.d.ts +18 -0
- package/dist/components/timeline/Timeline.js +96 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/toast/Toast.d.ts +16 -0
- package/dist/components/toast/Toast.js +99 -0
- package/dist/components/toast/Toaster.d.ts +19 -0
- package/dist/components/toast/Toaster.js +147 -0
- package/dist/components/toast/index.d.ts +6 -0
- package/dist/components/toast/store.d.ts +102 -0
- package/dist/components/toast/store.js +118 -0
- package/dist/components/toggle/Toggle.d.ts +28 -0
- package/dist/components/toggle/Toggle.js +69 -0
- package/dist/components/toggle/index.d.ts +2 -0
- package/dist/components/toggle-group/ToggleGroup.d.ts +42 -0
- package/dist/components/toggle-group/ToggleGroup.js +150 -0
- package/dist/components/toggle-group/ToggleGroupItem.d.ts +21 -0
- package/dist/components/toggle-group/ToggleGroupItem.js +100 -0
- package/dist/components/toggle-group/index.d.ts +6 -0
- package/dist/components/toggle-group/types.d.ts +75 -0
- package/dist/components/toggle-group/types.js +7 -0
- package/dist/components/tool-call/ToolCall.d.ts +39 -0
- package/dist/components/tool-call/ToolCall.js +195 -0
- package/dist/components/tool-call/index.d.ts +2 -0
- package/dist/components/tool-timeline/ToolTimeline.d.ts +31 -0
- package/dist/components/tool-timeline/ToolTimeline.js +99 -0
- package/dist/components/tool-timeline/index.d.ts +2 -0
- package/dist/components/tooltip/Tooltip.d.ts +36 -0
- package/dist/components/tooltip/Tooltip.js +214 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tracing-beam/TracingBeam.d.ts +11 -0
- package/dist/components/tracing-beam/TracingBeam.js +163 -0
- package/dist/components/tracing-beam/index.d.ts +2 -0
- package/dist/components/typing-indicator/TypingIndicator.d.ts +17 -0
- package/dist/components/typing-indicator/TypingIndicator.js +47 -0
- package/dist/components/typing-indicator/index.d.ts +2 -0
- package/dist/components/voice-input/VoiceInput.d.ts +60 -0
- package/dist/components/voice-input/VoiceInput.js +268 -0
- package/dist/components/voice-input/index.d.ts +2 -0
- package/dist/components/web-search/WebSearch.d.ts +37 -0
- package/dist/components/web-search/WebSearch.js +135 -0
- package/dist/components/web-search/index.d.ts +2 -0
- package/dist/index.d.ts +148 -0
- package/dist/index.js +489 -0
- package/dist/internals/Portal.d.ts +35 -0
- package/dist/internals/Portal.js +37 -0
- package/dist/internals/StreamText.d.ts +20 -0
- package/dist/internals/StreamText.js +25 -0
- package/dist/internals/ai-types.d.ts +117 -0
- package/dist/internals/anchor-position.d.ts +79 -0
- package/dist/internals/anchor-position.js +154 -0
- package/dist/internals/calendar-core.d.ts +26 -0
- package/dist/internals/calendar-core.js +57 -0
- package/dist/internals/diff.d.ts +38 -0
- package/dist/internals/diff.js +176 -0
- package/dist/internals/dismissable.d.ts +76 -0
- package/dist/internals/dismissable.js +105 -0
- package/dist/internals/dom/context.d.ts +16 -0
- package/dist/internals/dom/context.js +20 -0
- package/dist/internals/dom/ssr.d.ts +21 -0
- package/dist/internals/dom/ssr.js +21 -0
- package/dist/internals/dom/types.d.ts +9 -0
- package/dist/internals/dom/use-composed-refs.d.ts +15 -0
- package/dist/internals/dom/use-composed-refs.js +34 -0
- package/dist/internals/dom/use-element-ref.d.ts +11 -0
- package/dist/internals/dom/use-element-ref.js +12 -0
- package/dist/internals/dom/use-event-callback.d.ts +14 -0
- package/dist/internals/dom/use-event-callback.js +12 -0
- package/dist/internals/dom/use-inert-attribute.d.ts +26 -0
- package/dist/internals/dom/use-inert-attribute.js +22 -0
- package/dist/internals/dom/use-live-ref.d.ts +10 -0
- package/dist/internals/dom/use-live-ref.js +12 -0
- package/dist/internals/field.d.ts +136 -0
- package/dist/internals/field.js +33 -0
- package/dist/internals/float.d.ts +47 -0
- package/dist/internals/float.js +31 -0
- package/dist/internals/focus-trap.d.ts +82 -0
- package/dist/internals/focus-trap.js +145 -0
- package/dist/internals/host.d.ts +38 -0
- package/dist/internals/host.js +24 -0
- package/dist/internals/listbox.d.ts +101 -0
- package/dist/internals/listbox.js +171 -0
- package/dist/internals/markdown/Markdown.d.ts +22 -0
- package/dist/internals/markdown/Markdown.js +53 -0
- package/dist/internals/markdown/MarkdownInline.d.ts +5 -0
- package/dist/internals/markdown/MarkdownInline.js +40 -0
- package/dist/internals/markdown.d.ts +66 -0
- package/dist/internals/markdown.js +467 -0
- package/dist/internals/menu.d.ts +121 -0
- package/dist/internals/menu.js +217 -0
- package/dist/internals/motion/anchored.d.ts +104 -0
- package/dist/internals/motion/anchored.js +44 -0
- package/dist/internals/motion/animate.d.ts +92 -0
- package/dist/internals/motion/animate.js +84 -0
- package/dist/internals/motion/easing.d.ts +20 -0
- package/dist/internals/motion/easing.js +13 -0
- package/dist/internals/motion/haptics.d.ts +42 -0
- package/dist/internals/motion/haptics.js +29 -0
- package/dist/internals/motion/in-view.d.ts +67 -0
- package/dist/internals/motion/in-view.js +97 -0
- package/dist/internals/motion/media-query.d.ts +50 -0
- package/dist/internals/motion/media-query.js +54 -0
- package/dist/internals/motion/presence.d.ts +108 -0
- package/dist/internals/motion/presence.js +197 -0
- package/dist/internals/motion/presets.d.ts +34 -0
- package/dist/internals/motion/presets.js +19 -0
- package/dist/internals/motion/raf.d.ts +35 -0
- package/dist/internals/motion/raf.js +27 -0
- package/dist/internals/motion/stagger.d.ts +32 -0
- package/dist/internals/motion/stagger.js +15 -0
- package/dist/internals/motion/tokens.d.ts +97 -0
- package/dist/internals/motion/tokens.js +18 -0
- package/dist/internals/motion/transitions.d.ts +66 -0
- package/dist/internals/motion/transitions.js +41 -0
- package/dist/internals/motion/types.d.ts +17 -0
- package/dist/internals/relative-time.d.ts +25 -0
- package/dist/internals/relative-time.js +46 -0
- package/dist/internals/scroll-lock.d.ts +26 -0
- package/dist/internals/scroll-lock.js +65 -0
- package/dist/internals/use-anchor-position.d.ts +54 -0
- package/dist/internals/use-anchor-position.js +87 -0
- package/dist/internals/use-autoscroll.d.ts +43 -0
- package/dist/internals/use-autoscroll.js +128 -0
- package/dist/internals/use-copy.d.ts +54 -0
- package/dist/internals/use-copy.js +67 -0
- package/dist/internals/use-elapsed.d.ts +96 -0
- package/dist/internals/use-elapsed.js +195 -0
- package/dist/internals/use-float.d.ts +49 -0
- package/dist/internals/use-float.js +150 -0
- package/dist/internals/use-id.d.ts +22 -0
- package/dist/internals/use-id.js +20 -0
- package/dist/internals/use-text-stream.d.ts +94 -0
- package/dist/internals/use-text-stream.js +133 -0
- package/dist/internals/waveform-core.d.ts +33 -0
- package/dist/internals/waveform-core.js +39 -0
- package/dist/sound/SoundToggle.d.ts +23 -0
- package/dist/sound/SoundToggle.js +96 -0
- package/dist/sound/engine.d.ts +67 -0
- package/dist/sound/engine.js +370 -0
- package/dist/sound/index.d.ts +7 -0
- package/dist/sound/sound-feedback.d.ts +77 -0
- package/dist/sound/sound-feedback.js +152 -0
- package/dist/sound/sound.d.ts +98 -0
- package/dist/sound/sound.js +309 -0
- package/dist/sound/themes.d.ts +19 -0
- package/dist/sound/themes.js +355 -0
- package/dist/sound/types.d.ts +125 -0
- package/dist/sound/types.js +54 -0
- package/dist/sound/use-sound.d.ts +53 -0
- package/dist/sound/use-sound.js +82 -0
- package/dist/styles.css +7975 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +8 -0
- package/package.json +96 -0
- package/tailwind.css +132 -0
package/README.md
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
# fancy-ui-react
|
|
2
|
+
|
|
3
|
+
React counterpart of [`fancy-ui-svelte`](https://www.npmjs.com/package/fancy-ui-svelte) —
|
|
4
|
+
same components, same visual contract, ported from the Svelte 5 reference
|
|
5
|
+
implementation that lives at the root of this repo.
|
|
6
|
+
|
|
7
|
+
Status: at parity. All 144 components of `fancy-ui-svelte` are ported and
|
|
8
|
+
exported from the package root, alongside the `sound` family; the cameleon
|
|
9
|
+
skin engine (FancyProvider + primitives + skins) ships on the
|
|
10
|
+
`fancy-ui-react/cameleon` subpath. The Svelte package remains the reference;
|
|
11
|
+
each React component is a faithful transpose (see `PORTING.md` for the law
|
|
12
|
+
that governs ports), and every deliberate difference is listed under
|
|
13
|
+
[Divergences](#divergences-from-the-svelte-api) below.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install fancy-ui-react
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Peer dependencies: `react` / `react-dom` 18 or 19, `tailwindcss` 4. TypeScript
|
|
22
|
+
is an optional peer at 5.0 or later — the type barrel uses `export type *`,
|
|
23
|
+
which is 5.0 syntax and is emitted verbatim into `dist/index.d.ts`.
|
|
24
|
+
|
|
25
|
+
Three things about the package's shape, because each of them is a decision
|
|
26
|
+
rather than an oversight:
|
|
27
|
+
|
|
28
|
+
- **ESM only.** There is no `require` condition and no CJS build. A TypeScript
|
|
29
|
+
project on `moduleResolution: node16` that emits CommonJS gets TS1479 on the
|
|
30
|
+
bare import; the fix is on that side (`"module": "esnext"`, or a dynamic
|
|
31
|
+
`import()`), not here.
|
|
32
|
+
- **Four entry points, no deep imports.** `fancy-ui-react`,
|
|
33
|
+
`fancy-ui-react/cameleon`, `fancy-ui-react/styles.css` and
|
|
34
|
+
`fancy-ui-react/tailwind.css`, plus `fancy-ui-react/package.json` for tooling
|
|
35
|
+
that resolves a manifest by specifier. Everything else is blocked by the
|
|
36
|
+
exports map on purpose: the build keeps one module per source file, so
|
|
37
|
+
importing one component from the package root tree-shakes the rest away, and
|
|
38
|
+
the alternative would freeze `dist/`'s internal folder layout as public API.
|
|
39
|
+
- **0.x, so minors can break.** Until 1.0 a minor version may change a
|
|
40
|
+
component's API; patches never do. Every deliberate difference from the Svelte
|
|
41
|
+
package is listed under [Divergences](#divergences-from-the-svelte-api).
|
|
42
|
+
|
|
43
|
+
## Setup
|
|
44
|
+
|
|
45
|
+
```css
|
|
46
|
+
/* app.css */
|
|
47
|
+
@import "tailwindcss";
|
|
48
|
+
@import "fancy-ui-react/tailwind.css"; /* lets Tailwind scan the shipped sources */
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import "fancy-ui-react/styles.css"; // keyframes + component-scoped CSS
|
|
53
|
+
import { RainbowButton, Marquee } from "fancy-ui-react";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Those two imports are the whole setup. `tailwind.css` also declares every
|
|
57
|
+
semantic colour the components spend — the full shadcn token set:
|
|
58
|
+
`background`, `foreground`, `card`, `card-foreground`, `popover`,
|
|
59
|
+
`popover-foreground`, `primary`, `primary-foreground`, `secondary`,
|
|
60
|
+
`secondary-foreground`, `muted`, `muted-foreground`, `accent`,
|
|
61
|
+
`accent-foreground`, `destructive`, `border`, `input`, `ring`. None of them
|
|
62
|
+
exist in Tailwind's default palette, and Tailwind v4 emits no rule at all for
|
|
63
|
+
an undeclared colour name, so without them `bg-primary` and friends compile to
|
|
64
|
+
nothing. They are wired with `@theme inline`, so the utilities resolve the
|
|
65
|
+
variables at use time: an app that already defines the shadcn token set keeps
|
|
66
|
+
its own colours automatically. The defaults ship in `@layer base`, which an
|
|
67
|
+
unlayered `:root` in your app overrides whatever the import order.
|
|
68
|
+
|
|
69
|
+
## Dark mode
|
|
70
|
+
|
|
71
|
+
Out of the box the package follows the operating-system preference: `dark:`
|
|
72
|
+
utilities and the components' `light-dark()` colours both switch with
|
|
73
|
+
`prefers-color-scheme`, so an app that never touches dark mode already looks
|
|
74
|
+
right on a dark desktop. To control it yourself, put `dark` or `light` on
|
|
75
|
+
`<html>` (or on any ancestor of the subtree you want to force) and both halves
|
|
76
|
+
follow the class instead:
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<html class="dark">
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`tailwind.css` is what makes that work, in three parts: it declares the `.dark`
|
|
83
|
+
token block, it declares a `dark` variant that matches a `.dark` ancestor OR
|
|
84
|
+
the media query (unless a `.light` ancestor opts out), and it sets
|
|
85
|
+
`color-scheme: light dark` on `:root` with `.dark` / `.light` overrides so the
|
|
86
|
+
components' `light-dark()` colours — and the browser's own form controls,
|
|
87
|
+
scrollbars and caret — resolve the same way. An app that declares its own
|
|
88
|
+
`@custom-variant dark` after the import keeps its own definition.
|
|
89
|
+
|
|
90
|
+
## Server Components
|
|
91
|
+
|
|
92
|
+
Components and hooks are client modules. Import them from a Server Component
|
|
93
|
+
file and they cross the boundary as client references, which is exactly what
|
|
94
|
+
you want: no `"use client"` wrapper of your own, and no `useState` running on
|
|
95
|
+
the server. The `examples/next-app` App Router example in this repo is a
|
|
96
|
+
Server Component that imports the whole barrel, and it is part of CI.
|
|
97
|
+
|
|
98
|
+
What a Server Component can **call and read** directly, because these modules
|
|
99
|
+
ship without the boundary:
|
|
100
|
+
|
|
101
|
+
| Export | From |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `cn` | the class-merge helper (clsx + tailwind-merge) |
|
|
104
|
+
| `SOUND_CUES`, `SOUND_LIMITS`, `SOUND_MIN_INTERVAL_MS`, `SOUND_STORAGE_KEY`, `SOUND_THEME_NAMES`, `DEFAULT_SOUND_PREFERENCES` | the sound constant tables |
|
|
105
|
+
| `SOUND_THEMES`, `FANCY_SOUND_THEME`, `getSoundTheme`, `validateSoundTheme` | the shipped sound themes and their validators |
|
|
106
|
+
| `BOOK_COLOR_MAP`, `BOOK_SIZE_MAP`, `BOOK_RADIUS_MAP`, `BOOK_SHADOW_SIZE_MAP` | the `Book` lookup tables |
|
|
107
|
+
|
|
108
|
+
Everything else — every component, every hook, the `sound` controller, `toast`
|
|
109
|
+
and `dismissToast`, the cameleon skins — is a client module. Calling one from
|
|
110
|
+
the server throws "Attempted to call … from the server", which is the right
|
|
111
|
+
answer: the sound controller and the toast store are browser singletons, and a
|
|
112
|
+
skin has to arrive at `<FancyProvider>` as a client reference or React refuses
|
|
113
|
+
to serialize its recipe functions.
|
|
114
|
+
|
|
115
|
+
## Compatibility
|
|
116
|
+
|
|
117
|
+
- **React 18 and 19.** Both are in the peer range and both are in CI: one job
|
|
118
|
+
runs the suite on 19, another packs the tarball, installs it next to
|
|
119
|
+
`@types/react@18`, compiles every emitted declaration with `skipLibCheck`
|
|
120
|
+
off, and runs the hydration sweep and the `internals` / `sound` suites
|
|
121
|
+
against React 18.
|
|
122
|
+
- **TypeScript 5.0+, `@types/react` 18.3+.** Below either, the package's own
|
|
123
|
+
declarations fail to parse or resolve and everything from it reads as `any`.
|
|
124
|
+
- **Tailwind CSS 4.** `tailwind.css` uses v4 at-rules (`@source`,
|
|
125
|
+
`@theme inline`, `@custom-variant`) and has no v3 equivalent.
|
|
126
|
+
- **The cameleon subpath is barrel-only.** `fancy-ui-react/cameleon` ships the
|
|
127
|
+
skin engine, the primitives and the five skins. There is no `./cameleon/*`
|
|
128
|
+
wildcard for a single skin, and the retro-OS component kit that the Svelte
|
|
129
|
+
package publishes as `fancy-ui-svelte/cameleon/retro-kit` has no React
|
|
130
|
+
counterpart.
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
Workspace member of the repo's pnpm workspace — one `pnpm install` at the
|
|
135
|
+
repo root covers it.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pnpm install # at the repo root
|
|
139
|
+
pnpm --filter fancy-ui-react test # vitest + testing-library
|
|
140
|
+
pnpm --filter fancy-ui-react check # tsc --noEmit
|
|
141
|
+
pnpm --filter fancy-ui-react build # vite lib build + d.ts via tsc, then the dist gates
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`build` does more than build. After Vite and `tsc` it runs four scripts in
|
|
145
|
+
`react/scripts/`, each guarding something no other gate can see:
|
|
146
|
+
|
|
147
|
+
| Script | What it stops |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| `strip-dts-css-imports.mjs` | `tsc` copies each component's `import "./x.css"` into its `.d.ts`, naming a file dist does not ship — one TS2307 per component for any consumer without `skipLibCheck` |
|
|
150
|
+
| `check-dist-names.mjs` | a minified build shipping `AnimatedBeam` as `function ut(...)` in every consumer's DevTools tree and stack traces |
|
|
151
|
+
| `check-dist-shape.mjs` | the `"use client"` boundary moving in either direction, a test rig reaching the tarball, a declaration pointing at a file that is not there |
|
|
152
|
+
| `smoke-dist.mjs` | the built artifact never being executed: it imports every server module with no DOM, renders the barrel, and holds a gzip budget over the emitted JS and CSS |
|
|
153
|
+
|
|
154
|
+
Two build decisions worth knowing before changing `vite.config.ts`: the output
|
|
155
|
+
is **not minified** (a library must not — the consumer's bundler does that over
|
|
156
|
+
the whole app, and minifying here costs every component its name), and **no
|
|
157
|
+
source maps are emitted**, which follows from the first. Unminified output plus
|
|
158
|
+
one dist file per source module already reads like the TSX with the types
|
|
159
|
+
removed, so a map would roughly double the tarball to point at text the
|
|
160
|
+
consumer can already read.
|
|
161
|
+
|
|
162
|
+
## Divergences from the Svelte API
|
|
163
|
+
|
|
164
|
+
Deliberate, small, and documented — everything else is a faithful transpose:
|
|
165
|
+
|
|
166
|
+
- **Two-way binding.** Svelte's `bind:value` / `bind:checked` become the
|
|
167
|
+
standard React split: uncontrolled by default (a bare `<Switch />` flips on
|
|
168
|
+
click), controlled once you pass `value`/`checked` — at which point you must
|
|
169
|
+
also handle the change (`onChange`, or `onClick` for `Switch`). Passing a
|
|
170
|
+
value with no handler is idiomatic-React frozen input, and React warns
|
|
171
|
+
loudly; the Svelte side stays typable in that situation.
|
|
172
|
+
- **Bare `<Select>` shows the first option** (native uncontrolled behavior).
|
|
173
|
+
The Svelte one renders blank, because `$bindable("")` matches no option —
|
|
174
|
+
that quirk was not imported.
|
|
175
|
+
- **`RainbowButton` accepts no extra DOM props** (`onClick` included) — the
|
|
176
|
+
Svelte source reads only its declared props and spreads nothing, and its own
|
|
177
|
+
README example inherits that bug. Ported as-is per the fidelity law; fix it
|
|
178
|
+
upstream first if it bothers you.
|
|
179
|
+
- Compiler-scoped selectors with no root anchor in the source gained one
|
|
180
|
+
(`fancy-marquee`, `ripple-button`) so their CSS does not leak into consumer
|
|
181
|
+
pages — see PORTING.md, styling rule 2.
|
|
182
|
+
- **`Meteors` takes a `seed`** the Svelte side has no equivalent for. Svelte
|
|
183
|
+
runs its randomiser once, in the browser; React runs the same initializer on
|
|
184
|
+
the server AND again during hydration, and `Math.random()` disagrees with
|
|
185
|
+
itself across the two — a hydration mismatch React may settle by keeping the
|
|
186
|
+
server values. A seeded PRNG makes both renders agree while leaving the
|
|
187
|
+
shower in the server HTML. The default seed is shared, so two unseeded
|
|
188
|
+
showers fall the same way; pass different seeds to separate them.
|
|
189
|
+
|
|
190
|
+
- **agent-plan**: Svelte's `item` prop is a Snippet<[PlanStepData, number]>; ported as a render-prop function `(step, index) => ReactNode` per PORTING.md's Snippet->ReactNode mapping.
|
|
191
|
+
- **agent-plan**: Svelte's `ref = $bindable(null)` became a standard forwardRef<HTMLDivElement, AgentPlanProps> on the root div; no functional difference.
|
|
192
|
+
- **ai-data-table**: The `cell` snippet prop became a render-function prop `cell?: (value, at) => ReactNode` instead of a ReactNode, since the Svelte Snippet<[unknown,{row,key}]> takes arguments — same call-site shape, a JS function instead of a snippet.
|
|
193
|
+
- **animated-beam**: containerRef/fromRef/toRef additionally accept a React ref object ({ current: HTMLElement | null }) alongside a plain HTMLElement, resolved at effect/observer time (exported helper type AnimatedBeamTarget), and are typed nullable since a ref may not be populated yet
|
|
194
|
+
- **animated-beam**: gradient id comes from useFancyId("beam") (SSR-stable) instead of the Svelte side's Math.random() id
|
|
195
|
+
- **animated-beam**: new seed prop (default 1): the default duration (Svelte: Math.random() * 3 + 4) is derived from a deterministic mulberry32 PRNG so server render and hydration agree
|
|
196
|
+
- **apple-card-carousel**: AppleCard's props interface is now exported as AppleCardProps (the Svelte side kept it a local, unexported interface) to satisfy the <Name>Props tooling contract.
|
|
197
|
+
- **apple-card-carousel**: AppleCardData.content is a ReactNode instead of a Svelte Snippet (rendered directly rather than invoked).
|
|
198
|
+
- **apple-card-carousel**: Svelte's await tick() + inline rAF chain after expand became two effects keyed on overlayVisible: a layout effect that focuses the close button (and commits the reduced-motion still frame), then a passive effect whose double rAF flips fullyExpanded; the rAFs are cancelled on cleanup (Svelte had no cancellation, but the timing/behaviour is identical). The reduced-motion branch is read from a ref so it is decided once per expand, like the source handler.
|
|
199
|
+
- **apple-card-carousel**: TRANSITION_MS is exported from AppleCard.tsx (as in the Svelte module script) but, matching the Svelte index, is not re-exported from the folder's index.ts.
|
|
200
|
+
- **apple-card-carousel**: The collapse setTimeout is not cleared on unmount, mirroring the Svelte source verbatim (React 18+ makes the late setState a no-op).
|
|
201
|
+
- **apple-card-carousel**: AppleCardCarousel reads the reduced-motion preference through the package's useReducedMotion() (useSyncExternalStore over matchMedia) rather than the source's onMount + matchMedia state, so the preference is correct on the first committed render and there is no hydration-mismatch surface.
|
|
202
|
+
- **approval-card**: Svelte's bind:state two-way binding becomes a controlled/uncontrolled prop pair: `state` + `onStateChange` (React's counterpart, following the Stepper.tsx precedent), rather than a bindable ref. Consumers driving state from outside now pass both props instead of `bind:state`.
|
|
203
|
+
- **approval-card**: children (Snippet) becomes ReactNode children as usual for the detail region.
|
|
204
|
+
- **bento-grid**: BentoGridItemProps uses Omit<HTMLAttributes<HTMLDivElement>, 'title'> to avoid a TS conflict between the DOM 'title' attribute and the Svelte 'title' snippet prop (same intersection pattern PORTING.md prescribes for RainbowButton).
|
|
205
|
+
- **bento-grid**: BentoGridItemProps and BentoGridCardProps extend HTMLAttributes<HTMLDivElement>, so they accept every div attribute — including a `children` the components render fixed JSX in place of and therefore silently drop; the Svelte parts declare a closed prop list.
|
|
206
|
+
- **bg-falling-stars**: Added optional `seed?: number` (default 1) + mulberry32 PRNG replacing every `Math.random()` (star layout and respawn), per PORTING.md's randomisation rule; consequence: two `<FallingStarsBg />` with no seed show an identical sky, where the Svelte side gave each instance a different one.
|
|
207
|
+
- **bg-falling-stars**: `count` re-initialises the starfield in React (it is a dependency of the canvas effect); the Svelte side reads `count` only inside `onMount`, so a later `count` change there is silently ignored. `color` keeps Svelte's behaviour exactly (live, next-frame, no re-seed) via a ref rather than an effect dependency.
|
|
208
|
+
- **bg-stars**: Added a `seed` prop (default 1) with a deterministic mulberry32 PRNG replacing the Svelte side's Math.random() star scatter — required by the SSR/hydration rule (PORTING.md, C-7); same seed = same sky.
|
|
209
|
+
- **bg-stars**: Per-frame spring transform is written imperatively to the parallax element's style in the rAF loop (per group guidance) instead of re-rendering through state; a stiffness/damping change restarts the loop but spring position/velocity persist in refs, so motion resumes from the in-flight position.
|
|
210
|
+
- **bg-stars**: Port-added root anchor class `fancy-bg-stars` for the colocated CSS (Svelte compiler-scoped .stars-parallax/.star-layer/.star-field). The bare slug `bg-stars` was avoided deliberately: tailwind-merge classifies `bg-*` tokens as background utilities and would drop the anchor against any consumer bg-* override.
|
|
211
|
+
- **bg-stars**: Star box-shadows are derived in render (useMemo on starColor+seed) instead of a client-only effect, so stars appear in server-rendered HTML; the Svelte side renders empty shadows until the effect runs.
|
|
212
|
+
- **box-reveal**: Rest props: React BoxRevealProps extends HTMLAttributes<HTMLDivElement> and spreads rest onto the root div; the Svelte BoxRevealProps declares only color/duration/delay/class and spreads nothing, so the React component accepts id/onClick/data-* attributes the Svelte one silently drops. Kept per PORTING.md's general 'rest props spread onto the root element' rule, recorded here because it is consumer-visible.
|
|
213
|
+
- **breadcrumb**: `class` becomes `className` (standard rename).
|
|
214
|
+
- **breadcrumb**: `item` snippet prop (`Snippet<[BreadcrumbItem, number]>`) becomes a render-prop function: `item?: (item: BreadcrumbItem, index: number) => ReactNode`.
|
|
215
|
+
- **breadcrumb**: `ref` bindable prop becomes `forwardRef<HTMLElement, BreadcrumbProps>` — the nav element arrives through the React ref channel instead of a `ref` prop.
|
|
216
|
+
- **button-group**: BUTTON_GROUP_CONTEXT_KEY is a React.Context<ButtonGroupContext | undefined> object rather than a Symbol context key: a nested control reads it with useContext(BUTTON_GROUP_CONTEXT_KEY) instead of getContext(BUTTON_GROUP_CONTEXT_KEY). Same exported name, same optional/degrades-to-undefined contract.
|
|
217
|
+
- **button-group**: ButtonGroupContext.orientation is a plain readonly value on an object the root rebuilds whenever orientation changes, not a Svelte getter. Observable behaviour is identical (consumers re-render on change); a consumer cannot destructure-and-hold it across renders, which the getter also did not allow meaningfully.
|
|
218
|
+
- **button-group**: The Svelte <style> block's `:global(...)` selectors become plain child/descendant selectors in the colocated button-group.css, every one anchored on the existing `.ft-button-group` root class (no class-string addition needed). Specificity story is unchanged: the rules are unlayered and so still beat Tailwind's layered `rounded-*` / `border` utilities on a child without !important.
|
|
219
|
+
- **button-group**: The `class` prop is `className`, per PORTING.md.
|
|
220
|
+
- **button-group**: The `ref` prop is gone from ButtonGroupProps: the root <div> arrives through forwardRef's ref channel (Svelte declares `ref = $bindable(null)`).
|
|
221
|
+
- **button-group**: `children?: Snippet` becomes `children?: ReactNode`.
|
|
222
|
+
- **card-3d**: A `<CardItem>` rendered outside a `<CardContainer>` throws `Card3DContext is missing: this component must be rendered inside its provider.` The Svelte side also throws there (`getMouseEntered is not a function`), so the failure mode is the same; only the message differs.
|
|
223
|
+
- **card-3d**: CardItem `as` is typed `ElementType` (React) instead of Svelte's raw `string` — `<svelte:element this={as}>` only accepts tag strings, so the React type is a widening; `as="span"` etc. behave identically.
|
|
224
|
+
- **card-3d**: CardItem's Svelte source declares `let ref: HTMLElement` with `bind:this={ref}` but never reads it and does not make it `$bindable`; the React port forwards no ref, matching the Svelte public API surface (PORTING.md forwardRef rule).
|
|
225
|
+
- **card-spotlight**: Svelte-side bug ported intentionally: the overlay's inline style sets opacity to gradientOpacity unconditionally, overriding the opacity-0 / group-hover:opacity-100 classes (inline style wins), same as the Svelte source
|
|
226
|
+
- **card-spotlight**: class prop becomes className (standard React mapping per PORTING.md)
|
|
227
|
+
- **chat-error**: icon/children Snippet props became ReactNode props (icon and children)
|
|
228
|
+
- **chat-error**: ref exposed via forwardRef (mirrors Svelte's ref = $bindable(null))
|
|
229
|
+
- **colourful-text**: New `seed` prop (default 1): the Svelte side shuffles with Math.random() at init; the React initial shuffle draws from a deterministic mulberry32(seed) stream so server render and hydration match (PORTING.md C-7). Same seed = same initial color order; two instances without a seed start identically.
|
|
230
|
+
- **colourful-text**: The 5-second reshuffles draw from a second deterministic stream (mulberry32(seed ^ 0x9e3779b9)) so the first reshuffle is not a visual no-op replay of the initial order; reshuffle sequences are therefore reproducible per seed rather than random.
|
|
231
|
+
- **compare**: StarField gains a `seed` prop (default 1) with a deterministic mulberry32 PRNG replacing the Svelte side's render-path Math.random(), per PORTING.md's SSR rule; two StarFields with the same starsCount and seed render identical skies, and stars only reshuffle when starsCount or seed changes.
|
|
232
|
+
- **compare**: StarField's root cn() gains the port-added anchor class `fancy-star-field` (PORTING.md styling rule 2 sanctioned addition) so the formerly compiler-scoped `.star` rules don't leak globally; keyframe names `twinkle`/`drift` kept identical.
|
|
233
|
+
- **confetti**: Context key stays private. Svelte publishes on the string key `"ConfettiContext"`; React uses `ConfettiReactContext` (via `createInternalContext`) in `context.ts`, not re-exported from `index.ts` — the Svelte `index.ts` exports only the two components, so the key has no public identity on either side. Consumers outside a `Confetti` still get the graceful `undefined` fallback (`useOptional()`), matching `getContext` returning undefined.
|
|
234
|
+
- **confetti**: No behavioural divergence in `ConfettiButton`: no className, no rest-prop spread, no `type` attribute — the Svelte source declares only `options`, `children` and `sound` on a bare `<button>`.
|
|
235
|
+
- **confetti**: `Confetti` gains one extra file over the Svelte tree (`context.ts`), mirroring the `button-group` precedent; one file per Svelte file is otherwise preserved.
|
|
236
|
+
- **confetti**: `fire()` reaches consumers through the ref channel, not a component instance. Svelte declares `export function fire(opts)` (callable via `bind:this`); React has no instance, so `Confetti` is a `forwardRef<ConfettiHandle, ConfettiProps>` whose ref carries `{ fire }` rather than the DOM node. This is the one forwardRef in the port not backed by a `ref = $bindable` declaration (PORTING.md C-4); the alternative was deleting a public method. `ConfettiHandle` is exported from `Confetti.tsx` but deliberately NOT from `index.ts`, since the mandated export list is exactly Confetti/ConfettiButton + Props types.
|
|
237
|
+
- **direction-aware-hover**: fade transitions on the overlay and caption are reproduced via usePresence + a local fade300 TransitionSpec (WAAPI mechanism per internals-api §5) instead of a framework transition directive — same 300ms linear opacity curve
|
|
238
|
+
- **direction-aware-hover**: isMobile lives in a ref rather than state — it is only read in event handlers and never drives markup, so resize events no longer trigger re-renders (no observable difference)
|
|
239
|
+
- **direction-aware-hover**: non-null assertion added on event.touches[0] to satisfy the React tsconfig's indexed-access checking (no runtime change)
|
|
240
|
+
- **direction-aware-hover**: overlay class freezes at the last hovered direction during the fade-out (explicit lastDirectionRef) to reproduce the source's inert-outro-branch behavior, since React keeps re-rendering the exiting node
|
|
241
|
+
- **direction-aware-hover**: Reduced-motion and <=768px touch-target rules are re-anchored from the source's `:global(*)` and shared `group/card` selectors onto the port-added `.direction-aware-hover` root class, so the aggregated dist/styles.css cannot reach apps that never render the component. The root element carries both classes, so the targeted element is unchanged.
|
|
242
|
+
- **displacement-text**: `class` prop is renamed `className` (PORTING.md API contract); every other prop name, default and type is unchanged.
|
|
243
|
+
- **editorial-engine**: Engine re-creation is keyed on pullquote CONTENT (`pullquotes.join("\u0000")`) rather than array identity. A caller passing an inline `pullquotes={[...]}` literal would otherwise tear down and re-measure the whole article on every parent render; identical content now yields identical output, so no rendered difference is observable.
|
|
244
|
+
- **editorial-engine**: `class` prop becomes `className` (PORTING.md API contract). Prop set is otherwise identical (headline, body, pullquotes, fontFamily) — no rest-props spread and no ref forwarding, matching the Svelte surface which declares neither.
|
|
245
|
+
- **fireworks-hdr**: Dev diagnostics: `import.meta.env.DEV` becomes `isDev()` (`dev.ts`), which reads `process.env.NODE_ENV` — the flag every React toolchain already replaces — and returns `false` when no such global exists. Consumer-visible only in that the `[FireworksHdr] …` console warnings appear in dev builds that set NODE_ENV and stay silent in a plain ESM page that sets nothing.
|
|
246
|
+
- **fireworks-hdr**: NO `seed` prop was added, deliberately. Every `Math.random()` on the Svelte side lives inside `onMount` (ambient scheduling, hue jitter, shell pick, poisson intervals) and drives an imperatively-painted canvas — no random value ever reaches the rendered markup, which is a static wrapper + `<canvas>`. PORTING.md's seed-prop rule targets render-path randomisation (the Meteors case); adding a seed here would invent API surface the Svelte component does not expose. `createSim({ rng })` remains the injectable-randomness seam and is what the tests use.
|
|
247
|
+
- **fireworks-hdr**: React StrictMode (dev only) double-invokes effects, so the engine boots, tears down and reboots once at mount; a consumer's `onReady` therefore fires twice under dev StrictMode. Production and non-StrictMode behaviour is unchanged (one boot, one `onReady`).
|
|
248
|
+
- **fireworks-hdr**: WebGPU types: the Svelte module opens with `/// <reference types="@webgpu/types" />`. `fancy-ui-react` does not declare that package and may not add it, and such a directive would be emitted into the published `.d.ts` and break every consumer that lacks it. The exact GPU surface the renderer touches is therefore declared locally in `webgpu-types.ts` (type-only, module-scoped, no ambient globals), and the three host boundaries (`navigator.gpu`, both `getContext("webgpu")` calls) go through `as unknown as`. No public export mentions a GPU type, so the emitted declarations stay WebGPU-free. Shader source (WGSL + GLSL) is byte-for-byte verbatim.
|
|
249
|
+
- **fireworks-hdr**: `class` prop is `className` (standard rename; same verbatim Tailwind literals on the wrapper: `pointer-events-none absolute inset-0 h-full w-full` + merge, and `block h-full w-full` on the canvas).
|
|
250
|
+
- **flickering-grid**: Added `seed?: number` (default `1`) — the source's bare `Math.random()` is replaced by mulberry32 for both the initial square opacities and every flicker change, per PORTING.md's seed rule and matching the sibling MatrixRain port. Consumer-visible: two `<FlickeringGrid />` with no seed now flicker in step (the Svelte side gives each an independent stream), and a remount replays the same sequence. Changing `seed` restarts the grid.
|
|
251
|
+
- **flickering-grid**: `class` prop is named `className`, per PORTING.md's API contract. Same position in the same `cn("h-full w-full", className)` call.
|
|
252
|
+
- **flip-words**: Compiler-scoped `.flip-words-enter` / `.flip-words-exit` rules are anchored under the `.flip-words` root class in the colocated CSS (global keyframe names kept identical)
|
|
253
|
+
- **flip-words**: Svelte `class` prop becomes `className` (standard port mapping)
|
|
254
|
+
- **flip-words**: Timer scheduling moved inside useEffect closures (refs for timeout ids).
|
|
255
|
+
- **flip-words**: The flip cycle is keyed on `words.length`, not on the `words` array identity the Svelte $effect tracks, so a parent handing down a new array reference (or a same-length content swap) no longer clears the pending timer and re-arms a full `duration` wait.
|
|
256
|
+
- **flip-words**: The next-index computation guards an empty `words` list: if the array empties while the 600 ms exit is in flight the React component falls back to index 0 and resumes when the list is repopulated, where the Svelte source computes `(index + 1) % 0` = NaN and stays blank forever.
|
|
257
|
+
- **fluid-cursor**: Dev-only console diagnostics (singleton warning, WebGPU fallback/tone-mapping/device-lost logs, HDR-level info) are gated on a `typeof`-guarded `process.env.NODE_ENV !== "production"` instead of `import.meta.env.DEV` — the react package's tsconfig does not load Vite client types. In an unbundled browser load where `process` is undefined the diagnostics are silent. No non-diagnostic behavior differs; `hexToRgb`'s invalid-hex `console.warn` is NOT gated on either side (the test asserts it).
|
|
258
|
+
- **fluid-cursor**: WebGPU is typed by module-scoped minimal interfaces instead of `@webgpu/types` (not declared in react/package.json; it is only reachable here by accident, transitively through `@types/three`). Type-level only — no runtime difference — but it also keeps the emitted `.d.ts` free of an external type reference consumers would have to install.
|
|
259
|
+
- **fluid-cursor**: `FluidCursorAdvancedProps` is a new exported type (empty interface extending `FluidCursorProps`). The Svelte index exports the deprecated `FluidCursorAdvanced` alias with no Props type of its own; PORTING.md's `<Name>Props` tooling contract requires one.
|
|
260
|
+
- **fluid-cursor**: `interactive` and `contained` are captured at mount and used for BOTH listener registration and removal. The Svelte source re-reads them (reactive getters) at cleanup time, so flipping either prop mid-life leaks or mis-pairs listeners there; here add/remove always pair. Unobservable unless a consumer mutates those props on a live instance, which the props are documented not to support.
|
|
261
|
+
- **frosted-glass**: Filter id generator: the Svelte `onMount` mints `fg-dist-${Math.random().toString(36).slice(2,8)}`; the port mints `uid("fg-dist")` from `src/internals/use-id.ts` inside the equivalent mount effect. Consumer-visible ids are now `fg-dist-1`, `fg-dist-2`, ... instead of a random base-36 suffix. Timing is unchanged (still client-only, still after mount, so the filter layer and its <defs> are still absent from the server HTML), and no seed prop was added — the existing `seed` prop stays the feTurbulence seed it is on the Svelte side.
|
|
262
|
+
- **hyper-text**: HyperText adds a `seed` prop (default 1): the scramble characters come from a deterministic mulberry32 PRNG instead of the source's bare `Math.random()` (PORTING.md seed-prop rule); the distribution and visual effect are unchanged.
|
|
263
|
+
- **hyper-text**: When `text` shrinks mid-animation, an already-revealed index past the new length keeps its previous letter (`target[i] ?? l`) instead of rendering the string "undefined" as the Svelte code would — strict-TS guard, practically unobservable since the text-sync effect resets `displayText` on any `text` change.
|
|
264
|
+
- **hyper-text**: `displayText` seeds from `text.split("")` instead of `[]`, so the character spans are present in the server render and on the first client commit; the Svelte source fills them only in a post-mount `$effect`. Post-mount DOM is identical.
|
|
265
|
+
- **image-trail-cursor**: Root `touch-action: none` is emitted through React's inline-style object instead of Svelte's literal style string. Identical in browsers (style="touch-action: none;"), but jsdom's cssstyle does not implement `touch-action` and silently drops any CSSOM write, so the transposed assertion reads the server markup (renderToStaticMarkup contains style="touch-action:none") rather than the live node's style attribute. Same fact, jsdom-observable form.
|
|
266
|
+
- **image-trail-cursor**: `ImageItem.defaultStyle` is `private` here where the Svelte class declares it `public`: a public TweenVars member emits a bare animation-library namespace reference into the shipped .d.ts that a deep-importing consumer cannot resolve. The member is read only by `initEvents()`, and `ImageItem` is not re-exported from index.ts on either side.
|
|
267
|
+
- **interactive-grid-pattern**: Root SVG carries an extra class token `interactive-grid-pattern` that the Svelte source does not emit: the Svelte <style> rule `.interactive-grid-square:not(:hover){transition-duration:1000ms}` was compiler-scoped, so the port adds the slug as an anchor per PORTING.md styling rule 2. This was already present in the ported component before this fix and is commented as port-added in interactive-grid-pattern.css.
|
|
268
|
+
- **line-reveal**: Port-added root anchor class `line-reveal` (first token of the root `cn()`), so the compiler-scoped `.line-mask` / `.line` / `.revealed` rules do not leak globally — same treatment as `fancy-marquee` and `ripple-button`; README's 'Compiler-scoped selectors ... gained one' bullet should list `line-reveal` too.
|
|
269
|
+
- **line-reveal**: `class` -> `className` (standard PORTING.md rename); no ref/forwardRef and no rest-prop spread, matching the Svelte source which declares neither.
|
|
270
|
+
- **line-reveal**: LineReveal creates one ResizeObserver per mounted instance where the Svelte `bind:clientWidth` routes through the framework's process-wide observer singleton; each disconnects on unmount and nothing leaks.
|
|
271
|
+
- **link**: Native click handler is `onClick` (React convention/rest-props spread) rather than Svelte's `onclick` prop name.
|
|
272
|
+
- **link**: Props extend AnchorHTMLAttributes (minus className) and spread ...rest onto the <a>, per PORTING.md's rest-props-spread rule; Svelte side only exposed a fixed prop list plus onclick.
|
|
273
|
+
- **liquid-glass**: Filter id: minted with the internals' `uid("lg")` inside the mount effect instead of `Math.random().toString(36).slice(2, 8)`. Same client-only timing as `onMount` (no filter and no `backdrop-filter` in the server HTML, exactly as Svelte SSR) and the same per-instance uniqueness, but the ids read `lg-1`, `lg-2`, … per page load instead of random 6-char suffixes. No `seed` prop was added: a shared default seed would give every instance on a page the same SVG filter id, which is the one thing the Svelte randomisation exists to prevent, and `uid()` is the sanctioned generator for an id minted in an effect (internals-api §C-6 / use-id.ts).
|
|
274
|
+
- **liquid-glass**: Inline style is a React style object rather than the Svelte raw style-attribute string, so a declaration the CSSOM does not recognise is dropped instead of surviving verbatim in the `style` attribute. Only observable where `backdrop-filter` is unsupported (jsdom drops it from the serialised attribute; the four CSS custom properties and `border-radius` are unaffected). No browser effect: engines that ignore `backdrop-filter` ignore it in the Svelte string form too, and Safari is served by the `@supports (background: -webkit-named-image(i))` fallback block regardless.
|
|
275
|
+
- **liquid-glass**: No rest-props spread and no `forwardRef` — the Svelte source declares neither `$restProps` nor `ref = $bindable`, so the API surface stays exactly the Svelte one.
|
|
276
|
+
- **liquid-glass**: Prop rename: the Svelte `class` prop (applied to the inner slot) becomes `className`, per PORTING.md. `containerClass` keeps its Svelte name — it is not `class`, and the transposed test drives it by that name.
|
|
277
|
+
- **liquid-text**: New internal dependency the Svelte side does not have: `useLiveRef` from `internals/dom/use-live-ref.js`. It reproduces Svelte's live `$props()` reads inside the long-lived sim closures (pointer handler, rAF loop, observers), so `interactive`, `forceGain`, `radius`, `dissipation`, `viscosity`, `strength`, `chromaticRatio`, `pauseWhenHidden`, `text` and `fontWeight` still take effect after mount without re-initialising GL.
|
|
278
|
+
- **liquid-text**: Test-only: `LiquidText.test.tsx` adds one throwaway `render(...).unmount()` before the listener-balance spies are installed. react-dom attaches its delegated `selectionchange` listener to the owner document the first time any root is created and never removes it; without the warm-up the transposed balance assertion fails when the test is run in isolation (`-t`). No production-code effect.
|
|
279
|
+
- **liquid-text**: `class` prop is `className` (PORTING.md API contract). Every other prop name, default and type is identical to the Svelte surface; no ref is exposed (the Svelte source declares no `$bindable` ref) and no rest props are spread (the Svelte root has none).
|
|
280
|
+
- **liquid-text**: `liquid-text.css`: the `.liquid-text-fallback` rule is anchored as `.liquid-text .liquid-text-fallback` (PORTING.md styling rule 2 — Svelte scoped it at compile time; as flat CSS the bare class would leak). Class names and the `.liquid-text` root rule are unchanged, and the fallback span is always a child of the root, so the computed styling is identical.
|
|
281
|
+
- **liquid-text**: The WebGL teardown deliberately diverges: the port does not call `WEBGL_lose_context.loseContext()` on a normal unmount (only on a failed init), because React re-runs the mount effect on the same `<canvas>` under StrictMode and Fast Refresh and a lost context is never re-acquired. Every GL object is still deleted explicitly and the context is reclaimed with the canvas.
|
|
282
|
+
- **logo-cloud**: Svelte compiler-scoped .logo-cloud-scroll/.logo-cloud-mask/keyframes are unscoped in plain CSS; both classes already existed as public identifiers in the Svelte markup/JS API so no anchor class was added (rule 4 exception doesn't apply — these already had public identity).
|
|
283
|
+
- **logo-cloud**: `class` prop renamed to `className` per PORTING.md contract (Svelte source used `class`) — purely mechanical, no behavior change.
|
|
284
|
+
- **matrix-rain**: New prop `seed?: number` (default 1), absent on the Svelte side: both `Math.random()` call sites (column initialisation in `init()` and glyph picking in `randomGlyph()`) are driven by a seeded mulberry32 stream, per PORTING.md's seed-prop rule. Same uniform distribution, so no visual change; two `<MatrixRain />` with no seed now start out alike where two Svelte instances did not.
|
|
285
|
+
- **matrix-rain**: The PRNG stream restarts when the effect re-runs (a `glyphSize`, `density` or `seed` change), whereas the Svelte source draws from the process-global `Math.random()` stream continuously across re-inits. Not observable — the distribution is identical either way.
|
|
286
|
+
- **mosaic-glow**: SSR markup: React serialises the host's inline style as `style="background-color:#0a0a0a"` (no space after the colon) where Svelte emits `background-color: #0a0a0a`. Same declaration, different byte string — the SSR test asserts the React form and carries a comment saying so.
|
|
287
|
+
- **mosaic-glow**: The Svelte `ref = $bindable(null)` prop becomes a React forwarded ref (`forwardRef`), per PORTING.md: `<MosaicGlow ref={r} />` publishes the host div, and `ref` is no longer a member of `MosaicGlowProps`.
|
|
288
|
+
- **mosaic-glow**: `MosaicGlowProps` extends `Omit<HTMLAttributes<HTMLDivElement>, "color" | "children">` rather than omitting every `keyof BaseProps` — those two are the only names that actually collide in `@types/react`, so the surviving attribute surface is one entry wider than the Svelte type (e.g. `title`, `role` were never omitted on either side anyway). No runtime effect.
|
|
289
|
+
- **navbar**: NavbarLink's onclick prop is renamed onClick (React event-prop casing convention, consistent with other ports)
|
|
290
|
+
- **navbar**: Svelte source had two <style> blocks (one per .svelte file); ported as two colocated CSS files, navbar.css and navbar-link.css, each imported by its own component
|
|
291
|
+
- **neon-border**: `neon-border.css` carries the Svelte `<style>` rules unanchored (`.neon-layer-one`, `.neon-layer-two`, `.neon-animated`) instead of nesting them under the root class, so they are global where the Svelte compiler scoped them. Known deviation from PORTING.md styling rule 2, shared with `meteors.css`.
|
|
292
|
+
- **neon-border**: NeonBorderProps extends HTMLAttributes<HTMLDivElement> and spreads rest onto the root, so id/role/onClick/data-* reach the element; the Svelte component declares a closed six-prop list and spreads nothing.
|
|
293
|
+
- **noise-reveal**: `class` prop renamed to `className` (package-wide PORTING.md convention); every other prop name, type and default is identical.
|
|
294
|
+
- **noise-reveal**: The viewport-trigger effect lists `delay` in its dependency array, which the Svelte `$effect` does not track, so changing `delay` after the element has intersected cancels a reveal already waiting out its delay and re-observes; `delay` is a mount-time setting.
|
|
295
|
+
- **pagination**: Pagination: Svelte's `bind:page` becomes the standard controlled/uncontrolled split — uncontrolled by default (internal page state starting at 1), controlled when the `page` prop is passed; `onPageChange` fires with the same value either way.
|
|
296
|
+
- **pagination**: Pagination: `previousLabel`/`nextLabel` snippets become `ReactNode` props; the nav element is exposed via `forwardRef` instead of `bind:ref`.
|
|
297
|
+
- **prompt-suggestions**: Svelte $effect.pre (pre-flush) mapped to useLayoutEffect (closest React equivalent for pre-paint DOM updates); no functional difference observed in tests.
|
|
298
|
+
- **prompt-suggestions**: Svelte 'item' prop was a Snippet<[string,number]>; ported as item?: (suggestion, index) => ReactNode, per PORTING.md snippet->ReactNode rule.
|
|
299
|
+
- **prompt-suggestions**: class prop renamed to className per PORTING.md convention.
|
|
300
|
+
- **sidebar**: No rest-prop spread and no DOM-attribute extension on any Props interface — the Svelte source reads a closed prop list off $props() and spreads nothing.
|
|
301
|
+
- **sidebar**: SIDEBAR_KEY is a React context object (createContext<SidebarContext|undefined>(undefined), displayName "SidebarContext") instead of the Svelte `unique symbol` context key — the ButtonGroup precedent. Consumers read it with useContext(SIDEBAR_KEY); Sidebar renders SIDEBAR_KEY.Provider around its <nav>.
|
|
302
|
+
- **sidebar**: SidebarHarness.test.svelte becomes a `Harness()` component declared at the top of Sidebar.test.tsx; the `await tick()` after each toggle is dropped (fireEvent flushes React synchronously). All other assertions transposed 1:1 — 36 tests, same count as the Svelte suite.
|
|
303
|
+
- **sidebar**: Snippet props become ReactNode: SidebarItem.icon, SidebarFooter.avatar, and `children` on Sidebar/SidebarGroup/SidebarItem/SidebarFooter.
|
|
304
|
+
- **sidebar**: The context value's `get collapsed()` getter becomes a plain object rebuilt via useMemo keyed on `collapsed`; the rebuild is what re-renders nested consumers. Same observable behaviour.
|
|
305
|
+
- **sidebar**: `class` becomes `className` on all five components; SidebarItem's `onclick` becomes `onClick`, typed (event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void.
|
|
306
|
+
- **sidebar**: `ref` props become forwardRef on Sidebar, SidebarItem, SidebarSeparator and SidebarFooter (the four declaring `ref = $bindable(null)`); SidebarGroup declares none and gets none. The `ref` field is therefore absent from every Props interface.
|
|
307
|
+
- **smooth-cursor**: `class` prop becomes `className` (standard mapping).
|
|
308
|
+
- **smooth-cursor**: `cursor` prop is a ReactNode instead of a Svelte Snippet (standard snippet->ReactNode mapping); truthiness check preserved, so a falsy node falls back to the default arrow exactly like the Svelte {#if}.
|
|
309
|
+
- **sound**: Svelte's `use:soundFeedback` action has no React counterpart: it ships as `attachSoundFeedback(element, options)` (the imperative attach/detach core, callable from a ref callback) plus the `useSoundFeedback(options)` hook that returns a ref callback for the common case. The action name `soundFeedback` is therefore absent from the package root.
|
|
310
|
+
- **sound**: The React engine clamps a custom theme's layer duration to `SOUND_LIMITS.MAX_LAYER_MS` before scheduling; the Svelte engine schedules the declared duration. Only `validateSoundTheme()` enforces the limit on the Svelte side, so a theme passed straight to `engine.setTheme()` with a layer longer than 400 ms plays in full under Svelte and truncated under React.
|
|
311
|
+
- **sound**: The sound family adds `useSound`, `useSoundCue`, `useSoundEnabled` and `useSoundStatus` — the React counterpart of reading the `sound` controller's runes directly.
|
|
312
|
+
- **sparkles**: Adds a `seed?: number` prop (default `1`) and generates the particle field with a seeded mulberry32 PRNG instead of `Math.random()`, per PORTING.md's determinism rule - consequence: two `<Sparkles />` with no `seed` render the identical field, whereas the Svelte version gives every instance and every remount a different one. Pass distinct `seed` values to differentiate.
|
|
313
|
+
- **sparkles**: No `.css` file is emitted - the Svelte source has no `<style>` block, so there is no port-added root anchor class and no new Tailwind literal. Root and canvas class strings are byte-identical to the Svelte source.
|
|
314
|
+
- **sparkles**: The mount effect re-inits (regenerates the particle field) when `minSize`, `maxSize`, `speed`, `particleDensity` or `seed` change. The Svelte side reads those five inside `generateParticles()` called from `onMount`, so changing them after mount is a no-op there until a remount. Same precedent as the FallingStarsBg port keying on `count`. `particleColor` is read through a live ref inside the rAF loop (repaints next frame, no re-init) and `background` is a plain inline style, so both behave identically to Svelte.
|
|
315
|
+
- **sparkles**: `class` prop becomes `className` (PORTING.md API contract). No `forwardRef` and no rest-prop spread: the Svelte source declares neither a `$bindable` ref nor `...restProps`, and its API surface is the contract.
|
|
316
|
+
- **sparkles-text**: Adds a `seed` prop (default 1) with a deterministic mulberry32 PRNG replacing the source's Math.random() — required for identical server render and hydration; same seed yields the same initial field.
|
|
317
|
+
- **sparkles-text**: Post-mount star regeneration draws from a second seeded stream (mulberry32(seed+1)) instead of Math.random(), so the animation timeline is also deterministic per seed.
|
|
318
|
+
- **sparkles-text**: Sparkle ids drop the source's Date.now()+Math.random() composition in favor of an extra PRNG draw (`${x}-${y}-${random()}`) — ids stay unique per field but are deterministic.
|
|
319
|
+
- **stepper**: Step.svelte's scoped `<style>` block ships as colocated `step.css` imported by `Step.tsx`. Every rule was already anchored on a class the component owns (`.ft-step`, `.ft-step-bullet`, `.ft-step-connector`, `.ft-step-trigger`), so no port-added anchor class was needed; keyframe-free, and the deliberate no-`prefers-reduced-motion` decision is preserved verbatim with its rationale.
|
|
320
|
+
- **stepper**: The Svelte `untrack` guard around register/unregister becomes two React rules: `register` is `useCallback(..., [])` over a ref-held registry (identity never changes), and a Step's registration effect depends on `[register, id]`, never on the context object — depending on the context (rebuilt whenever the registry changes) would re-run the effect from its own call and loop forever, the same bug in React shape.
|
|
321
|
+
- **stepper**: `STEPPER_KEY` is a `React.Context<StepperContext | undefined>` object, not a `Symbol` context key — read with `useContext(STEPPER_KEY)`. Same exported name, same optional-outside-the-root semantics (button-group's `BUTTON_GROUP_CONTEXT_KEY` precedent).
|
|
322
|
+
- **stepper**: `Step`'s custom-bullet branch is `children ?? default` (null/undefined only) rather than Svelte's snippet-existence test, so a falsy-but-present child such as `0` or `false` overrides the glyph where Svelte would have rendered the default.
|
|
323
|
+
- **stepper**: `StepperHarness.test.svelte` becomes an inline `Harness` component at the top of `Stepper.test.tsx` (a Svelte harness needs its own file only because Svelte components do); `bind:current` becomes the controlled pair and `bind:ref` a callback ref held in state.
|
|
324
|
+
- **stepper**: `current` is a controlled/uncontrolled pair instead of `bind:current`: pass `current` + `onCurrentChange` for two-way behaviour, omit `current` and the component owns the index itself, starting at the same 0 the Svelte `$bindable(0)` default uses.
|
|
325
|
+
- **terminal-text**: Root class gains a port-added `terminal-text` anchor token (sanctioned by PORTING.md styling rule 2: the Svelte <style> was compiler-scoped with no root class; `.cursor-blink` is anchored under it, keyframe name `blink` kept identical).
|
|
326
|
+
- **terminal-text**: The stream restarts on `lines` CONTENT change, not on array identity: a re-allocated equal-content array keeps the current stream running, where the Svelte side restarts it.
|
|
327
|
+
- **text-generate-effect**: Trailing ` ` after each word is rendered as the JSX string literal `" "` — identical character in the DOM.
|
|
328
|
+
- **text-generate-effect**: `class` prop becomes `className` (standard React rename per PORTING.md).
|
|
329
|
+
- **text-reveal-card**: Port-added CSS anchor class `text-reveal-stars` on the stars root div: the Svelte compiler scoped `.star-animate { animation: star-drift ... }` and the source has no root class, so the rule is anchored as `.text-reveal-stars .star-animate` to avoid leaking the generic name; keyframe name `star-drift` unchanged.
|
|
330
|
+
- **text-reveal-card**: TextRevealCard takes a `starsSeed?: number` prop forwarded to the star field so card consumers can vary the layout (the Svelte side reshuffles randomly per mount).
|
|
331
|
+
- **text-reveal-card**: TextRevealStars takes a `seed?: number` prop (default 1) with a deterministic mulberry32 PRNG in place of Math.random() in the render path (SSR/hydration safety, per PORTING.md seed rule); same seed = same star field, call order matches the Svelte generator.
|
|
332
|
+
- **text-reveal-card**: touchmove is attached natively via useEffect with { passive: false } instead of React's onTouchMove: the handler calls preventDefault() and React registers its touchmove root listener as passive. Same listener semantics as the Svelte attribute; behavior identical.
|
|
333
|
+
- **timeline**: `class` prop becomes `className` (standard port convention)
|
|
334
|
+
- **timeline**: `content` snippet becomes a `content?: (item: TimelineItem) => ReactNode` render prop
|
|
335
|
+
- **toggle**: ToggleHarness.test.svelte (Svelte bind: rig) became ToggleHarness.tsx (not .test.tsx, so vitest's src/**/*.test.{ts,tsx} include does not collect it as its own empty suite); its assertions live in Toggle.test.tsx as before.
|
|
336
|
+
- **toggle**: pressed is React state seeded once from the `pressed` prop (mirrors Svelte's pressed = $bindable(false)), not a controlled/uncontrolled toggle via `pressed ?? state` — re-passing a different `pressed` value after mount does not resync it, matching the Svelte bindable-prop semantics exactly.
|
|
337
|
+
- **toggle-group**: Test transposition: the two `bind:value` round-trip tests become "round-trips a single/multiple selection through the value channel", asserting the same values via the harness's `onValueChange`; "binds the root element" becomes "exposes the root element through the ref" using `createRef` + `forwardRef`. `ToggleGroupHarness.test.svelte` is now an inline `Harness` component inside `ToggleGroup.test.tsx`. Every `await tick()` flush is dropped as Svelte-scheduler mechanics (RTL's `fireEvent` already acts).
|
|
338
|
+
- **toggle-group**: The two Svelte `<style>` blocks split into two colocated stylesheets, `toggle-group.css` and `toggle-group-item.css` (one per Svelte file, per the sidebar precedent). Both are already anchored on the sources' own root classes `.ft-toggle-group` / `.ft-toggle-group-item`, so no port-added anchor class was needed; the `prefers-reduced-motion: no-preference` block and the `light-dark()` accent fallback are carried over verbatim.
|
|
339
|
+
- **toggle-group**: `TOGGLE_GROUP_KEY` is a `React.Context<ToggleGroupContext | undefined>` (displayName "ToggleGroupContext") rather than the Svelte `unique symbol` context key — read it with `useContext(TOGGLE_GROUP_KEY)`. Same exported name, same optional-read contract (an item outside a group gets `undefined`, never a throw). Mirrors the BUTTON_GROUP_CONTEXT_KEY precedent.
|
|
340
|
+
- **toggle-group**: `ToggleGroupContext.focusedValue`, `.value`, `.type`, `.disabled`, `.size` and `.orientation` are plain readonly values, not Svelte getters; the root rebuilds the context object every render and that rebuild is what re-renders the items. `register`/`unregister` are the only identity-stable members — they appear in each item's effect dependency list, the React counterpart of the Svelte `untrack` guard against the register/unregister loop.
|
|
341
|
+
- **toggle-group**: `class` becomes `className` on both parts. Neither part spreads rest props, matching the Svelte sources which read no `...restProps`.
|
|
342
|
+
- **toggle-group**: `value` is a controlled prop instead of a Svelte `$bindable`: pass `value` + `onValueChange` to control the selection; omit `value` entirely and the group keeps its own internal copy (seeded to "") and still reports every change through `onValueChange`. No `defaultValue` prop was added.
|
|
343
|
+
- **tool-call**: Snippet props become render props: `input`/`output` are `(value: unknown) => ReactNode` receiving `call.input`/`call.output`; `icon` (parameterless snippet) is a plain `ReactNode`.
|
|
344
|
+
- **tool-call**: `bind:open` becomes the standard controlled/uncontrolled split: `open` is uncontrolled by default (auto-open on failure still applies) and controlled when the prop is passed — pair it with `onToggle`; when controlled, a header click reports through `onToggle` but the parent owns the value.
|
|
345
|
+
|
|
346
|
+
- **alert-dialog**: Inherits every divergence recorded in `react/src/components/dialog/README.md`, since this renders through the same imported `DialogSurface`: portal target is `document.body` via `createPortal` (panel/scrim absent from server HTML), `data-state` is an ordinary attribute with the two anchored values, no portal-before-focus-trap ordering ceremony.
|
|
347
|
+
- **alert-dialog**: No behavioural divergence: `escape={true}` / `outsideClick={false}` stay literals, Escape still routes through the same `handleCancel` the Cancel button calls, Cancel still renders first in DOM order so it is the focus trap's default target, and `onCancel` still fires before `setOpen`'s no-op guard exactly as the source orders it.
|
|
348
|
+
- **alert-dialog**: `class` -> `className` and `trigger: Snippet` -> `trigger: ReactNode` (PORTING.md API contract). Every other member of `AlertDialogProps` keeps its source name, type and default.
|
|
349
|
+
- **alert-dialog**: `open = $bindable(false)` -> an internal `useState` copy re-synced during render whenever the caller changes the prop (identical to the already-ported `Dialog`). Consumer-visible effect: `open` is a plain controlled prop plus `onOpenChange`, and a caller passing only `onOpenChange` (or neither, letting `trigger` drive it) still works.
|
|
350
|
+
- **alert-dialog**: `ref = $bindable(null)` -> `forwardRef<HTMLDivElement, AlertDialogProps>`, so `AlertDialogProps` has no `ref` field; the panel element arrives through the component's ref channel, forwarded straight through `DialogSurface`.
|
|
351
|
+
- **artifact-card**: `actions?: Snippet` becomes `actions?: ReactNode` — pass JSX instead of a snippet; it is still rendered inside `.ft-artifact-actions` and still guarded from the card-wide open click.
|
|
352
|
+
- **artifact-card**: `class` prop is `className` (standard React rename); every Tailwind literal is copied verbatim.
|
|
353
|
+
- **artifact-card**: `ref` is not a prop: the Svelte `ref = $bindable(null)` becomes `forwardRef<HTMLDivElement, ArtifactCardProps>`, so the root element arrives through the ref channel.
|
|
354
|
+
- **autocomplete**: D-12: `useElementRef` costs one extra render at mount for both the input and the panel; lands before paint, not visible.
|
|
355
|
+
- **autocomplete**: D-1: `createPortal` renders into `document.body` instead of relocating a rendered node, so the panel is absent from server HTML (inert in practice — `open` starts false).
|
|
356
|
+
- **autocomplete**: D-2: `markSurfaceState` is not ported; `data-state` is an ordinary React attribute fed by `presence.surfaceState`. Same two emitted values, "open" and "closing".
|
|
357
|
+
- **autocomplete**: D-6: `dismissable`'s `active` is the plain boolean `ctx.open`; `exclude` keeps its getter form. `useAnchorPosition`'s return value replaces the source's `onPlacement` closure over two `$state` variables, seeded with the requested `bottom` / `start` exactly as the source seeds its own.
|
|
358
|
+
- **autocomplete**: Faithfully ported source bug: `data-align` is written as the static literal "start" on the panel even though the resolved align moves — the resolved value feeds only `transform-origin`.
|
|
359
|
+
- **autocomplete**: The `{#if open}` gate moves one level down: `AutocompletePanel` is rendered unconditionally and owns its own `usePresence(ctx.open)` clock. Hoisting the gate would put the panel's `Portal` in the same commit as the surface and silently skip the entrance animation (same reason `DialogSurface` hoists its Portal). A `Portal` with no children renders no DOM, so a closed autocomplete still costs nothing.
|
|
360
|
+
- **autocomplete**: The exiting panel holds an explicit snapshot of `suggestions` / `query` / `activeIndex`, refreshed on every open render and frozen while closing. Svelte gets this free by marking the closing `{#if}` branch inert (its scheduler skips inert effects); React re-renders an exiting subtree normally, and without the snapshot the most common close here — a keystroke whose query stops matching — would empty the list to a bare box mid-fade. Covered by the one PORT ADDITION test.
|
|
361
|
+
- **autocomplete**: `AUTOCOMPLETE_KEY` is a React context object (`createInternalContext`) rather than a `unique symbol`. Same public name and identity role; read by the panel with `.useRequired()`.
|
|
362
|
+
- **autocomplete**: `class` prop is `className` (PORTING.md API contract).
|
|
363
|
+
- **autocomplete**: `ref = $bindable` becomes `forwardRef<HTMLInputElement>`; `AutocompleteProps` carries no `ref` field. The forwarded ref is composed with a `useElementRef` because the panel needs the input NODE for its anchor and outside-click exclusion (convention C-1).
|
|
364
|
+
- **autocomplete**: `value = $bindable("")` becomes an internal copy that the `value` prop SEEDS and re-seeds during render whenever the consumer actually changes it. This keeps all three source-tested call shapes working off one implementation (consumer-owned value, `onValueChange` only, and a plain `value` the consumer never updates) — a strict controlled/uncontrolled split fails the third, which the source suite tests explicitly.
|
|
365
|
+
- **chat-message**: CHAT_MESSAGE_CONTEXT_KEY is a React context object (createContext<ChatMessageContext | undefined>(undefined)) instead of the Svelte Symbol context key; parts read it with useContext(CHAT_MESSAGE_CONTEXT_KEY) rather than getContext(KEY). Same exported name, same optional-read degradation outside a root. Follows the already-ported sources/ precedent.
|
|
366
|
+
- **chat-message**: ChatMessageAction's `onclick` prop is `onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void` — React naming and a synthetic event, so handlers receive the native event as `event.nativeEvent` (PORTING.md / NavbarLink precedent).
|
|
367
|
+
- **chat-message**: Relative timestamps are blank in server-rendered HTML and fill in during hydration, before the first paint. Svelte's `createNow` seeds itself with `Date.now()`, so its server HTML carries real labels; React's client has no way to reproduce the server's timestamp, so `useNow()` returns a not-started sentinel until the clock is retained in the layout phase and `formatRelativeTime` renders that as an empty string rather than a wrong label. Inherited from `useNow`; shared with `ThreadList` and `ToolTimeline`.
|
|
368
|
+
- **chat-message**: The snippet props (`avatar`, `actions`, `footer`, `children`) are ReactNode and are rendered on truthiness, so a deliberately falsy node (0, "", false) renders nothing where Svelte's `{#if snippet}` could never receive one.
|
|
369
|
+
- **chat-message**: Timestamp clock: the Svelte root builds a private createNow() and only starts it inside $effect while a valid timestamp is shown. React calls useNow() unconditionally (a hook cannot be conditional), so a ChatMessage rendered without a `timestamp` also joins the shared clock. Net cost is lower, not higher — useNow is one page-wide interval shared by every consumer, where the Svelte side paid one interval per message — and it still stops when the last consumer unmounts (asserted by the 'stops ticking once unmounted' test).
|
|
370
|
+
- **chat-message**: `class` is `className` on all four parts, and the Svelte `ref = $bindable(null)` on ChatMessage becomes forwardRef<HTMLElement, ChatMessageProps> (no `ref` prop). The three parts expose no ref, matching the Svelte API surface.
|
|
371
|
+
- **checkbox**: `bind:checked` becomes the standard controlled/uncontrolled split: uncontrolled by default (new `defaultChecked` prop seeds the initial state), controlled when `checked` is passed together with `onCheckedChange`.
|
|
372
|
+
- **checkbox**: `bind:indeterminate` becomes a prop that seeds local state and resyncs whenever the prop changes; any interaction that changes `checked` clears it locally — a controlled caller learns the cleared state through `onCheckedChange` and simply stops re-passing `true`.
|
|
373
|
+
- **checkbox**: `class` becomes `className` (merged onto the wrapping `<label>` via `cn()`, same literals and argument order).
|
|
374
|
+
- **checkbox**: `ref = $bindable(null)` becomes `forwardRef`, delivering the native `<input>` element through the standard React ref channel.
|
|
375
|
+
- **code-diff**: Root class `fancy-code-diff` is a PORT-ADDED anchor (PORTING.md styling rule 2): the Svelte <style> block had no root class, so all .ft-* rules are anchored under it in code-diff.css.
|
|
376
|
+
- **code-diff**: Test transposition: `body().inert` property assertions became `hasAttribute("inert")` (jsdom has no inert IDL; matches sources/dialog tests), the user-select rule regex now matches the anchored selectors in code-diff.css, and the `await tick()` after rerender is unnecessary (RTL flushes effects).
|
|
377
|
+
- **code-diff**: `collapsed` bindable prop becomes `collapsed?: boolean` (master-switch seed, re-seeds on prop change) + `onCollapsedChange?: (collapsed: boolean) => void` reporting the aggregate a header click produces — the established pattern for bindable booleans in this package.
|
|
378
|
+
- **combobox**: React portals bubble SYNTHETIC events through the React tree where a Svelte-moved node's native events stop at `<body>` (inherited contract divergence D-1; inert in practice — `useDismissable` listens natively on `document`).
|
|
379
|
+
- **combobox**: The panel freezes `options`/`query`/`activeIndex` for the length of the exit, refreshed only while `ctx.open` is true. Svelte gets this free by marking the closing `{#if}` branch inert (its scheduler skips inert effects); React re-renders an exiting subtree normally. Load-bearing here because `close()` resolves the query back to the selected option's label in the same turn it flips `open`, which un-filters the list.
|
|
380
|
+
- **combobox**: The panel is rendered UNCONDITIONALLY where the source writes `{#if open}<ComboboxPanel />{/if}`; `ComboboxPanel` keeps its `<Portal>` mounted and gates only the panel `<div>` on `presence.mounted`. A Portal first mounting in the same commit as the surface resolves its container a layout effect too late and silently skips the entrance leg (same divergence the Dialog port records).
|
|
381
|
+
- **combobox**: `COMBOBOX_KEY` is a React context object built with the shared `createInternalContext` helper, not a Svelte `Symbol`. Read with `COMBOBOX_KEY.useRequired()`, provided with `<COMBOBOX_KEY.Provider>`. Same shape as SELECT_KEY / AUTOCOMPLETE_KEY / TIME_PICKER_KEY.
|
|
382
|
+
- **combobox**: `class` -> `className`; the Svelte `ref = $bindable(null)` becomes `forwardRef`, so `<Combobox ref={...} />` yields the `<input>` element.
|
|
383
|
+
- **combobox**: `data-state` is an ordinary React attribute carrying `presence.surfaceState`'s two values (contract divergence D-2); `markSurfaceState` / `onoutrostart` are not ported. `inert` is set by `usePresence` on the registered node rather than by Svelte's transition machinery.
|
|
384
|
+
- **combobox**: `value`: React has no `$bindable` channel, so the prop SEEDS an internal copy and re-seeds it whenever the caller actually changes it (the Select/TimePicker/Autocomplete house spelling). A caller that writes `value` back from `onValueChange` is fully controlled; one that never updates it still selects, submits and resolves-on-blur against the option actually picked, as in Svelte.
|
|
385
|
+
- **command-menu**: The portal-before-focus-trap ordering ceremony is gone: `createPortal` commits children before any effect runs, so the detached-`.focus()` hazard cannot recur (contract D-10).
|
|
386
|
+
- **command-menu**: `class` -> `className` (house rule for every port).
|
|
387
|
+
- **command-menu**: `data-state` is an ordinary React attribute carrying `presence.surfaceState` ("open" | "closing") instead of the Svelte static literal mutated by `markSurfaceState` — same DOM values, never "opening" (contract C-5 / D-2).
|
|
388
|
+
- **command-menu**: `empty: Snippet` -> `empty?: ReactNode` (no-argument snippet is just a node).
|
|
389
|
+
- **command-menu**: `icon: Snippet<[CommandItem]>` -> `icon?: (item: CommandItem) => ReactNode` (parameterised snippet becomes a render function).
|
|
390
|
+
- **command-menu**: `open` / `query` bindable -> controlled-or-uncontrolled props: an internal copy seeded from the prop and re-synced during render when the caller changes it; `onOpenChange` / `onQueryChange` are the only way a value gets back out (no two-way binding channel in React).
|
|
391
|
+
- **command-menu**: `ref = $bindable(null)` -> `forwardRef<HTMLDivElement, CommandMenuProps>`; the panel element is what the forwarded ref receives.
|
|
392
|
+
- **command-menu**: Filter/display/group pipeline and per-row match ranges recompute on every render, including the arrow-key re-renders the source caches through `$derived`/`{@const}`; identical output, no memoisation.
|
|
393
|
+
- **composer**: COMPOSER_CONTEXT_KEY is a `React.Context` object read with `useContext(...)`, not a `Symbol` passed to `getContext(...)`. The exported name and the `ComposerContext` shape are unchanged.
|
|
394
|
+
- **composer**: Composer: Svelte's `value = $bindable("")` becomes `value` + `onValueChange`; controlled when `value` is passed, internal copy when it is not. Same split for `attachments = $bindable([])` -> `attachments` + `onAttachmentsChange`.
|
|
395
|
+
- **composer**: Composer: passing `value` WITHOUT `onValueChange` freezes the draft outright (React cannot write a controlled value it was not handed back). The Svelte side keeps writing its local copy for an unbound `value`. `onValueChange` is effectively required whenever `value` is passed.
|
|
396
|
+
- **composer**: ComposerModelPicker: `value = $bindable()` becomes `value` + a new `onValueChange` prop (fires on every pick, changed or not). `onChange` keeps its Svelte semantics exactly — silent when the pick changes nothing.
|
|
397
|
+
- **composer**: Snippet props are ReactNode: Composer `children`/`accessory`, ComposerSubmit/ComposerToolbar/ComposerAttachments `children`, ComposerCommandMenu `empty`.
|
|
398
|
+
- **composer**: The context object is rebuilt on every root render (that rebuild is what re-renders the parts reading the draft), where Svelte published one object with live getters. A consumer that captures the handle and reads `value.current`/`attachments.current` later sees a snapshot; every command (`submit`, `stop`, `setValue`, `insertText`, `addFiles`, `removeAttachment`) and `textareaRef` are identity-stable and always reach the latest state.
|
|
399
|
+
- **composer**: `class` is `className` on every part (repo-wide convention).
|
|
400
|
+
- **composer**: ref: Composer / ComposerInput / ComposerCommandMenu declare `ref = $bindable(null)` on the Svelte side, so they are `forwardRef` here (form element / textarea / menu div respectively) — there is no `ref` prop. ComposerSubmit, ComposerToolbar, ComposerModelPicker, ComposerAttachments and ComposerAttachment expose no ref, matching the source.
|
|
401
|
+
- **context-menu**: ContextMenuRootContext.close() is typed with the shared MenuCloseOptions ({ returnFocus?, silent? }) instead of the Svelte side's narrower { returnFocus?: boolean }. `silent` is ignored (this family plays no sound), so behaviour is identical; the widening is what lets MenuContext.closeAll forward its options object unchanged, exactly as the Svelte source does at runtime.
|
|
402
|
+
- **context-menu**: ContextMenuTrigger is forwardRef<HTMLDivElement> and ContextMenuContent forwardRef<HTMLDivElement> (both Svelte sides declare `ref = $bindable(null)`); ContextMenu itself takes no ref, as in the source. Neither trigger nor content spreads rest props — the Svelte sources declare none.
|
|
403
|
+
- **context-menu**: Post-open focus is moved in a passive effect where the source moves it in a `tick()` microtask, so the panel paints one frame before the focus ring lands on the first or last item; the anchored entrance is still animating at that point.
|
|
404
|
+
- **copy-button**: No rest-prop spread, deliberately: the Svelte `CopyButtonProps` interface declares an explicit prop list with no `...restProps`, so the React `CopyButtonProps` is a standalone interface rather than one extending `ButtonHTMLAttributes`. Fidelity to the Svelte API surface, but a departure from PORTING.md's general "rest props spread onto the root element" default — worth a line in react/README.md.
|
|
405
|
+
- **copy-button**: StatusMorph's inline `style` string becomes a module-scope `CSSProperties` object (React accepts no style strings). The serialized attribute is equivalent — `width: 1rem; height: 1rem; font-size: calc(1rem - 1px); --ft-statusmorph-error: var(--ft-status-error, light-dark(...))` — and both assertions on that attribute pass unchanged.
|
|
406
|
+
- **copy-button**: The Svelte `<style>` block's two `:global()` wrappers are dropped in copy-button.css: plain CSS is already global, and both selectors (`.ft-copybtn--copied`, `.ft-copybtn--failed`) are root-class modifiers, so no port-added anchor class was needed.
|
|
407
|
+
- **copy-button**: `bind:state={morphState}` on StatusMorph becomes `state={morphState}` + `onStateChange={setMorphState}` — the two-way-binding stand-in the already-ported StatusMorph declares. Behaviour is identical: the morph's own `resetAfter` timer still writes "idle" back into CopyButton's state.
|
|
408
|
+
- **copy-button**: `children?: Snippet` becomes `children?: ReactNode`. The Svelte `{#if children}` / `children ? … : …` truthiness tests are kept verbatim as `Boolean(children)`, so a React children value of `0`, empty string or `false` reads as "no custom content" — the same reading the Svelte side gives a falsy snippet slot.
|
|
409
|
+
- **copy-button**: `class` prop becomes `className` (package-wide convention).
|
|
410
|
+
- **copy-button**: `ref = $bindable(null)` becomes `forwardRef<HTMLButtonElement | HTMLAnchorElement, CopyButtonProps>`, forwarded to the inner Button exactly as the Svelte source does.
|
|
411
|
+
- **copy-button**: `untrack(() => resetMs)` becomes `useConstant(() => resetMs)` (internals/dom/ssr.js), and `createCopy(resetWindow)` + `$effect(() => copyState.destroy)` becomes `useCopy(resetWindow)` (internals/use-copy.js), which owns arm/destroy. Same observable contract: the window is fixed at mount, a later `resetMs` change is ignored by both skin and glyph, and unmount cancels the pending timer (both asserted).
|
|
412
|
+
- **date-picker**: `bind:value` becomes the standard React controlled/uncontrolled split: `value` is controlled when the prop is passed (caller writes it back from `onValueChange`), uncontrolled with an internal copy when omitted
|
|
413
|
+
- **date-picker**: `data-state` on the panel is an ordinary React attribute carrying `presence.surfaceState` ("open" | "closing") instead of the source's imperative `markSurfaceState` transition handlers (register-wide divergence D-2); `inert` during exit is set by `usePresence`, not written by hand
|
|
414
|
+
- **date-picker**: `ref = $bindable` on the trigger button becomes `forwardRef` exposing the `<button>` element
|
|
415
|
+
- **date-picker**: `viewDate`/`focusedDate` start as `null` and are seeded on first open rather than with `dayOnly(new Date())` at construction (C-7: no `new Date()` in a render path); not observable — nothing reads either before `openPanel` seeds them and the live region is empty while closed on both sides
|
|
416
|
+
- **dock**: Context key: Svelte's `DOCK_CONTEXT_KEY = Symbol("dock-context")` becomes a React context object of the same name in types.ts. Neither barrel exports it, so the public API surface is unchanged.
|
|
417
|
+
- **dock**: Dock tracks and cancels any rAF still queued at unmount; the Svelte source relies on its scheduler tearing the component down first. No observable behaviour change — a cancelled frame had nothing left to paint into.
|
|
418
|
+
- **dock**: Media queries go through `useMediaQuery`/`useReducedMotion` (useSyncExternalStore) instead of `createMediaQuery().start()` in an `$effect` — internals-contract divergence D-4. SSR and the hydration render still answer `false`/`false` (identical to the Svelte fallback), but on a client-only first render `magnify` is already correct instead of settling one effect pass later.
|
|
419
|
+
- **dock**: `DockContext.mouseX`/`mouseY` keep the exact `{ current: number }` shape, but the box is REBUILT by Dock on every pointer frame instead of being mutated in place — a mutated object is invisible to React and the new identity is what re-renders the icons.
|
|
420
|
+
- **dock**: index.ts re-exports the three components plus their Props types AND the `DataOrientation`, `Direction`, `DockContext` types, mirroring the Svelte index.ts exactly (a superset of the three components + Props types requested in the brief; DockProps references `Direction`/`DataOrientation`, so consumers need them).
|
|
421
|
+
- **drawer**: No portal-before-focus-trap ordering ceremony (contract divergence D-10): createPortal commits before effects, so the trap always focuses a connected node
|
|
422
|
+
- **drawer**: Per-frame drag offset lives in a ref with direct element.style writes instead of reactive state (group guidance); the spring-back class is applied via flushSync so the CSS transition and the transform reset land in the same frame, matching Svelte's batched flush
|
|
423
|
+
- **drawer**: Scroll lock is `useScrollLock(presence.mounted)` rather than an outro-delayed action destroy — identical release timing (page unlocks when the slide-out finishes)
|
|
424
|
+
- **drawer**: `bind:open` becomes the standard controlled shape: `open` prop + `onOpenChange`, with an internal copy re-synced during render (same pattern as Dialog) — a caller closing the drawer must do it via the prop, not a two-way binding
|
|
425
|
+
- **drawer**: `bind:ref` becomes `forwardRef` to the panel div; `class` becomes `className`; `children`/`footer` snippets become ReactNode props
|
|
426
|
+
- **drawer**: `data-state` is an ordinary attribute carrying `surfaceState`'s two values instead of a static literal mutated by `markSurfaceState` (contract divergence D-2); `inert` during the exit is set by `usePresence`, not the framework
|
|
427
|
+
- **drawer**: React adds an `ariaLabel` prop (no Svelte counterpart yet) so a title-less panel can carry an accessible name; the Svelte side is tracked to mirror it.
|
|
428
|
+
- **form-field**: Generated ids come from `useFancyId()` (React `useId()`) rather than `$props.id()`, so the seed's literal shape differs (`fui-«r0»-control` / `fui-:r0:-control` instead of Svelte's). Suffix contract is identical (`<base>-label` / `-description` / `-error`), and an explicit `id` prop produces byte-identical ids on both sides. Consequence, per C-6: a generated id must never be used as an unescaped CSS selector.
|
|
429
|
+
- **form-field**: `children` is `ReactNode` instead of a `Snippet`; `class` becomes `className`; the Svelte `ref = $bindable(null)` becomes `forwardRef<HTMLDivElement>` (all three per PORTING.md).
|
|
430
|
+
- **hover-card**: Resolved side/align come from `useAnchorPosition`'s return value (seeded with the requested values) instead of the `onPlacement` + `$state` pair, per the internals contract §3.1.
|
|
431
|
+
- **hover-card**: `markSurfaceState` is not ported (contract D-2): `data-state` is an ordinary attribute rendering `presence.surfaceState`'s two values, and `inert` during the exit is written by `usePresence` rather than by Svelte's outro machinery — observable DOM is identical.
|
|
432
|
+
- **hover-card**: `open = $bindable(false)` becomes the controlled/uncontrolled pattern used by Popover: internal state seeded from the prop, re-synced during render when the caller changes it, plus `onOpenChange`.
|
|
433
|
+
- **hover-card**: `ref = $bindable(null)` (trigger wrapper element) arrives via `forwardRef` instead of a bindable prop.
|
|
434
|
+
- **hover-card**: `trigger` snippet (Snippet<[descriptionId]>) becomes a render-prop function `(descriptionId: string | undefined) => ReactNode`, per the house precedent for parameterized snippets (Breadcrumb.item, ThreadList.item).
|
|
435
|
+
- **icon-button**: `children?: Snippet` becomes `children?: ReactNode`, still forwarded as Button's `iconStart` (not as Button's children), so the loading spinner replaces the icon exactly as in Svelte.
|
|
436
|
+
- **icon-button**: `class` prop is `className` (PORTING.md rename); Tailwind literals, SIZE_CLASSES/VARIANT_EXTRA_CLASSES tables and the `cn()` argument order are copied verbatim.
|
|
437
|
+
- **icon-button**: `onclick` is renamed `onClick` and typed `(event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void` instead of the DOM `MouseEvent` — the same rename and typing the ported `Button` carries.
|
|
438
|
+
- **icon-button**: `ref = $bindable(null)` becomes `forwardRef<HTMLButtonElement | HTMLAnchorElement, IconButtonProps>` and is therefore not a member of `IconButtonProps` (the Svelte interface listed it).
|
|
439
|
+
- **image-generation**: Port addition, not consumer-visible in production: the mount effect carries a once-guard ref so React's development StrictMode double-invoke of mount effects cannot fire `onLoad` twice for an image that was already `complete` at mount. Production behaviour is identical to the Svelte `onMount`.
|
|
440
|
+
- **image-generation**: The Svelte `ref = $bindable(null)` prop becomes `forwardRef<HTMLDivElement>` — the root element ref is obtained with a React ref rather than a bound prop, so `ref` is absent from `ImageGenerationProps`.
|
|
441
|
+
- **image-generation**: `class` prop becomes `className` (standard PORTING.md rename; every other prop name, default and type is unchanged).
|
|
442
|
+
- **inline-citation**: Port-internal only, no consumer-visible effect: `open` is mirrored into a synchronous `openRef` alongside `setOpen`, because the Svelte handlers read a live `$state` while React handlers close over their render's value — the `onOpen`-once-per-appearance and grace-window branches depend on a fresh read.
|
|
443
|
+
- **inline-citation**: Test-only: the Svelte `InlineCitationHarness.test.svelte` becomes `InlineCitationHarness.tsx` (plain `.tsx`, so vitest does not collect it as its own suite — the same shape `SourcesHarness.tsx` already uses). It is not exported from `index.ts`.
|
|
444
|
+
- **inline-citation**: `class` -> `className` (package-wide convention).
|
|
445
|
+
- **inline-citation**: `preview` was `Snippet<[SourceData]>`; in React it is a render prop `preview?: (source: SourceData) => ReactNode` — a parameterised snippet cannot collapse to a bare `ReactNode`. Same call site (`preview(source)`), same truthiness test for the `border p-3` chrome.
|
|
446
|
+
- **inline-citation**: `ref = $bindable(null)` (typed `HTMLElement | null`) -> `forwardRef<HTMLElement, InlineCitationProps>`; the `ref` entry is therefore gone from the props interface. The forwarded ref is composed with the internal `useElementRef` marker ref, since the float anchor needs the same node.
|
|
447
|
+
- **input**: The Svelte `oninput` handler becomes React `onChange` (fires per keystroke, identical observable behaviour); while disabled, a synthetic input event additionally has the DOM value restored to the model value, mirroring the Checkbox port's guard.
|
|
448
|
+
- **input**: `bind:ref` becomes `forwardRef`, pointing at the native `<input>`.
|
|
449
|
+
- **input**: `bind:value` becomes the standard React controlled/uncontrolled split: `value` + `onValueChange` when controlled, new `defaultValue` prop (default "") for the uncontrolled initial value — a `value` prop passed alone now pins the input instead of seeding it.
|
|
450
|
+
- **input**: `class` becomes `className`; the `autocomplete` prop is typed as React's `HTMLInputAutoCompleteAttribute` instead of Svelte's `FullAutoFill` (same DOM token set).
|
|
451
|
+
- **label**: Label: the Svelte `for` prop is `htmlFor` in React (JSX reserved-word convention); rendered DOM still carries the `for` attribute.
|
|
452
|
+
- **magnetic**: reduced motion is read via useReducedMotion() (useSyncExternalStore); the Svelte createReducedMotion().start() lifecycle has no counterpart (internals contract D-4) — observable behavior identical, including runtime flips tearing the field down
|
|
453
|
+
- **magnetic**: style merging: the inline --ft-magnetic-radius var merges into React's style object (a consumer-passed `style` prop is spread first, the var wins), instead of Svelte's style-attribute + style: directive merge
|
|
454
|
+
- **magnetic**: The halo `::before` rule is plain CSS at specificity (0,1,1) where the Svelte compiler emitted a scoped selector at (0,2,1), so a consumer rule of equal specificity can now win on source order and override `pointer-events: none` on the halo.
|
|
455
|
+
- **navigation-menu**: D-12: `useElementRef` costs one extra render when the panel mounts (pre-paint, not visible).
|
|
456
|
+
- **navigation-menu**: D-1: `createPortal` renders the panel into `document.body` instead of relocating an already-rendered node; synthetic events still bubble through the React tree, which nothing here relies on.
|
|
457
|
+
- **navigation-menu**: D-2: `markSurfaceState` is not ported — `data-state` is an ordinary React attribute fed by `presence.surfaceState`, same two values (`"open"` / `"closing"`).
|
|
458
|
+
- **navigation-menu**: D-6: `useDismissable`'s `active` is the plain boolean `isOpen`; `exclude` keeps its getter form.
|
|
459
|
+
- **navigation-menu**: The panel's focus effect checks the node BEFORE consuming the request, where the source checks it after — `useElementRef` publishes the panel one commit after the branch mounts, so consuming on the null pass would spend the request on nothing. Same observable behaviour, one guard reordered.
|
|
460
|
+
- **navigation-menu**: `Portal` is hoisted above the `presence.mounted` gate, and `useAnchorPosition`'s return value replaces the source's `resolvedSide`/`resolvedAlign` state pair plus its `onPlacement` callback (DialogSurface's two contract divergences in shape).
|
|
461
|
+
- **navigation-menu**: `consumeFocusRequest`'s identity changes with the pending focus value (Svelte's implicit `$state` subscription has no React equivalent); `requestFocus`, `registerTrigger` and `setListRef` stay identity-stable. Observable behaviour is identical.
|
|
462
|
+
- **navigation-menu**: `onfocusout` becomes React's `onBlur` (which is `focusout` under React 17+ and still bubbles from a link inside the panel).
|
|
463
|
+
- **navigation-menu**: `value = $bindable("")` becomes a controlled-when-passed internal copy plus a live `valueRef` written eagerly by `setValue`, reproducing a `$state` assignment being visible to the very next statement.
|
|
464
|
+
- **number-input**: `bind:ref` becomes `forwardRef`, pointing at the native `<input>`.
|
|
465
|
+
- **number-input**: `bind:value` becomes the standard controlled/uncontrolled split: controlled via `value` + `onValueChange` when the `value` prop is passed (`null` counts as a value meaning empty), uncontrolled via `defaultValue` (default `null`) otherwise — matching the convention Input established.
|
|
466
|
+
- **number-input**: `class` becomes `className`.
|
|
467
|
+
- **password-input**: Svelte's `await tick()` selection restore becomes a layout effect keyed on `revealed`: selection captured in the click handler, restored after the new `type` commits — same setSelectionRange(start, end, direction) call
|
|
468
|
+
- **password-input**: The closing icon layer gets `inert` set by usePresence's default during its 80ms exit (mirrors Svelte 5's own outro inert behaviour; both glyphs are aria-hidden so it is observable only as an attribute)
|
|
469
|
+
- **password-input**: The icon cross-fade's bidirectional `transition:` pair is reproduced with two `usePresence` clocks feeding the same `preset("fade")` through the WAAPI sampler — same 80ms micro duration, same reduced-motion duration-0 instant-swap path, both layers animate during the swap
|
|
470
|
+
- **password-input**: `bind:ref` becomes `forwardRef`, pointing at the native <input>
|
|
471
|
+
- **password-input**: `bind:value` becomes the controlled/uncontrolled split: `value` + `onValueChange` when controlled, new `defaultValue` prop when uncontrolled (same pattern as the Input port)
|
|
472
|
+
- **password-input**: `class` prop becomes `className` (standard port rename)
|
|
473
|
+
- **password-input**: handleInput's disabled guard additionally writes the model value back into the DOM (Input-port pattern) so a synthetic input on a disabled control cannot leave the visible text diverged from React's controlled value
|
|
474
|
+
- **password-input**: During the 80 ms icon cross-fade the two layers share one grid cell with no z-index, so paint order follows DOM order: the React layers sit in a fixed order (eye-off first, eye second) where the Svelte `{#if}`/`{:else}` always inserts the entering branch after the outgoing one, so the entering glyph paints on top in both directions there and in only one direction here. Both glyphs are aria-hidden and the overlap lasts 80 ms.
|
|
475
|
+
- **popover**: Inherited internals-contract divergences apply unchanged: D-1 (createPortal), D-2 (`data-state` is an ordinary attribute; `markSurfaceState` not ported), D-3 (focus-trap `onActivate` becomes the hook's return value), D-6 (`dismissable.active` is a plain boolean, not a getter), D-10 (no portal-before-focus-trap ordering), D-12 (`useElementRef` costs one extra pre-paint render at the panel's mount).
|
|
476
|
+
- **popover**: Ported as-is, not fixed: `data-align` publishes the REQUESTED alignment while `transform-origin` follows the RESOLVED one, exactly as the Svelte panel does.
|
|
477
|
+
- **popover**: `POPOVER_KEY` is a React context object (`React.Context<PopoverContext | undefined>`) where the Svelte side exports a `unique symbol` — same name, same role, read with `useContext(POPOVER_KEY)`. Matches the `MENU_KEY`/`SUB_KEY`/`DROPDOWN_MENU_KEY` precedent in the dropdown-menu port.
|
|
478
|
+
- **popover**: `Popover` renders `<PopoverContent>` unconditionally where the Svelte root wraps it in `{#if open}`. The panel owns its own mount clock (`usePresence`), which keeps it on screen for the exit, and hoisting it also lets its `Portal` resolve a container before the commit that opens the panel — mounting the portal in that same commit would leave `usePresence` with no attached node and silently skip the entrance. Same shape as the Dialog/DialogSurface port. No consumer-visible DOM difference: a closed popover still emits nothing.
|
|
479
|
+
- **popover**: `class` -> `className`, and the panel `ref` is the component's `forwardRef` channel rather than a `ref` prop (both `Popover` and `PopoverContent` declare `ref = $bindable(null)` on the Svelte side, so both get `forwardRef<HTMLDivElement>`).
|
|
480
|
+
- **popover**: `open` is an internal copy seeded from the prop and re-synced during render when the caller changes it (the React shape of `open = $bindable(false)`), not a strict controlled prop. Required for the source's own `open={false} + onOpenChange` call shape to still open itself.
|
|
481
|
+
- **pressable**: Svelte's suppressed `onfocusout` consumer prop becomes React's `onBlur` (both are the native bubbling focusout listener); the omitted handler props are the React camelCase names (onPointerDown/onPointerUp/onPointerCancel/onPointerLeave/onBlur/onKeyDown/onKeyUp).
|
|
482
|
+
- **radio-group**: Outside a RadioGroup, RadioGroupItem renders its input UNCONTROLLED (`defaultChecked={false}` instead of `checked={isChecked}`). React restores a controlled `checked={false}` immediately after the click and would undo the browser's own local check, which the Svelte source leaves standing. Observable behaviour matches Svelte; the prop shape does not.
|
|
483
|
+
- **radio-group**: RadioGroupItem's content fallback is `children != null ? children : (label ?? value)` where Svelte uses `{#if children}` truthiness — an explicitly falsy-but-present child (empty string, `false`) renders as-is instead of falling back to `label ?? value`.
|
|
484
|
+
- **radio-group**: Sound: `useSoundCue` forwards its optional `options` argument, so the singleton is called as `sound.play("select", undefined)` where the Svelte call site passes one argument. No behavioural difference; the transposed spy assertions record two args.
|
|
485
|
+
- **radio-group**: The generated `name` is `${useFancyId()}-name` (e.g. `fui-«r0»-name`) rather than `${$props.id()}-name`, so the literal string differs between packages. Same per-instance, SSR-stable guarantee.
|
|
486
|
+
- **radio-group**: `RADIO_GROUP_KEY` is a `React.Context` object rather than a `Symbol` context key — `useContext(RADIO_GROUP_KEY)` replaces `getContext(RADIO_GROUP_KEY)`. The exported name is unchanged (same convention as TOGGLE_GROUP_KEY).
|
|
487
|
+
- **radio-group**: `class` becomes `className` on both RadioGroup and RadioGroupItem.
|
|
488
|
+
- **radio-group**: `ref` is the forwardRef channel on both components, not a prop (Svelte declares `ref = $bindable(null)` on each: root `<div>` for RadioGroup, native `<input>` for RadioGroupItem).
|
|
489
|
+
- **radio-group**: `value` is controlled-when-supplied with internal state as the fallback (React has no `bind:`). A Svelte caller passing a plain, non-bound `value="a"` got a group that then updated itself; the React equivalent needs `onValueChange`. No `defaultValue` prop was added — this mirrors the ToggleGroup port exactly.
|
|
490
|
+
- **reasoning-panel**: Root anchor class `fancy-reasoning-panel` added as the first cn() token (PORTING.md styling rule 2 sanctioned addition) to scope the formerly compiler-scoped .ft-body/.ft-chevron/.ft-shimmer rules.
|
|
491
|
+
- **reasoning-panel**: `open` is not bindable in React: a changed `open` prop is adopted as the new state during render and announced through `onToggle` — same observable behaviour as a consumer writing to `bind:open`, but the component cannot push its automatic open/collapse back into a parent-held variable; a consumer holding `open` in state should update it from `onToggle`.
|
|
492
|
+
- **recommendation-card**: Svelte's `children` Snippet becomes React `children: ReactNode`; the `.ft-rec-detail` wrapper is still rendered only when children are present.
|
|
493
|
+
- **recommendation-card**: Svelte's post-decision `tick().then(() => resolvedRef?.focus())` becomes a `shouldFocusResolved` ref read by a no-deps `useEffect`, so focus still lands on `.ft-rec-resolved` after the footer swap (same observable behaviour, same ApprovalCard pattern).
|
|
494
|
+
- **recommendation-card**: `ref = $bindable(null)` becomes `forwardRef<HTMLDivElement, RecommendationCardProps>` (no `ref` entry in the Props interface), per PORTING.md.
|
|
495
|
+
- **recommendation-card**: `state` is `$bindable("open")` in Svelte; React exposes it as a controlled/uncontrolled pair — supply `state` + the new `onStateChange?: (state: RecommendationState) => void` prop to own the value, omit both and the card keeps it internally starting at "open". Same shape as the already-ported ApprovalCard.
|
|
496
|
+
- **scroll-anchor**: `class` prop is `className`; the `ref = $bindable` root ref is exposed via forwardRef (standard port mapping, no behavioral change).
|
|
497
|
+
- **scroll-anchor**: The initial pin-geometry read runs in a passive `useEffect` rather than Svelte's pre-paint `$effect`, so a region that mounts already overflowing shows the return pill one frame later; no behavioural difference.
|
|
498
|
+
- **search-input**: Focus returns to the input synchronously inside `clearValue()` before React commits the button's removal (Svelte removes the button in the same update); observable ordering is identical.
|
|
499
|
+
- **search-input**: The Svelte `in:pop` directive is reproduced with the motion contract's sampler: `runTransition` started from the clear button's ref callback at attach time (same pre-paint moment, same preset("scale") keyframes, same reduced-motion duration-0 fast path); no intro on the initial render, matching Svelte's local-transition rule. No `usePresence` — the source deliberately has no outro, and the button must leave the DOM in the same tick as the focus handoff.
|
|
500
|
+
- **search-input**: `bind:value` becomes the standard controlled/uncontrolled split: `value` (controlled) + `defaultValue` (uncontrolled initial) + `onValueChange` — same pattern as PasswordInput.
|
|
501
|
+
- **search-input**: `ref = $bindable(null)` becomes `forwardRef<HTMLInputElement>`; `class` becomes `className`.
|
|
502
|
+
- **select**: D-1 — `Portal` uses `createPortal` (renders into the target) instead of moving an already-rendered node, so the panel is absent from server HTML and React synthetic events still bubble through the React tree. Nil in practice: the panel is gated on an `open` that starts false, and no ancestor renders handlers over it.
|
|
503
|
+
- **select**: D-12 — `useElementRef` (convention C-1) costs one extra pre-paint render at mount for the trigger and for the panel.
|
|
504
|
+
- **select**: D-2 — `markSurfaceState` is not ported. `data-state` is an ordinary attribute carrying `presence.surfaceState` (`"open" | "closing"`, never `"opening"`, per C-5). Same emitted DOM as the source's imperative writes.
|
|
505
|
+
- **select**: D-6 — the dismiss layer's `active` is a plain boolean (`ctx.open`) where the source needed a getter. Semantics unchanged: the layer stays on the stack for its whole exit and stops being top of it the instant `open` flips.
|
|
506
|
+
- **select**: The `{#if open}` gate moves down one level: `Select` renders `<SelectPanel>` unconditionally and the mount gate is `presence.mounted` inside the panel, above which `Portal` is hoisted so its container is resolved before the commit that opens the surface. `open` still travels through the context exactly as in the source.
|
|
507
|
+
- **select**: `SelectPanel` is not exported from the folder's `index.ts` (matching the source barrel), and the context is exposed only internally as `SelectReactContext` / `useSelectContext` in `types.ts` — the source does not export `SELECT_KEY` from its `index.ts` either.
|
|
508
|
+
- **select**: `class` prop becomes `className` (PORTING.md API contract); `ref = $bindable(null)` on the trigger becomes `forwardRef<HTMLButtonElement>`, so `ref` is no longer a member of `SelectProps`.
|
|
509
|
+
- **select**: `value = $bindable("")` becomes the two-way prop pattern: an internal copy seeded from `value` and re-synced during render whenever the caller changes the prop. All three source call shapes (caller-owned value, `onValueChange`-only, plain value + callback) work off the one implementation, but there is no `bind:value` write-back — a caller that wants the value must read `onValueChange`.
|
|
510
|
+
- **sheet**: `bind:open` becomes controlled `open` + write-back via `onOpenChange` (internal copy re-synced in render, Drawer pattern)
|
|
511
|
+
- **sheet**: `bind:ref` becomes `forwardRef<HTMLDivElement>`
|
|
512
|
+
- **sheet**: `children`/`footer` snippets become ReactNode props
|
|
513
|
+
- **sheet**: `class` prop becomes `className`
|
|
514
|
+
- **sheet**: `data-state` is an ordinary reactive attribute carrying surfaceState's two values (contract D-2/C-5) instead of the source's static literal rewritten by markSurfaceState
|
|
515
|
+
- **sheet**: no portal-before-focus-trap ordering ceremony (contract D-10): createPortal commits before effects run
|
|
516
|
+
- **sheet**: scroll lock keyed on `presence.mounted` via useScrollLock instead of the action's outro-delayed destroy — same observable release timing
|
|
517
|
+
- **sheet**: React adds an `ariaLabel` prop (no Svelte counterpart yet) so a title-less panel can carry an accessible name; the Svelte side is tracked to mirror it.
|
|
518
|
+
- **skeleton**: Reveal fade is driven by usePresence with a duration-0 enter leg standing in for the Svelte exit-only transition — visually identical (overlay mounts at rest, fades 200ms JS_EASINGS.in, instant under reduced motion), but the overlay briefly carries the presence clock's inert handling during the fade, matching Svelte's native inert-while-outroing behaviour
|
|
519
|
+
- **skeleton**: style is a React CSSProperties object; the internal --ft-skeleton-phase custom property is merged into it (caller keys preserved, phase wins on collision) rather than written as a style: directive — same rendered style attribute
|
|
520
|
+
- **slider**: SliderHarness.tsx and SliderFieldHarness.tsx replace the .test.svelte harnesses (React components instead of Svelte rigs); not exported from index.ts, matching the Svelte originals' non-export.
|
|
521
|
+
- **slider**: value is not a true two-way bindable prop (React has no bind:); mirrors the Input.tsx pattern instead — value prop seeds internal state, resynced on prop identity change, corrected via onValueChange. Observable behavior is unchanged.
|
|
522
|
+
- **sources**: Snippet props become ReactNode: `SourceCard.icon` is `ReactNode`, `SourcesList.item` is `(source: SourceData, index: number) => ReactNode`, and `Sources.children` is React `children`.
|
|
523
|
+
- **sources**: `SOURCES_CONTEXT_KEY` is exported as a `React.Context<SourcesContext | undefined>` object (read with `useContext`), not a Svelte `Symbol` context key. Name kept per the barrel contract.
|
|
524
|
+
- **sources**: `SourcesContext.open` keeps its `{ current: boolean }` box shape from the Svelte getter contract, but it is a snapshot on a context value rebuilt when `open`/`sources`/`listId`/`onToggle` change — not a live getter.
|
|
525
|
+
- **sources**: `class` is `className` on all four parts, per the package-wide rule.
|
|
526
|
+
- **sources**: `open` is controlled/uncontrolled rather than Svelte's `bind:open`: passing `open` makes the component controlled, so a consumer who passes `open` without acting on `onToggle` gets a list that no longer toggles on click (the Svelte bindable prop still flips its local copy).
|
|
527
|
+
- **status-morph**: No two-way binding in React: Svelte's `state = $bindable("idle")` becomes a plain `state` prop plus a new `onStateChange?: (state) => void` callback that fires when StatusMorph itself writes back to "idle" via the resetAfter timer. Callers who want the auto-reset to actually change what they render must wire onStateChange into their own state, unlike the Svelte bind:state contract which mutates the caller's variable automatically.
|
|
528
|
+
- **status-morph**: The Svelte StatusMorphHarness.test.svelte is not a separate file in the port — its role is filled by an inline Harness function component defined at the top of StatusMorph.test.tsx (React has no equivalent of importing a `.test.svelte` rig from a `.test.ts` file), so the matrix's two listed test files collapse into one .test.tsx, as instructed.
|
|
529
|
+
- **status-morph**: `ref = $bindable(null)` on the Svelte side is a forwardRef in React per PORTING.md C-4; no other ref-related behavior differs.
|
|
530
|
+
- **sticky-scroll**: Exiting frames are marked `inert` by usePresence's default, matching Svelte's own outroing-block inert marking.
|
|
531
|
+
- **sticky-scroll**: The `{#key panelIndex}` crossfade is rebuilt on usePresence + preset("fade") (per internals-api.md §5.1 row 1); an exiting frame freezes the panel content from the render BEFORE the index changed (the counterpart of Svelte freezing the outgoing keyed block's DOM), so during the one render where the swap is detected the still-live frame briefly shows the new index's content — invisible in practice (same commit, pre-paint swap).
|
|
532
|
+
- **sticky-scroll**: `children` is omitted from the rest-prop attribute surface: the Svelte source renders no children snippet, and a React children spread onto the root div would render where Svelte rendered nothing.
|
|
533
|
+
- **sticky-scroll**: `item`/`panel` snippets become render-prop functions `(item, index, active) => ReactNode` / `(item, index) => ReactNode`, per PORTING.md snippet mapping.
|
|
534
|
+
- **sticky-scroll**: activeIndex is controlled-when-passed (tabs precedent for `$bindable`): omit it for uncontrolled use; when passed, the parent must echo `onChange` back for internal activations (IO/focus) to take effect — Svelte's unbound-prop local-override semantics have no React counterpart.
|
|
535
|
+
- **sticky-scroll**: A panel frame interrupted mid-entrance reverses from its current opacity over a proportionally shortened duration rather than snapping back to full and restarting the fade, because `usePresence` owns one bidirectional leg per node where the Svelte source used a split `in:`/`out:` pair.
|
|
536
|
+
- **sticky-scroll**: `StickyScroll`'s exported type is restored by assertion, because forwardRef erases a render function's type parameter and ref-as-prop is React-19-only while the peer range includes 18; the same idiom restores the type parameter on the memoised internal row.
|
|
537
|
+
- **streaming-text**: onComplete edge-detection runs in a useEffect (post-commit) rather than Svelte's untracked $effect body — observably equivalent (fires once on the true→false edge, never on mount), but React fires it after paint instead of synchronously during the reactive flush.
|
|
538
|
+
- **switch**: Switch: Svelte `bind:checked` becomes the standard controlled/uncontrolled split — uncontrolled by default with a new `defaultChecked` prop, controlled when `checked` is passed (pair with `onCheckedChange`).
|
|
539
|
+
- **tabs**: TabsTrigger: the `document.activeElement` sample is kept continuously by `handleFocus`/`handleBlur` (plus an activeElement read in the layout effect) because React has no pre-mutation phase equivalent to `$effect.pre`. Pre-existing in the port; unchanged by this fix.
|
|
540
|
+
- **tabs**: TabsTrigger: the focus reclaim waits for `focusedValue` to stop naming this trigger before acting, because React lands the unregister state update one render after the commit that disabled the button, where Svelte's cleanup has already completed by the time its effect body runs. Same observable behaviour; the flag is now consumed on the empty-registry answer too, so no reclaim can survive into a later re-enable.
|
|
541
|
+
- **tabs**: `TABS_KEY` is a `React.Context<TabsContext | undefined>` object (displayName "TabsContext") rather than the Svelte `unique symbol` context key — read it with `useContext(TABS_KEY)`. `TabsContext`'s `value`, `orientation`, `activation`, `variant` and `focusedValue` are plain readonly fields on an object the root rebuilds every render, not Svelte getters.
|
|
542
|
+
- **terminal-block**: No consumer-visible divergence: header snippet becomes ReactNode; ref becomes forwardRef per PORTING.md; autoscroll uses react/src/internals/use-autoscroll.js's useAutoscroll(node, options) hook (already implemented for this repo) instead of the Svelte `use:autoscroll` action, targeting the log div via useElementRef.
|
|
543
|
+
- **terminal-block**: TerminalBlockProps extends HTMLAttributes<HTMLDivElement> minus className and spreads ...rest onto the root div; the Svelte source declares a closed prop list and forwards nothing.
|
|
544
|
+
- **text-roll**: Mid-roll DOM order inside the aria-hidden cell layer: exiting cells are appended after the current cells instead of holding their original sibling position (explicit grid-column/grid-row placement makes the painted result identical; only DOM inspection during the roll window can tell)
|
|
545
|
+
- **text-roll**: On a length-changing update the generation bump lands in a post-commit effect (mirroring the source's after-DOM-update $effect), so one committed frame may briefly reuse a positionally-matching node before the full re-roll — same two-phase behavior as Svelte, but the intermediate frame is a real React commit
|
|
546
|
+
- **text-roll**: rollIn/rollOut return the package's local TransitionSpec (delay always present) instead of svelte/transition's TransitionConfig — visible only to direct importers of roll-transitions.ts, which neither package exports from its index
|
|
547
|
+
- **text-roll**: On a `direction="auto"` reversal both legs of the same roll travel the same way, because the port resolves the direction before the leg orchestrator runs; the reference starts the outro with the previous direction, so its two glyphs cross.
|
|
548
|
+
- **text-roll**: A grapheme whose key returns while its old cell is still rolling out eases back from wherever the exit leg had got to, because the shared transition sampler hands the in-flight run to the reversing leg as its counterpart; the reference replays the whole entrance from fully hidden.
|
|
549
|
+
- **textarea**: The Svelte source's autoResize `$effect` runs as `useIsomorphicLayoutEffect` keyed [autoResize, value, rows], so the height write lands before paint exactly as Svelte's pre-paint effect does.
|
|
550
|
+
- **textarea**: `bind:value` becomes the standard controlled/uncontrolled split: uncontrolled by default (`defaultValue` seeds it), controlled the moment a `value` prop is passed with `onValueChange`.
|
|
551
|
+
- **textarea**: `class` becomes `className` (house-wide rename).
|
|
552
|
+
- **thinking-indicator**: `class` prop becomes `className`.
|
|
553
|
+
- **thinking-indicator**: `done` snippet becomes a `done?: ReactNode` prop.
|
|
554
|
+
- **thinking-indicator**: `ref = $bindable(null)` becomes `forwardRef<HTMLDivElement>`.
|
|
555
|
+
- **thinking-indicator**: `useElapsed`'s server snapshot is a deterministic `0`, so a server-rendered ThinkingIndicator shows "0s"; Svelte's `createElapsed({ since })` seeds from the server's wall clock, which no hydration render can reproduce. The live duration arrives in the layout phase, before the first paint.
|
|
556
|
+
- **thread-list**: A Svelte consumer passing a non-bound initial `activeId` and expecting clicks to still move the highlight must instead omit the prop (uncontrolled) or update it from `onSelect` — there is no defaultActiveId, matching the Tabs precedent.
|
|
557
|
+
- **thread-list**: Timestamps read `useNow()`'s shared module clock instead of a per-instance `createNow` — one interval per page, none under SSR. Relative timestamps are blank in server-rendered HTML and fill in during hydration, before the first paint. Svelte's `createNow` seeds itself with `Date.now()`, so its server HTML carries real labels; React's client has no way to reproduce the server's timestamp, so `useNow()` returns a not-started sentinel until the clock is retained in the layout phase and `formatRelativeTime` renders that as an empty string rather than a wrong label.
|
|
558
|
+
- **thread-list**: `bind:activeId` becomes the standard controlled/uncontrolled split: `activeId` is controlled when passed (pair it with `onSelect` to move the highlight); omit it and the list owns its own selection, reporting every pick through `onSelect`.
|
|
559
|
+
- **time-picker**: Apart from the active-slot reconciliation recorded below, behaviourally unchanged elsewhere: reduced-motion fast path, the `anchored` transition, `data-side`/`data-align` and `transform-origin` — `data-align` stays the statically requested "start" while `data-side` is the resolved one, the same asymmetry the source ships.
|
|
560
|
+
- **time-picker**: D-1: the panel is rendered into `document.body` with `createPortal` instead of a node moved by `use:portal`. Same resulting DOM, but synthetic React events from the panel still bubble through the React tree (inert here — dismissal listens natively on `document`).
|
|
561
|
+
- **time-picker**: D-2: `data-state` on the panel is an ordinary React attribute; `markSurfaceState` and the `onintrostart`/`onoutrostart` handlers are not ported. Same DOM output ("open" then "closing").
|
|
562
|
+
- **time-picker**: Open-time scroll: `tick().then(() => scrollActiveIntoView(index))` becomes a parked pending-index ref paid out by an effect keyed on `[panelNode, open]` (the panel mounts a commit later under presence, and a reopen can reuse the same node).
|
|
563
|
+
- **time-picker**: The Svelte `{#if open}` around `<TimePickerPanel>` moves INSIDE the panel as a `usePresence` mount gate: `TimePicker` renders `<TimePickerPanel>` unconditionally so the portal target is resolved before the opening commit and the panel survives its own exit.
|
|
564
|
+
- **time-picker**: `TIME_PICKER_KEY` (a `unique symbol`) becomes `TimePickerReactContext` + `useTimePickerContext` in `types.ts`; like the Svelte barrel, `index.ts` does not export it.
|
|
565
|
+
- **time-picker**: `TimePickerPanel`'s `class`/`ref` props survive as `className` + `forwardRef`, but the component is not exported from `index.ts` (matching the Svelte barrel).
|
|
566
|
+
- **time-picker**: `class` prop is spelled `className` (PORTING.md API contract).
|
|
567
|
+
- **time-picker**: `ref = $bindable(null)` on the trigger becomes `forwardRef<HTMLButtonElement, TimePickerProps>`; the exposed element is still the `<button>`.
|
|
568
|
+
- **time-picker**: `value` (`$bindable(null)`) becomes a controlled `value` prop plus `onValueChange`; the component keeps an internal copy re-synced during render when the caller changes the prop, so controlled and uncontrolled use both work off one implementation — there is no two-way binding.
|
|
569
|
+
- **time-picker**: React re-resolves the highlighted slot onto the same TIME when `step`, `min` or `max` change the grid (and therefore scrolls an open panel); the Svelte source keeps the raw numeric index, which can leave `aria-activedescendant` citing a removed row.
|
|
570
|
+
- **time-picker**: TimePicker formats its trigger and slot labels with Intl.DateTimeFormat and the runtime's default locale when `locale` is omitted, so a server render and its hydration can produce different text; pass an explicit `locale` for SSR-stable output.
|
|
571
|
+
- **tool-timeline**: Svelte source has no rest-prop spread on the root div, so the React port matches it exactly (no ...rest) rather than adding one speculatively.
|
|
572
|
+
- **tool-timeline**: Svelte's `item` Snippet<[ToolTimelineItemData, number]> prop becomes a render-prop function `(item, index) => ReactNode` per PORTING.md snippet-to-ReactNode mapping.
|
|
573
|
+
- **tool-timeline**: Relative timestamps are blank in server-rendered HTML and fill in during hydration, before the first paint. Svelte's `createNow` seeds itself with `Date.now()`, so its server HTML carries real labels; React's client has no way to reproduce the server's timestamp, so `useNow()` returns a not-started sentinel until the clock is retained in the layout phase and `formatRelativeTime` renders that as an empty string rather than a wrong label.
|
|
574
|
+
- **tool-timeline**: The root `cn()` argument order differs from the Svelte class/class: emission order (compact class before className, where Svelte emits className then class:); class order affects neither specificity nor matching.
|
|
575
|
+
- **tooltip**: The bubble is rendered through the `Portal` component (createPortal) instead of the node-moving `use:portal` action — same resulting DOM under document.body (contract divergence D-1, inert here).
|
|
576
|
+
- **tooltip**: The dev-only focusable-trigger warning gates on `process.env.NODE_ENV !== "production"` instead of `import.meta.env.DEV` (same pattern as fluid-cursor/fireworks-hdr).
|
|
577
|
+
- **tooltip**: The in-only entrance is a bare `runTransition` in a layout effect (no `usePresence`): the source uses `in:anchored` with no outro, so close/unmount stays instant.
|
|
578
|
+
- **tooltip**: Trigger and bubble hover/focus listeners are attached natively via addEventListener (mirroring the source's imperative wiring and real pointerenter/pointerleave events) rather than React synthetic props — React's enter/leave plugin synthesises those from pointerover/out.
|
|
579
|
+
- **tooltip**: `class` prop becomes `className`; the bindable `ref` (trigger wrapper span) arrives via forwardRef per PORTING.md.
|
|
580
|
+
- **voice-input**: No `mounted` state: a React effect never runs on the server, and the canvas node arrives through `useElementRef`, which together give exactly the guarantee the Svelte flag existed for. Not consumer-visible.
|
|
581
|
+
- **voice-input**: No `untrack()` around the reduced-motion still frame and the ResizeObserver repaint — there is no reactivity graph to escape. The same guarantee (incoming `samples`/`demo` cannot restart the loop) comes from reading them through `useLiveRef` instead of effect dependencies. Effect deps are `[active, canvasEl, barHeight, color]`, matching the Svelte effect's tracked set exactly.
|
|
582
|
+
- **voice-input**: The `ref = $bindable(null)` prop is gone; the root `HTMLDivElement` arrives through `forwardRef` (PORTING.md / C-4).
|
|
583
|
+
- **voice-input**: `active` is no longer `bind:active`: it is the controlled/uncontrolled pair `active?: boolean` + `onActiveChange?: (active: boolean) => void` (added prop). The component keeps its own copy either way and re-syncs it in the render path when the prop changes, so every observable behaviour the Svelte tests assert is preserved — a supplied `active` opens/closes the panel, a button-driven change closes it even when `active` was passed and no callback is wired, and an externally driven change still fires no callback. Mirrors the Dialog/ApprovalCard convention already in the package.
|
|
584
|
+
- **voice-input**: `class` → `className` (PORTING.md).
|
|
585
|
+
- **voice-input**: `samples` is a prop in React, so a consumer bridging a 60 Hz audio pipeline re-renders the component and reconciles the panel subtree once per frame; the Svelte source reads `samples` inside the untracked rAF callback and re-renders nothing. The rAF loop itself is unaffected — `samples` is read through a live ref, so the canvas effect never restarts.
|
|
586
|
+
|
|
587
|
+
- **approval-card**: onApprove/onDeny receive the committed decision as an argument — React batches the onStateChange parent update, so the argument is the only synchronously-committed signal (Svelte writes through bind:state and needs none).
|
|
588
|
+
- **code-diff**: inert is written to the collapsed views imperatively via internals/dom/use-inert-attribute (React 18 drops the boolean JSX prop); absent from server HTML where Svelte SSRs it. A local DiffBody sub-component hosts the hook — markup unchanged.
|
|
589
|
+
- **compare**: new ariaLabel prop (default "Image comparison slider") and full keyboard operation (Arrow ±1, PageUp/PageDown ±10, Home/End) on the role=slider root; the Svelte source exposes a focusable slider with no name and no key handling.
|
|
590
|
+
- **compare**: The autoplay loop is started once: the Svelte source starts it twice (onMount plus the $effect tracking hover and drag), so two rAF loops run there and `onpercentagechange` fires twice per frame. The divider position is identical on both sides, but a consumer counting or debouncing that callback sees half the invocations here.
|
|
591
|
+
- **dock**: pointer tracked in viewport coordinates (clientX/clientY); the Svelte source reads pageX/pageY against getBoundingClientRect() and mis-magnifies on a scrolled page.
|
|
592
|
+
- **dock**: React adds an `ariaLabel` prop (rendered as `aria-label` on the toolbar) and emits `aria-orientation` matching `orientation`; the Svelte source has neither, so this is a temporary React-only addition until the Svelte side mirrors it.
|
|
593
|
+
- **dock**: While the pointer is inside the dock every animation frame produces a new context value, so the Dock root and every DockSeparator re-render and re-run their `cn()` calls where Svelte mutates two `{ current }` boxes and re-renders neither; visual output is identical.
|
|
594
|
+
- **dropdown-menu**: Tab/Shift+Tab return focus to the trigger before the browser continues traversal; the source passes returnFocus: false and leaves focus in a portalled panel, wrapping traversal to the body.
|
|
595
|
+
- **dropdown-menu**: Post-open focus is moved in a passive effect where the source moves it in a `tick()` microtask, so the panel paints one frame before the focus ring lands on the first or last item; the anchored entrance is still animating at that point.
|
|
596
|
+
- **file-upload**: The native file input is reset on picker-open (not on change) so `name`/`required` see a real FileList; `removeFile` clears it again when a removal invalidates it. A cancelled picker leaves the input empty while the row list keeps the earlier pick; dropped files never feed the native input, as in the Svelte source.
|
|
597
|
+
- **glow-border**: style custom properties are built as a React style object during render (present in server HTML); the Svelte source emits one raw CSS string — byte order differs, rendered result identical.
|
|
598
|
+
- **inline-citation**: a scheme-less host like docs.example.dev/guide is promoted to https:// before sanitizing, matching SourceCard and WebSearch; genuine relative paths pass through.
|
|
599
|
+
- **link**: The new-tab announcement and the safe-`rel` tokens are gated on the RESOLVED target, not on the bare `external` flag, so an `external` link whose `target` is overridden to `_self`/`_parent`/`_top` stays silent and keeps the caller's own `rel`; the Svelte source announces a new tab whenever `external` is set.
|
|
600
|
+
- **logo-cloud**: the four cloned marquee tracks carry aria-hidden and empty alt, so assistive tech hears the brand list once; the Svelte source announces all five copies.
|
|
601
|
+
- **matrix-rain**: column pitch is glyphSize / density where the Svelte source uses glyphSize * density; the source README documents "higher = more, narrower columns" and contradicts it in code — the port honors the documented contract.
|
|
602
|
+
- **reasoning-panel**: inert applied imperatively via use-inert-attribute (React 18 compatibility); absent from server HTML where Svelte SSRs it.
|
|
603
|
+
- **scroll-progress**: an element target is observed with ResizeObserver + MutationObserver; the source listens for a resize event elements never fire, so async content growth left the bar stale.
|
|
604
|
+
- **sources**: collapsed source lists get inert imperatively via use-inert-attribute (React 18 compatibility); absent from server HTML where Svelte SSRs it.
|
|
605
|
+
- **sources**: `SourcesList` applies `inert` to a collapsed list imperatively through internals/dom/use-inert-attribute rather than as a JSX attribute (React 18 drops `inert={true}`, React 19 rejects `inert=""`); it is absent from server HTML where Svelte SSRs it, and the transposed assertion checks `hasAttribute("inert")` instead of the Svelte test's `.inert` IDL property, which jsdom does not implement.
|
|
606
|
+
- **tooltip**: aria-describedby appends the tooltip id to the trigger's existing list and removes only its own id on close; the source overwrote and then deleted the whole attribute.
|
|
607
|
+
- **anchor-position**: The anchor-position core sizes the floating element from `offsetWidth`/`offsetHeight`, falling back to `getBoundingClientRect()` when those read zero; the Svelte core reads the rect unconditionally. React needs the layout box because the presence clock pins the entrance transform one commit before the position hook receives the node, and a painted measurement would place every anchored panel 8% of its own size off its anchor and leave it there.
|
|
608
|
+
- **anchor-position**: The anchor-position core clears the inline position it wrote when the handle is destroyed, so a `useAnchorPosition` surface with `enabled: false` returns to normal flow rather than staying pinned at its last computed coordinates; the Svelte action leaves the styles in place.
|
|
609
|
+
- **focus-trap**: The React focus trap treats a control under a `display: none` ancestor as non-focusable, where the Svelte trap checks the control's own computed style only — so initial focus and Tab cycling can select different elements in the two packages.
|
|
610
|
+
- **listbox**: `setActive` additionally rejects an index outside `0..count()-1`, so an out-of-range index is silently refused where the Svelte core commits it and leaves `aria-activedescendant` naming a row that does not exist.
|
|
611
|
+
- **useComposedRefs**: `useComposedRefs` never returns a ref cleanup. Detach happens on the `null` call, which is the one channel both React 18 and React 19 support; a returned function is a dev-console error on React 18.
|
|
612
|
+
- **useFloat**: `attachFloat().destroy()` strips `position`, `top`, `left`, `width`, `visibility` and `data-placement` from the node, where the Svelte `float` action leaves all of them in place.
|
|
613
|
+
- **useElapsed**: `useElapsed`'s server snapshot is a deterministic `0`; Svelte's `createElapsed({ since })` seeds from the server's wall clock, which no hydration render can reproduce. The live duration arrives in the layout phase, before the first paint.
|
|
614
|
+
- **canvas components**: MosaicGlow, MatrixRain, FlickeringGrid, Sparkles and LiquidText set up their canvas and paint the first frame in a passive effect, so the host can show one frame of the flat background before the artwork appears — including under `prefers-reduced-motion`, where that first paint is the only paint. Svelte's `onMount` runs before the browser paints. A package-wide phase choice, with no functional loss.
|
|
615
|
+
- **cameleon**: The retro-OS component kit that the Svelte package publishes on its own `cameleon/retro-kit` subpath (18 components, the accent vocabulary, and the `--r-*` token layer in `kit.css`) has no React equivalent and none is planned. `fancy-ui-react` declares the `./cameleon` subpath and nothing beneath it, and there is no `./cameleon/*` wildcard for reaching a single skin; `retroOsSkin` itself ships and skins the cameleon primitives normally.
|
|
616
|
+
- **cameleon**: `setSkinContext` is not exported. `<FancyProvider>` is the setter. For a subtree that must be skinned without the provider's wrapper `<div>`, the barrel exports `SkinReactContext` instead, per the `FooReactContext` naming rule. A caller taking that path supplies the token variables, `data-skin`, `.dark` and the webfont links itself, since those live on the element it is skipping.
|
|
617
|
+
- **registry**: The Svelte barrel's registry family (`registry`, `categories`, `categoryLabels`, `categoryDescriptions`, `getAllComponents`, `getComponent`, `getComponentsByStatus`, `getComponentsByCategory`, `getComponentsGroupedByCategory`, `getComponentsGroupedByStatus`, `searchComponents`, `getStats`, `hasComponent`, `getComponentCategory`) is docs-site tooling and is not ported; there is no `react/src/registry.ts`.
|
|
618
|
+
- **subpaths**: No per-component subpaths: import from the package root. The build preserves modules, so a bundler shakes out what you do not use; a wildcard would freeze `dist/`'s folder layout as public API.
|
|
619
|
+
- **cn**: `cn` (clsx + tailwind-merge) is a root export of `fancy-ui-react`; the Svelte package keeps it internal.
|
|
620
|
+
- **animated-testimonials**: The pending 300 ms navigation clamps to index 0 when the collection empties mid-flight, and the wrap reads the live length rather than the one captured when the button was pressed; the Svelte source computes `% 0` = NaN and stays broken once items come back.
|
|
621
|
+
- **animated-testimonials**: Autoplay pauses on keyboard focus inside the region as well as on pointer hover, and does not start at all under `prefers-reduced-motion` — temporarily ahead of the Svelte source, which mirrors it next.
|
|
622
|
+
- **button**: `onclick` is renamed `onClick` and typed with React's synthetic MouseEvent, matching the event-prop casing NavbarLink, Sidebar, ChatMessageAction, Toggle and ToggleGroupItem already use.
|
|
623
|
+
- **chat-panel**: ChatEmptyState's `icon` fallback uses `??`, so a nullish `icon` falls back to the default sparkle but a falsy-but-defined node such as `icon={false}` or `icon={""}` renders an empty decorative span where the Svelte `{#if icon}` branch still draws the sparkle; pass `undefined` to get the default mark.
|
|
624
|
+
- **container-text-flip**: ContainerTextFlipProps extends HTMLAttributes<HTMLParagraphElement> and spreads rest onto the root, so id/onClick/data-*/aria-* reach the element where the Svelte component drops them; the inherited `children` is type-accepted and dropped, since the component renders its own.
|
|
625
|
+
- **gradient-button**: GradientButton forwards a ref to the underlying `<button>` even though the Svelte source declares no bindable ref; additive only, recorded rather than removed.
|
|
626
|
+
- **letter-pullup**: LetterPullupProps extends HTMLAttributes<HTMLDivElement> and spreads rest onto the root div, so id/style/onClick/role/aria-*/data-* reach the element; the Svelte component's surface is exactly {words, delay, class} and it spreads nothing.
|
|
627
|
+
- **line-hover-link**: Props extend AnchorHTMLAttributes minus className and spread ...rest onto the `<a>`, per PORTING.md's rest-props-spread rule; the Svelte side exposed a fixed prop list and spread nothing.
|
|
628
|
+
- **marquee**: `ReviewCardProps` is exported as a named type from the folder barrel; the Svelte README states the prop shape is deliberately not re-exported, so a consumer writing their own card need not match it.
|
|
629
|
+
- **number-ticker**: Duration and delay are captured when the animation starts; the Svelte source re-reads both props each frame, so a mid-animation duration change re-times the count there and not here.
|
|
630
|
+
- **number-ticker**: The re-animate effect depends on the animation target only; the Svelte $effect also re-runs on displayValue and on delay, so a delay-only change restarts the count in Svelte and not in React.
|
|
631
|
+
- **pixel-loader**: PixelLoaderProps extends HTMLAttributes<HTMLDivElement> and spreads rest onto the root, so a consumer's `style` can override the component's own `--ft-pixel-*` custom properties; the Svelte component accepts exactly nine props and spreads nothing.
|
|
632
|
+
- **ripple-button**: Port-added `ref`: RippleButton is a forwardRef publishing the root `<button>`, which the Svelte source does not expose; the consumer's ref is composed through `useComposedRefs`, so it attaches once and is never churned by the ripple state.
|
|
633
|
+
- **toast**: The per-toast entrance and exit are owned by `<Toaster>`'s per-item presence clock rather than by `<Toast>` itself, so a `<Toast>` rendered directly outside a `<Toaster>` is static where the Svelte one still plays its 300 ms rise in and 200 ms sink out.
|
|
634
|
+
- **toast**: A dismissed toast is `inert` for the length of its exit (the presence clock's default), so its Retry and Dismiss buttons stop answering clicks and focus inside it is released; the Svelte toast root carries no `inert` and stays interactive until the outro destroys it.
|
|
635
|
+
- **tracing-beam**: Per-frame spring values are written imperatively to the gradient node in the rAF loop (setAttribute "y1"/"y2") instead of round-tripping through state, so the component and its children never re-render during the animation; the rendered JSX keeps y1/y2 at their 0 seed, which is also what the server markup emits.
|
|
636
|
+
- **tracing-beam**: The SVG gradient id is minted per instance with useFancyId("tracing-beam-gradient") and referenced as url(#id), where the source hardcodes the id; the React side therefore supports several beams on one page.
|
|
637
|
+
- **typing-indicator**: TypingIndicatorProps extends HTMLAttributes<HTMLDivElement> and spreads ...rest onto the root div, so a consumer can pass id/onClick/data-* or override role/aria-live/style; the Svelte component declares a fixed prop list and spreads nothing.
|
|
638
|
+
|
|
639
|
+
## Porting a component
|
|
640
|
+
|
|
641
|
+
Read `PORTING.md` first — folder shape, rune→hook mapping, the styling rules
|
|
642
|
+
that break silently, and the hard rules. The Svelte source under
|
|
643
|
+
`src/lib/fancy-ui/<slug>/` is always the reference.
|