motion-ui-skill 2.0.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 +22 -0
- package/README.md +637 -0
- package/SKILL.md +529 -0
- package/agents/openai.yaml +8 -0
- package/bin/index.mjs +242 -0
- package/bin/installer.mjs +457 -0
- package/bin/updater.mjs +207 -0
- package/catalog.json +8120 -0
- package/components/agents/agent-activity/activity-row.tsx +242 -0
- package/components/agents/agent-activity/index.tsx +287 -0
- package/components/agents/agent-activity/types.ts +106 -0
- package/components/agents/agent-code.tsx +171 -0
- package/components/agents/agent-disclosure.tsx +55 -0
- package/components/agents/ai-sidebar.tsx +981 -0
- package/components/agents/approval-card/index.tsx +467 -0
- package/components/agents/approval-card/types.ts +56 -0
- package/components/agents/chat-app.tsx +97 -0
- package/components/agents/citations.tsx +288 -0
- package/components/agents/code-block.tsx +202 -0
- package/components/agents/file-diff.tsx +288 -0
- package/components/agents/image-generation.tsx +388 -0
- package/components/agents/loading-states/agent-progress.tsx +105 -0
- package/components/agents/loading-states/index.ts +13 -0
- package/components/agents/loading-states/reasoning-text.tsx +224 -0
- package/components/agents/loading-states/thinking-shimmer.tsx +27 -0
- package/components/agents/message-bubble.tsx +369 -0
- package/components/agents/message-context.tsx +9 -0
- package/components/agents/message-scroller.tsx +487 -0
- package/components/agents/message.tsx +272 -0
- package/components/agents/prompt-input.tsx +327 -0
- package/components/agents/streaming-response.tsx +263 -0
- package/components/agents/todo-list.tsx +387 -0
- package/components/agents/tool-approval.tsx +276 -0
- package/components/agents/tool-result.tsx +352 -0
- package/components/app/icons.tsx +19 -0
- package/components/audio/music-player-card.tsx +146 -0
- package/components/audio/music-playlist-card.tsx +172 -0
- package/components/audio/now-playing-bar.tsx +116 -0
- package/components/background-gradient/arc-bands-background.tsx +54 -0
- package/components/background-gradient/aurora-background.tsx +49 -0
- package/components/background-gradient/cherry-petal-background.tsx +50 -0
- package/components/background-gradient/coral-glow-background.tsx +47 -0
- package/components/background-gradient/dark-arc-bands-background.tsx +52 -0
- package/components/background-gradient/dark-aurora-background.tsx +52 -0
- package/components/background-gradient/dark-carbon-spotlight-background.tsx +47 -0
- package/components/background-gradient/dark-ember-background.tsx +47 -0
- package/components/background-gradient/dark-ink-field-background.tsx +46 -0
- package/components/background-gradient/dark-midnight-mesh-background.tsx +61 -0
- package/components/background-gradient/dark-rose-noir-background.tsx +52 -0
- package/components/background-gradient/dark-teal-depth-background.tsx +52 -0
- package/components/background-gradient/frost-mesh-background.tsx +56 -0
- package/components/background-gradient/halftone-pop-background.tsx +52 -0
- package/components/background-gradient/honey-ember-background.tsx +47 -0
- package/components/background-gradient/ink-wash-background.tsx +49 -0
- package/components/background-gradient/linen-weave-background.tsx +47 -0
- package/components/background-gradient/mint-lagoon-background.tsx +47 -0
- package/components/background-gradient/paper-fold-background.tsx +52 -0
- package/components/background-gradient/rain-prism-background.tsx +52 -0
- package/components/background-gradient/sand-drift-background.tsx +47 -0
- package/components/background-gradient/soft-spotlight-background.tsx +47 -0
- package/components/background-gradient/sunrise-horizon-background.tsx +51 -0
- package/components/background-gradient/sunset-bloom-background.tsx +47 -0
- package/components/background-gradient/terrazzo-fragment-background.tsx +53 -0
- package/components/background-gradient/tropical-tide-background.tsx +47 -0
- package/components/background-pattern/diagonal-box-pattern.tsx +29 -0
- package/components/background-pattern/dot-grid-pattern.tsx +29 -0
- package/components/background-pattern/fine-grain-pattern.tsx +39 -0
- package/components/background-pattern/graph-paper-pattern.tsx +29 -0
- package/components/background-pattern/line-grid-pattern.tsx +39 -0
- package/components/background-pattern/reverse-diagonal-box-pattern.tsx +30 -0
- package/components/buttons/add-to-cart-button.tsx +190 -0
- package/components/buttons/bookmark-save-button.tsx +105 -0
- package/components/buttons/cinder-latch-button.tsx +80 -0
- package/components/buttons/copy-button.tsx +155 -0
- package/components/buttons/depth-outline-button.tsx +72 -0
- package/components/buttons/dimple-switch.tsx +114 -0
- package/components/buttons/download-button.tsx +186 -0
- package/components/buttons/follow-button.tsx +98 -0
- package/components/buttons/hold-to-delete-button.tsx +205 -0
- package/components/buttons/inset-button.tsx +82 -0
- package/components/buttons/like-button.tsx +135 -0
- package/components/buttons/linen-tab-button.tsx +92 -0
- package/components/buttons/prism-depth-button.tsx +90 -0
- package/components/buttons/quantity-stepper-button.tsx +104 -0
- package/components/buttons/segmented-toggle-button.tsx +134 -0
- package/components/buttons/sheen-pill-button.tsx +127 -0
- package/components/buttons/slate-chip-switch.tsx +94 -0
- package/components/buttons/slide-to-confirm-button.tsx +163 -0
- package/components/buttons/soft-pill-button.tsx +86 -0
- package/components/buttons/soft-ui-button.tsx +59 -0
- package/components/buttons/three-d-button.tsx +99 -0
- package/components/buttons/three-d-icon-button.tsx +88 -0
- package/components/calendar/booking-slot-calendar.tsx +315 -0
- package/components/calendar/date-range-picker-card.tsx +216 -0
- package/components/calendar/event-countdown-card.tsx +105 -0
- package/components/calendar/month-picker-calendar.tsx +183 -0
- package/components/calendar/week-strip-calendar.tsx +182 -0
- package/components/contact/copy-email.tsx +94 -0
- package/components/docks/Icons.tsx +222 -0
- package/components/docks/app-dock.tsx +111 -0
- package/components/docks/editor-tool-dock.tsx +113 -0
- package/components/docks/mac-dock.tsx +144 -0
- package/components/docks/presence-dock.tsx +178 -0
- package/components/docks/spotlight-bar.tsx +188 -0
- package/components/dropdowns/file-menu-dropdown.tsx +192 -0
- package/components/dropdowns/filter-sort-dropdown.tsx +189 -0
- package/components/dropdowns/kebab-actions-dropdown.tsx +195 -0
- package/components/dropdowns/notification-dropdown.tsx +235 -0
- package/components/dropdowns/share-menu-dropdown.tsx +197 -0
- package/components/dropdowns/user-menu-dropdown.tsx +251 -0
- package/components/dropdowns/workspace-switcher-dropdown.tsx +248 -0
- package/components/event/event-ticket-card.tsx +116 -0
- package/components/files/ink-stamp-document-card.tsx +88 -0
- package/components/files/stacked-folder-card.tsx +176 -0
- package/components/folder/folder-tab-card.tsx +123 -0
- package/components/forms/contact-form.tsx +417 -0
- package/components/forms/forgot-password-form.tsx +264 -0
- package/components/forms/login-form.tsx +342 -0
- package/components/forms/newsletter-form.tsx +212 -0
- package/components/forms/signup-form.tsx +487 -0
- package/components/frames/circle-cut-frame.tsx +198 -0
- package/components/frames/hard-shadow-polaroid-frame.tsx +158 -0
- package/components/frames/sticky-note-polaroid-frame.tsx +230 -0
- package/components/frames/transform-box-frame.tsx +287 -0
- package/components/frames/transform-plus-frame.tsx +308 -0
- package/components/gallery/film-strip-card.tsx +103 -0
- package/components/gallery/gallery-grid-card.tsx +106 -0
- package/components/gallery/gallery-wall-card.tsx +71 -0
- package/components/gallery/glass-overlay-image-card.tsx +156 -0
- package/components/gallery/museum-placard-card.tsx +105 -0
- package/components/gallery/photo-album-card.tsx +114 -0
- package/components/gallery/photo-contact-sheet-card.tsx +71 -0
- package/components/gallery/polaroid-image-card.tsx +81 -0
- package/components/gallery/slow-living-polaroid-card.tsx +88 -0
- package/components/gallery/stamp-postcard-card.tsx +78 -0
- package/components/inputs/checkbox-field-input.tsx +148 -0
- package/components/inputs/combobox-field-input.tsx +466 -0
- package/components/inputs/date-field-input.tsx +472 -0
- package/components/inputs/file-upload-field-input.tsx +578 -0
- package/components/inputs/floating-label-field-input.tsx +206 -0
- package/components/inputs/input-group-field.tsx +132 -0
- package/components/inputs/password-field-input.tsx +125 -0
- package/components/inputs/phone-field-input.tsx +157 -0
- package/components/inputs/radio-group-field-input.tsx +220 -0
- package/components/inputs/search-input.tsx +163 -0
- package/components/inputs/select-field-input.tsx +416 -0
- package/components/inputs/switch-field-input.tsx +179 -0
- package/components/inputs/text-field-input.tsx +89 -0
- package/components/inputs/textarea-field-input.tsx +152 -0
- package/components/loaders/apple-hello-loader.tsx +86 -0
- package/components/loaders/spin-loader.tsx +51 -0
- package/components/loaders/text-loader.tsx +148 -0
- package/components/mockups/apple-ipod-mockup-card.tsx +155 -0
- package/components/mockups/apple-watch-mockup-card.tsx +278 -0
- package/components/mockups/browser-mockup-card.tsx +109 -0
- package/components/mockups/laptop-mockup-card.tsx +118 -0
- package/components/mockups/phone-mockup-card.tsx +210 -0
- package/components/mockups/tablet-mockup-card.tsx +212 -0
- package/components/motion/action-sheet.tsx +218 -0
- package/components/motion/action-swap-roll.tsx +32 -0
- package/components/motion/action-swap.tsx +340 -0
- package/components/motion/adaptive-stepper.tsx +442 -0
- package/components/motion/animated-badge.tsx +213 -0
- package/components/motion/animated-number.tsx +50 -0
- package/components/motion/animated-sidebar.tsx +1174 -0
- package/components/motion/animated-toast-stack.tsx +503 -0
- package/components/motion/aspect-ratio.tsx +55 -0
- package/components/motion/attachment-upload.tsx +1080 -0
- package/components/motion/audio-player.tsx +266 -0
- package/components/motion/autocomplete.tsx +183 -0
- package/components/motion/availability-scheduler/copy-menu.tsx +119 -0
- package/components/motion/availability-scheduler/day-row.tsx +231 -0
- package/components/motion/availability-scheduler/icon-button.tsx +46 -0
- package/components/motion/availability-scheduler/index.tsx +154 -0
- package/components/motion/availability-scheduler/time-select.tsx +49 -0
- package/components/motion/availability-scheduler/types.ts +189 -0
- package/components/motion/avatar-group.tsx +154 -0
- package/components/motion/bloom-menu.tsx +216 -0
- package/components/motion/bottom-sheet.tsx +249 -0
- package/components/motion/bounce-sidebar.tsx +266 -0
- package/components/motion/bouncy-accordion.tsx +325 -0
- package/components/motion/breadcrumb.tsx +122 -0
- package/components/motion/button/base.tsx +189 -0
- package/components/motion/button/index.tsx +13 -0
- package/components/motion/button/magnetic.tsx +25 -0
- package/components/motion/button/metallic.tsx +100 -0
- package/components/motion/button/stateful.tsx +237 -0
- package/components/motion/card-folder.tsx +345 -0
- package/components/motion/card-resize.tsx +229 -0
- package/components/motion/cascader.tsx +279 -0
- package/components/motion/center-morph-modal.tsx +366 -0
- package/components/motion/checkbox.tsx +123 -0
- package/components/motion/chip.tsx +121 -0
- package/components/motion/chromatic-text-reveal.tsx +203 -0
- package/components/motion/collapsible.tsx +108 -0
- package/components/motion/color-picker.tsx +206 -0
- package/components/motion/combobox/content.tsx +163 -0
- package/components/motion/combobox/context.tsx +359 -0
- package/components/motion/combobox/list.tsx +222 -0
- package/components/motion/combobox/trigger.tsx +191 -0
- package/components/motion/combobox/use-active-option.ts +130 -0
- package/components/motion/combobox.tsx +33 -0
- package/components/motion/command-palette.tsx +381 -0
- package/components/motion/confetti.tsx +128 -0
- package/components/motion/context-menu.tsx +790 -0
- package/components/motion/copy-button.tsx +103 -0
- package/components/motion/cylinder-carousel.tsx +459 -0
- package/components/motion/date-range-picker.tsx +218 -0
- package/components/motion/digit-swap.tsx +125 -0
- package/components/motion/dock.tsx +113 -0
- package/components/motion/drawer.tsx +108 -0
- package/components/motion/dynamic-island.tsx +221 -0
- package/components/motion/error-shake.tsx +66 -0
- package/components/motion/event-calendar.tsx +224 -0
- package/components/motion/expandable-action-bar.tsx +412 -0
- package/components/motion/expandable-control.tsx +254 -0
- package/components/motion/expandable-tabs.tsx +444 -0
- package/components/motion/expanding-arrow-button.tsx +171 -0
- package/components/motion/feedback-widget.tsx +473 -0
- package/components/motion/file-tree.tsx +429 -0
- package/components/motion/file-upload.tsx +606 -0
- package/components/motion/filter-builder.tsx +283 -0
- package/components/motion/frame.tsx +116 -0
- package/components/motion/gantt.tsx +156 -0
- package/components/motion/glow-button.tsx +101 -0
- package/components/motion/haptic-pressable.tsx +107 -0
- package/components/motion/hold-action-button.tsx +279 -0
- package/components/motion/hover-card.tsx +118 -0
- package/components/motion/icon-stack.tsx +138 -0
- package/components/motion/infinite-masonry.tsx +349 -0
- package/components/motion/input.tsx +242 -0
- package/components/motion/kanban.tsx +255 -0
- package/components/motion/kbd.tsx +127 -0
- package/components/motion/knockout-bracket.tsx +909 -0
- package/components/motion/knockout-wheel.tsx +1112 -0
- package/components/motion/liquid.tsx +351 -0
- package/components/motion/loader.tsx +616 -0
- package/components/motion/magnet-dock.tsx +117 -0
- package/components/motion/magnetic.tsx +50 -0
- package/components/motion/marquee.tsx +66 -0
- package/components/motion/metric-card.tsx +116 -0
- package/components/motion/morphing-modal.tsx +160 -0
- package/components/motion/morphing-search.tsx +643 -0
- package/components/motion/morphing-tabs.tsx +940 -0
- package/components/motion/multi-select/content.tsx +164 -0
- package/components/motion/multi-select/context.tsx +381 -0
- package/components/motion/multi-select/index.tsx +33 -0
- package/components/motion/multi-select/list.tsx +239 -0
- package/components/motion/multi-select/trigger.tsx +262 -0
- package/components/motion/not-found/glitch.tsx +107 -0
- package/components/motion/not-found/index.tsx +11 -0
- package/components/motion/not-found/magnetic.tsx +57 -0
- package/components/motion/not-found/shared.tsx +96 -0
- package/components/motion/not-found/spotlight.tsx +86 -0
- package/components/motion/not-found/stacked.tsx +77 -0
- package/components/motion/not-found/terminal.tsx +83 -0
- package/components/motion/notification-stack.tsx +380 -0
- package/components/motion/number-field.tsx +178 -0
- package/components/motion/number-ticker.tsx +185 -0
- package/components/motion/otp-input.tsx +392 -0
- package/components/motion/overflow-actions.tsx +375 -0
- package/components/motion/page-transition.tsx +92 -0
- package/components/motion/pagination.tsx +163 -0
- package/components/motion/parallax.tsx +64 -0
- package/components/motion/password-input.tsx +165 -0
- package/components/motion/phone-input.tsx +181 -0
- package/components/motion/popover-morph.tsx +317 -0
- package/components/motion/popover-position.ts +86 -0
- package/components/motion/popover.tsx +694 -0
- package/components/motion/prediction-market.tsx +682 -0
- package/components/motion/preview-rail.tsx +390 -0
- package/components/motion/progress-ring.tsx +115 -0
- package/components/motion/project-folder.tsx +418 -0
- package/components/motion/pull-to-refresh.tsx +522 -0
- package/components/motion/radio.tsx +148 -0
- package/components/motion/range-slider.tsx +93 -0
- package/components/motion/rating.tsx +171 -0
- package/components/motion/reorder-grid.tsx +123 -0
- package/components/motion/resizable-panel.tsx +160 -0
- package/components/motion/scroll-progress.tsx +127 -0
- package/components/motion/scroll-reveal.tsx +60 -0
- package/components/motion/scroll-to.tsx +48 -0
- package/components/motion/segmented-control.tsx +130 -0
- package/components/motion/segmented-progress.tsx +128 -0
- package/components/motion/select.tsx +440 -0
- package/components/motion/shader-background.tsx +134 -0
- package/components/motion/shared-layout-bg.tsx +151 -0
- package/components/motion/signup-form.tsx +467 -0
- package/components/motion/slide-action-button.tsx +203 -0
- package/components/motion/smooth-scroll.tsx +264 -0
- package/components/motion/sortable-list.tsx +98 -0
- package/components/motion/speed-dial.tsx +144 -0
- package/components/motion/split-text.tsx +115 -0
- package/components/motion/spotlight-card.tsx +89 -0
- package/components/motion/stepper.tsx +127 -0
- package/components/motion/success-check.tsx +142 -0
- package/components/motion/swap/constants.ts +2 -0
- package/components/motion/swap/controls.tsx +201 -0
- package/components/motion/swap/data.ts +186 -0
- package/components/motion/swap/field.tsx +115 -0
- package/components/motion/swap/quote-row.tsx +46 -0
- package/components/motion/swap/token-badges.tsx +83 -0
- package/components/motion/swap/token-picker.tsx +219 -0
- package/components/motion/swap/types.ts +20 -0
- package/components/motion/swap/utils.ts +28 -0
- package/components/motion/swap.tsx +182 -0
- package/components/motion/swipeable-list.tsx +507 -0
- package/components/motion/switch.tsx +96 -0
- package/components/motion/table/editable-cell.tsx +22 -0
- package/components/motion/table/index.tsx +431 -0
- package/components/motion/table/row-handle.tsx +81 -0
- package/components/motion/table/skeleton-rows.tsx +39 -0
- package/components/motion/table/table-header.tsx +344 -0
- package/components/motion/table/table-menu.tsx +129 -0
- package/components/motion/table/types.ts +86 -0
- package/components/motion/table/use-column-reorder.ts +105 -0
- package/components/motion/table/use-column-resize.ts +81 -0
- package/components/motion/table/use-column-sort.ts +64 -0
- package/components/motion/table/use-row-selection.ts +59 -0
- package/components/motion/table/utils.ts +33 -0
- package/components/motion/tabs.tsx +207 -0
- package/components/motion/text-cascade.tsx +22 -0
- package/components/motion/text-reveal.tsx +143 -0
- package/components/motion/text-scramble.tsx +84 -0
- package/components/motion/text-shimmer.tsx +34 -0
- package/components/motion/text-swap.tsx +56 -0
- package/components/motion/theme-toggle.tsx +210 -0
- package/components/motion/tilt-card.tsx +68 -0
- package/components/motion/timeline.tsx +236 -0
- package/components/motion/toggle-group.tsx +128 -0
- package/components/motion/tooltip.tsx +297 -0
- package/components/motion/tree-view.tsx +200 -0
- package/components/motion/wallet-card/account-avatar.tsx +21 -0
- package/components/motion/wallet-card/account-switcher.tsx +199 -0
- package/components/motion/wallet-card/actions.tsx +59 -0
- package/components/motion/wallet-card/balance-delta.tsx +69 -0
- package/components/motion/wallet-card/constants.ts +18 -0
- package/components/motion/wallet-card/copy-button.tsx +58 -0
- package/components/motion/wallet-card/index.tsx +151 -0
- package/components/motion/wallet-card/search-bar.tsx +198 -0
- package/components/motion/wallet-card/types.ts +34 -0
- package/components/motion/wallet-card/utils.ts +9 -0
- package/components/motion/wheel-picker.tsx +610 -0
- package/components/notifications/apple-notification-banner.tsx +155 -0
- package/components/notifications/calendar-reminder-notification-banner.tsx +138 -0
- package/components/notifications/chat-bubble-notification-banner.tsx +136 -0
- package/components/notifications/delivery-notification-banner.tsx +126 -0
- package/components/notifications/deploy-notification-banner.tsx +140 -0
- package/components/notifications/email-notification-banner.tsx +148 -0
- package/components/notifications/incoming-call-notification-banner.tsx +144 -0
- package/components/notifications/payment-notification-banner.tsx +137 -0
- package/components/notifications/system-alert-banner.tsx +137 -0
- package/components/notifications/toast-notification-banner.tsx +130 -0
- package/components/others/progress-ring-card.tsx +217 -0
- package/components/others/stacked-cards-effect.tsx +62 -0
- package/components/others/terminal-log-card.tsx +107 -0
- package/components/others/thermal-receipt-card.tsx +132 -0
- package/components/others/weather-snapshot-card.tsx +124 -0
- package/components/otp/otp-boxed-input.tsx +482 -0
- package/components/otp/otp-underline-input.tsx +356 -0
- package/components/previews/agents/agent-activity.preview.tsx +136 -0
- package/components/previews/agents/ai-sidebar.preview.tsx +236 -0
- package/components/previews/agents/chat-app-usage.tsx +689 -0
- package/components/previews/agents/chat-app.preview.tsx +130 -0
- package/components/previews/agents/chat-preview.tsx +285 -0
- package/components/previews/agents/citations.preview.tsx +78 -0
- package/components/previews/agents/code-block.preview.tsx +67 -0
- package/components/previews/agents/file-diff.preview.tsx +64 -0
- package/components/previews/agents/image-generation.preview.tsx +117 -0
- package/components/previews/agents/message-bubble.preview.tsx +12 -0
- package/components/previews/agents/message-scroller.preview.tsx +70 -0
- package/components/previews/agents/message.preview.tsx +14 -0
- package/components/previews/agents/prompt-input.preview.tsx +145 -0
- package/components/previews/agents/streaming-response.preview.tsx +156 -0
- package/components/previews/agents/todo-list.preview.tsx +73 -0
- package/components/previews/agents/tool-approval.preview.tsx +80 -0
- package/components/previews/agents/use-tool-result-demo.ts +28 -0
- package/components/previews/blocks/availability-scheduler.preview.tsx +11 -0
- package/components/previews/blocks/bloom-menu.preview.tsx +11 -0
- package/components/previews/blocks/card-folder.preview.tsx +105 -0
- package/components/previews/blocks/command-palette.preview.tsx +40 -0
- package/components/previews/blocks/dynamic-island.preview.tsx +150 -0
- package/components/previews/blocks/expandable-action-bar.preview.tsx +136 -0
- package/components/previews/blocks/expandable-tabs.preview.tsx +136 -0
- package/components/previews/blocks/feedback-widget.preview.tsx +34 -0
- package/components/previews/blocks/file-upload.preview.tsx +175 -0
- package/components/previews/blocks/infinite-masonry.preview.tsx +145 -0
- package/components/previews/blocks/knockout-bracket.preview.tsx +43 -0
- package/components/previews/blocks/morphing-search.preview.tsx +59 -0
- package/components/previews/blocks/morphing-tabs.preview.tsx +91 -0
- package/components/previews/blocks/notification-stack.preview.tsx +39 -0
- package/components/previews/blocks/otp-input.preview.tsx +29 -0
- package/components/previews/blocks/overflow-actions.preview.tsx +51 -0
- package/components/previews/blocks/prediction-market.preview.tsx +41 -0
- package/components/previews/blocks/project-folder.preview.tsx +41 -0
- package/components/previews/blocks/signup-form.preview.tsx +36 -0
- package/components/previews/blocks/swap.preview.tsx +11 -0
- package/components/previews/blocks/swipeable-list.preview.tsx +149 -0
- package/components/previews/blocks/wallet-card.preview.tsx +36 -0
- package/components/previews/motion/action-swap.preview.tsx +82 -0
- package/components/previews/motion/adaptive-stepper.preview.tsx +20 -0
- package/components/previews/motion/animated-badge.preview.tsx +43 -0
- package/components/previews/motion/animated-sidebar.preview.tsx +269 -0
- package/components/previews/motion/animated-toast-stack.preview.tsx +151 -0
- package/components/previews/motion/bottom-sheet.preview.tsx +35 -0
- package/components/previews/motion/bounce-sidebar.preview.tsx +30 -0
- package/components/previews/motion/bouncy-accordion.preview.tsx +66 -0
- package/components/previews/motion/center-morph-modal.preview.tsx +75 -0
- package/components/previews/motion/checkbox.preview.tsx +26 -0
- package/components/previews/motion/combobox.preview.tsx +119 -0
- package/components/previews/motion/context-menu.preview.tsx +144 -0
- package/components/previews/motion/cylinder-carousel.preview.tsx +96 -0
- package/components/previews/motion/dock.preview.tsx +46 -0
- package/components/previews/motion/drawer.preview.tsx +46 -0
- package/components/previews/motion/expandable-control.preview.tsx +27 -0
- package/components/previews/motion/expanding-arrow-button.preview.tsx +11 -0
- package/components/previews/motion/file-tree.preview.tsx +67 -0
- package/components/previews/motion/input.preview.tsx +55 -0
- package/components/previews/motion/loader.preview.tsx +36 -0
- package/components/previews/motion/marquee.preview.tsx +22 -0
- package/components/previews/motion/morphing-modal.preview.tsx +184 -0
- package/components/previews/motion/multi-select.preview.tsx +73 -0
- package/components/previews/motion/number.preview.tsx +61 -0
- package/components/previews/motion/popover.preview.tsx +53 -0
- package/components/previews/motion/preview-rail.preview.tsx +108 -0
- package/components/previews/motion/pull-to-refresh.preview.tsx +117 -0
- package/components/previews/motion/radio.preview.tsx +17 -0
- package/components/previews/motion/range-slider.preview.tsx +19 -0
- package/components/previews/motion/select.preview.tsx +29 -0
- package/components/previews/motion/shader-background.preview.tsx +308 -0
- package/components/previews/motion/shared-layout-bg.preview.tsx +33 -0
- package/components/previews/motion/switch.preview.tsx +15 -0
- package/components/previews/motion/table.preview.tsx +140 -0
- package/components/previews/motion/tabs.preview.tsx +49 -0
- package/components/previews/motion/text-animation.preview.tsx +63 -0
- package/components/previews/motion/theme-toggle.preview.tsx +28 -0
- package/components/previews/motion/tilt-card.preview.tsx +15 -0
- package/components/previews/motion/tooltip.preview.tsx +34 -0
- package/components/previews/motion/wheel-picker.preview.tsx +91 -0
- package/components/pricing/retail-price-tag-card.tsx +104 -0
- package/components/pricing/toggle-pricing-cards.tsx +209 -0
- package/components/profile/contact-profile-card.tsx +100 -0
- package/components/profile/editorial-staff-profile-card.tsx +79 -0
- package/components/profile/team-member-profile-grid.tsx +159 -0
- package/components/profile/user-profile-card.tsx +125 -0
- package/components/resources/resource-links-panel.tsx +176 -0
- package/components/socials/discord-chat-card.tsx +157 -0
- package/components/socials/facebook-post-card.tsx +198 -0
- package/components/socials/github-contribution.tsx +716 -0
- package/components/socials/github-repo-card.tsx +111 -0
- package/components/socials/instagram-post-card.tsx +204 -0
- package/components/socials/linked-in-post-card.tsx +213 -0
- package/components/socials/linked-in-profile-card.tsx +173 -0
- package/components/socials/threads-post-card.tsx +162 -0
- package/components/socials/twitter-post-card.tsx +184 -0
- package/components/socials/twitter-profile-card.tsx +180 -0
- package/components/system/loaders/index.ts +1 -0
- package/components/system/loaders/page-loader-overlay.tsx +16 -0
- package/components/table/customers-table.tsx +146 -0
- package/components/table/orders-table.tsx +195 -0
- package/components/table/recent-transactions-table.tsx +125 -0
- package/components/table/tasks-table.tsx +163 -0
- package/components/table/team-members-table.tsx +155 -0
- package/components/table/users-select-table.tsx +184 -0
- package/components/text/cafe-menu-board-card.tsx +101 -0
- package/components/text/cinema-ticket-card.tsx +99 -0
- package/components/text/daily-motivation-card.tsx +80 -0
- package/components/text/denim-product-editorial-card.tsx +101 -0
- package/components/text/drop-cap-editorial-card.tsx +54 -0
- package/components/text/editorial-quote-card.tsx +98 -0
- package/components/text/journal-writing-card.tsx +131 -0
- package/components/text/keyboard-shortcuts-card.tsx +92 -0
- package/components/text/magazine-cover-card.tsx +109 -0
- package/components/text/notepad-card.tsx +95 -0
- package/components/travel/flight-boarding-card.tsx +177 -0
- package/components/travel/travel-postcard-card.tsx +96 -0
- package/components/underlines/annotated-text-showcase.tsx +37 -0
- package/components/underlines/annotated-text.tsx +471 -0
- package/components/users/credit-card-glass.tsx +113 -0
- package/components/users/team-member-card.tsx +50 -0
- package/components/users/testimonial-card.tsx +239 -0
- package/components/wallet/wallet-pass-card.tsx +220 -0
- package/components/widgets/analog-clock-widget.tsx +203 -0
- package/components/widgets/audio-recorder-widget.tsx +87 -0
- package/components/widgets/battery-face-widget.tsx +152 -0
- package/components/widgets/blob-profile.tsx +64 -0
- package/components/widgets/bluetooth-face-widget.tsx +125 -0
- package/components/widgets/compass-widget.tsx +296 -0
- package/components/widgets/daily-activity-calendar-widget.tsx +133 -0
- package/components/widgets/dnd-face-widget.tsx +129 -0
- package/components/widgets/electric-scooter-widget.tsx +88 -0
- package/components/widgets/flight-arrival-widget.tsx +76 -0
- package/components/widgets/focus-breath-widget.tsx +71 -0
- package/components/widgets/heart-rate-widget.tsx +93 -0
- package/components/widgets/hydration-widget.tsx +109 -0
- package/components/widgets/ios-calendar-widget.tsx +87 -0
- package/components/widgets/ios-digital-clock-widget.tsx +192 -0
- package/components/widgets/ios-earbuds-widget.tsx +120 -0
- package/components/widgets/ios-map-location-widget.tsx +133 -0
- package/components/widgets/minimal-agenda-widget.tsx +123 -0
- package/components/widgets/pomodoro-widget.tsx +155 -0
- package/components/widgets/recorder-face-widget.tsx +146 -0
- package/components/widgets/ride-pickup-widget.tsx +72 -0
- package/components/widgets/sleep-score-widget.tsx +107 -0
- package/components/widgets/step-count-widget.tsx +53 -0
- package/components/widgets/stopwatch-widget.tsx +176 -0
- package/components/widgets/torch-face-widget.tsx +128 -0
- package/components/widgets/voice-assistant-widget.tsx +103 -0
- package/components/widgets/wifi-toggle-widget.tsx +108 -0
- package/lib/cn.ts +1 -0
- package/lib/ease.ts +108 -0
- package/lib/favicon.ts +8 -0
- package/lib/hooks/use-dismiss.ts +120 -0
- package/lib/hooks/use-favicon.ts +39 -0
- package/lib/hooks/use-haptic.ts +44 -0
- package/lib/hooks/use-hover-capable.ts +23 -0
- package/lib/hooks/use-hover-gesture.ts +61 -0
- package/lib/hooks/use-in-view-animation.ts +35 -0
- package/lib/hooks/use-measure.ts +39 -0
- package/lib/hooks/use-on-open.ts +24 -0
- package/lib/hooks/use-row-cursor.ts +86 -0
- package/lib/hooks/use-slider.ts +176 -0
- package/lib/hooks/use-tap-gesture.ts +66 -0
- package/lib/hooks/use-touch-capable.ts +31 -0
- package/lib/presence-gate.tsx +52 -0
- package/lib/styles.ts +124 -0
- package/lib/text-shimmer.ts +21 -0
- package/lib/tick-sound.ts +151 -0
- package/lib/touch.ts +117 -0
- package/lib/utils.ts +6 -0
- package/package.json +49 -0
- package/references/agents/agent-activity.md +747 -0
- package/references/agents/ai-sidebar.md +293 -0
- package/references/agents/approval-card.md +233 -0
- package/references/agents/chat-app.md +184 -0
- package/references/agents/citations.md +159 -0
- package/references/agents/code-block.md +122 -0
- package/references/agents/file-diff.md +119 -0
- package/references/agents/image-generation.md +173 -0
- package/references/agents/loading-states.md +186 -0
- package/references/agents/message-bubble.md +274 -0
- package/references/agents/message-scroller.md +128 -0
- package/references/agents/message.md +162 -0
- package/references/agents/prompt-input.md +204 -0
- package/references/agents/streaming-response.md +216 -0
- package/references/agents/todo-list.md +123 -0
- package/references/agents/tool-approval.md +143 -0
- package/references/agents/tool-result.md +199 -0
- package/references/blocks/availability-scheduler.md +59 -0
- package/references/blocks/bloom-menu.md +56 -0
- package/references/blocks/card-folder.md +165 -0
- package/references/blocks/command-palette.md +89 -0
- package/references/blocks/dynamic-island.md +203 -0
- package/references/blocks/expandable-action-bar.md +191 -0
- package/references/blocks/expandable-tabs.md +184 -0
- package/references/blocks/feedback-widget.md +82 -0
- package/references/blocks/file-upload.md +406 -0
- package/references/blocks/infinite-masonry.md +211 -0
- package/references/blocks/knockout-bracket.md +161 -0
- package/references/blocks/morphing-search.md +113 -0
- package/references/blocks/morphing-tabs.md +143 -0
- package/references/blocks/not-found.md +228 -0
- package/references/blocks/notification-stack.md +92 -0
- package/references/blocks/otp-input.md +85 -0
- package/references/blocks/overflow-actions.md +105 -0
- package/references/blocks/prediction-market.md +97 -0
- package/references/blocks/project-folder.md +99 -0
- package/references/blocks/signup-form.md +92 -0
- package/references/blocks/swap.md +58 -0
- package/references/blocks/swipeable-list.md +202 -0
- package/references/blocks/wallet-card.md +97 -0
- package/references/codex-install.md +59 -0
- package/references/craft/3d-button.md +51 -0
- package/references/craft/3d-icon-button.md +51 -0
- package/references/craft/add-to-cart-button.md +52 -0
- package/references/craft/analog-clock-minimal.md +51 -0
- package/references/craft/analog-clock-numeric.md +51 -0
- package/references/craft/analog-clock-roman.md +51 -0
- package/references/craft/annotated-text.md +51 -0
- package/references/craft/app-dock.md +52 -0
- package/references/craft/apple-hello-loader.md +51 -0
- package/references/craft/apple-notification.md +53 -0
- package/references/craft/apple-watch.md +51 -0
- package/references/craft/arc-bands-background.md +51 -0
- package/references/craft/audio-recorder.md +52 -0
- package/references/craft/aurora-background.md +51 -0
- package/references/craft/battery-face.md +52 -0
- package/references/craft/blob-profile.md +53 -0
- package/references/craft/bluetooth-face.md +52 -0
- package/references/craft/booking-slot-calendar.md +52 -0
- package/references/craft/bookmark-save-button.md +52 -0
- package/references/craft/browser.md +51 -0
- package/references/craft/cafe-menu-board.md +52 -0
- package/references/craft/calendar-reminder-notification.md +52 -0
- package/references/craft/chat-bubble-notification.md +53 -0
- package/references/craft/checkbox-field-input.md +52 -0
- package/references/craft/cherry-petal-background.md +51 -0
- package/references/craft/cinder-latch-button.md +51 -0
- package/references/craft/cinema-ticket.md +52 -0
- package/references/craft/circle-cut-frame.md +51 -0
- package/references/craft/combobox-field-input.md +52 -0
- package/references/craft/compass.md +51 -0
- package/references/craft/contact-form.md +52 -0
- package/references/craft/contact-profile.md +52 -0
- package/references/craft/copy-email.md +53 -0
- package/references/craft/coral-glow-background.md +51 -0
- package/references/craft/craft-copy-button.md +52 -0
- package/references/craft/craft-signup-form.md +53 -0
- package/references/craft/credit-card-glass.md +51 -0
- package/references/craft/customers-table.md +52 -0
- package/references/craft/daily-activity-calendar.md +52 -0
- package/references/craft/daily-motivation.md +53 -0
- package/references/craft/dark-arc-bands-background.md +51 -0
- package/references/craft/dark-aurora-background.md +51 -0
- package/references/craft/dark-carbon-spotlight-background.md +51 -0
- package/references/craft/dark-ember-background.md +51 -0
- package/references/craft/dark-ink-field-background.md +51 -0
- package/references/craft/dark-midnight-mesh-background.md +51 -0
- package/references/craft/dark-rose-noir-background.md +51 -0
- package/references/craft/dark-teal-depth-background.md +51 -0
- package/references/craft/date-field-input.md +52 -0
- package/references/craft/date-range-picker-card.md +52 -0
- package/references/craft/delivery-notification.md +52 -0
- package/references/craft/denim-product-editorial.md +52 -0
- package/references/craft/deploy-notification.md +52 -0
- package/references/craft/depth-outline-button.md +51 -0
- package/references/craft/diagonal-box-pattern.md +51 -0
- package/references/craft/dimple-switch.md +51 -0
- package/references/craft/discord-chat.md +53 -0
- package/references/craft/dnd-face.md +52 -0
- package/references/craft/dot-grid-pattern.md +51 -0
- package/references/craft/download-button.md +52 -0
- package/references/craft/drop-cap-editorial.md +52 -0
- package/references/craft/editor-tool-dock.md +52 -0
- package/references/craft/editorial-quote.md +52 -0
- package/references/craft/editorial-staff-profile.md +51 -0
- package/references/craft/electric-scooter.md +53 -0
- package/references/craft/email-notification.md +53 -0
- package/references/craft/event-countdown-card.md +51 -0
- package/references/craft/event-ticket.md +53 -0
- package/references/craft/facebook-post.md +53 -0
- package/references/craft/file-menu.md +52 -0
- package/references/craft/file-upload-field-input.md +52 -0
- package/references/craft/film-strip.md +52 -0
- package/references/craft/filter-sort.md +52 -0
- package/references/craft/fine-grain-pattern.md +51 -0
- package/references/craft/flight-arrival.md +52 -0
- package/references/craft/flight-boarding.md +52 -0
- package/references/craft/floating-label-field-input.md +51 -0
- package/references/craft/focus-breath.md +51 -0
- package/references/craft/folder-tab-card.md +52 -0
- package/references/craft/follow-button.md +52 -0
- package/references/craft/forgot-password-form.md +53 -0
- package/references/craft/frost-mesh-background.md +51 -0
- package/references/craft/gallery-grid.md +53 -0
- package/references/craft/gallery-wall.md +52 -0
- package/references/craft/github-contribution.md +52 -0
- package/references/craft/github-repo.md +52 -0
- package/references/craft/glass-overlay-image.md +53 -0
- package/references/craft/graph-paper-pattern.md +51 -0
- package/references/craft/halftone-pop-background.md +51 -0
- package/references/craft/hard-shadow-polaroid-frame.md +51 -0
- package/references/craft/heart-rate.md +52 -0
- package/references/craft/hold-to-delete-button.md +52 -0
- package/references/craft/honey-ember-background.md +51 -0
- package/references/craft/hydration.md +51 -0
- package/references/craft/incoming-call-notification.md +53 -0
- package/references/craft/ink-stamp-document.md +52 -0
- package/references/craft/ink-wash-background.md +51 -0
- package/references/craft/input-group-field.md +51 -0
- package/references/craft/inset-button.md +51 -0
- package/references/craft/instagram-post.md +53 -0
- package/references/craft/ios-calendar-widget.md +51 -0
- package/references/craft/ios-digital-clock.md +51 -0
- package/references/craft/ios-earbuds.md +51 -0
- package/references/craft/ios-map-location.md +51 -0
- package/references/craft/ipad.md +51 -0
- package/references/craft/ipod.md +51 -0
- package/references/craft/journal-writing.md +52 -0
- package/references/craft/kebab-actions.md +52 -0
- package/references/craft/keyboard-shortcuts.md +52 -0
- package/references/craft/laptop.md +51 -0
- package/references/craft/like-button.md +52 -0
- package/references/craft/line-grid-pattern.md +51 -0
- package/references/craft/linen-tab-button.md +51 -0
- package/references/craft/linen-weave-background.md +51 -0
- package/references/craft/linked-in-post.md +53 -0
- package/references/craft/linked-in-profile.md +52 -0
- package/references/craft/login-form.md +53 -0
- package/references/craft/mac-dock.md +52 -0
- package/references/craft/magazine-cover.md +53 -0
- package/references/craft/minimal-agenda.md +52 -0
- package/references/craft/mint-lagoon-background.md +51 -0
- package/references/craft/month-picker-calendar.md +52 -0
- package/references/craft/museum-placard.md +51 -0
- package/references/craft/music-player.md +53 -0
- package/references/craft/music-playlist.md +53 -0
- package/references/craft/newsletter-form.md +52 -0
- package/references/craft/notepad.md +52 -0
- package/references/craft/notification.md +52 -0
- package/references/craft/now-playing-bar.md +53 -0
- package/references/craft/orders-table.md +52 -0
- package/references/craft/otp-boxed-input.md +52 -0
- package/references/craft/otp-underline-input.md +51 -0
- package/references/craft/page-loader-overlay.md +46 -0
- package/references/craft/paper-fold-background.md +51 -0
- package/references/craft/password-field-input.md +52 -0
- package/references/craft/payment-notification.md +52 -0
- package/references/craft/phone-field-input.md +51 -0
- package/references/craft/phone.md +51 -0
- package/references/craft/photo-album.md +52 -0
- package/references/craft/photo-contact-sheet.md +52 -0
- package/references/craft/polaroid-image.md +52 -0
- package/references/craft/pomodoro.md +52 -0
- package/references/craft/presence-dock.md +51 -0
- package/references/craft/prism-depth-button.md +51 -0
- package/references/craft/progress-ring-card.md +51 -0
- package/references/craft/quantity-stepper-button.md +52 -0
- package/references/craft/radio-group-field-input.md +51 -0
- package/references/craft/rain-prism-background.md +51 -0
- package/references/craft/recent-transactions-table.md +52 -0
- package/references/craft/recorder-face.md +52 -0
- package/references/craft/resource-links-panel.md +52 -0
- package/references/craft/retail-price-tag.md +51 -0
- package/references/craft/reverse-diagonal-box-pattern.md +51 -0
- package/references/craft/ride-pickup.md +53 -0
- package/references/craft/sand-drift-background.md +51 -0
- package/references/craft/search-input.md +52 -0
- package/references/craft/segmented-toggle-button.md +51 -0
- package/references/craft/select-field-input.md +52 -0
- package/references/craft/share-menu.md +52 -0
- package/references/craft/sheen-pill-button.md +51 -0
- package/references/craft/slate-chip-switch.md +51 -0
- package/references/craft/sleep-score.md +52 -0
- package/references/craft/slide-to-confirm-button.md +52 -0
- package/references/craft/slow-living-polaroid.md +52 -0
- package/references/craft/soft-pill-button.md +51 -0
- package/references/craft/soft-spotlight-background.md +51 -0
- package/references/craft/soft-ui-button.md +51 -0
- package/references/craft/spin-loader.md +52 -0
- package/references/craft/spotlight-bar.md +52 -0
- package/references/craft/stacked-cards-effect.md +52 -0
- package/references/craft/stacked-folder-card.md +52 -0
- package/references/craft/stamp-postcard.md +52 -0
- package/references/craft/step-count.md +51 -0
- package/references/craft/sticky-note-polaroid-frame.md +51 -0
- package/references/craft/stopwatch.md +52 -0
- package/references/craft/sunrise-horizon-background.md +51 -0
- package/references/craft/sunset-bloom-background.md +51 -0
- package/references/craft/switch-field-input.md +51 -0
- package/references/craft/system-alert.md +52 -0
- package/references/craft/tasks-table.md +53 -0
- package/references/craft/team-member-profile-grid.md +52 -0
- package/references/craft/team-member.md +53 -0
- package/references/craft/team-members-table.md +53 -0
- package/references/craft/terminal-log.md +52 -0
- package/references/craft/terrazzo-fragment-background.md +51 -0
- package/references/craft/testimonial.md +53 -0
- package/references/craft/text-field-input.md +51 -0
- package/references/craft/text-loader.md +51 -0
- package/references/craft/textarea-field-input.md +51 -0
- package/references/craft/thermal-receipt.md +52 -0
- package/references/craft/threads-post.md +53 -0
- package/references/craft/toast-notification.md +52 -0
- package/references/craft/toggle-pricing-cards.md +52 -0
- package/references/craft/torch-face.md +52 -0
- package/references/craft/transform-box-frame.md +51 -0
- package/references/craft/transform-plus-frame.md +51 -0
- package/references/craft/travel-postcard.md +53 -0
- package/references/craft/tropical-tide-background.md +51 -0
- package/references/craft/twitter-post.md +53 -0
- package/references/craft/twitter-profile.md +53 -0
- package/references/craft/user-menu.md +53 -0
- package/references/craft/user-profile.md +53 -0
- package/references/craft/users-select-table.md +53 -0
- package/references/craft/voice-assistant.md +52 -0
- package/references/craft/wallet-pass.md +52 -0
- package/references/craft/weather-snapshot.md +52 -0
- package/references/craft/week-strip-calendar.md +52 -0
- package/references/craft/wifi-toggle.md +52 -0
- package/references/craft/workspace-switcher.md +52 -0
- package/references/guides/baseline-ui-craft.md +61 -0
- package/references/guides/craft-surface-design-system.md +120 -0
- package/references/guides/design-system-checklist.md +98 -0
- package/references/guides/enterprise-dashboard-patterns.md +53 -0
- package/references/guides/interaction-transitions.md +71 -0
- package/references/guides/motion-engineering.md +137 -0
- package/references/guides/motion-patterns.md +106 -0
- package/references/guides/motion-performance.md +66 -0
- package/references/guides/style-presets.md +115 -0
- package/references/guides/universal-mobile-patterns.md +72 -0
- package/references/motion/action-sheet.md +98 -0
- package/references/motion/action-swap.md +339 -0
- package/references/motion/adaptive-stepper.md +95 -0
- package/references/motion/animated-badge.md +92 -0
- package/references/motion/animated-sidebar.md +446 -0
- package/references/motion/animated-toast-stack.md +214 -0
- package/references/motion/aspect-ratio.md +59 -0
- package/references/motion/audio-player.md +59 -0
- package/references/motion/autocomplete.md +69 -0
- package/references/motion/avatar-group.md +93 -0
- package/references/motion/bottom-sheet.md +85 -0
- package/references/motion/bounce-sidebar.md +80 -0
- package/references/motion/bouncy-accordion.md +115 -0
- package/references/motion/breadcrumb.md +62 -0
- package/references/motion/button.md +271 -0
- package/references/motion/card-resize.md +60 -0
- package/references/motion/cascader.md +99 -0
- package/references/motion/center-morph-modal.md +133 -0
- package/references/motion/checkbox.md +76 -0
- package/references/motion/chip.md +81 -0
- package/references/motion/collapsible.md +73 -0
- package/references/motion/color-picker.md +57 -0
- package/references/motion/combobox.md +247 -0
- package/references/motion/confetti.md +65 -0
- package/references/motion/context-menu.md +269 -0
- package/references/motion/copy-button.md +59 -0
- package/references/motion/cylinder-carousel.md +151 -0
- package/references/motion/date-range-picker.md +68 -0
- package/references/motion/dock.md +105 -0
- package/references/motion/drawer.md +94 -0
- package/references/motion/error-shake.md +85 -0
- package/references/motion/event-calendar.md +81 -0
- package/references/motion/expandable-control.md +89 -0
- package/references/motion/expanding-arrow-button.md +178 -0
- package/references/motion/file-tree.md +139 -0
- package/references/motion/filter-builder.md +106 -0
- package/references/motion/frame.md +61 -0
- package/references/motion/gantt.md +61 -0
- package/references/motion/glow-button.md +59 -0
- package/references/motion/haptic-pressable.md +64 -0
- package/references/motion/hover-card.md +86 -0
- package/references/motion/icon-stack.md +64 -0
- package/references/motion/input.md +108 -0
- package/references/motion/kanban.md +111 -0
- package/references/motion/kbd.md +66 -0
- package/references/motion/loader.md +82 -0
- package/references/motion/magnet-dock.md +64 -0
- package/references/motion/marquee.md +68 -0
- package/references/motion/metric-card.md +81 -0
- package/references/motion/morphing-modal.md +230 -0
- package/references/motion/multi-select.md +202 -0
- package/references/motion/number-field.md +70 -0
- package/references/motion/number.md +198 -0
- package/references/motion/page-transition.md +78 -0
- package/references/motion/pagination.md +64 -0
- package/references/motion/password-input.md +77 -0
- package/references/motion/phone-input.md +63 -0
- package/references/motion/popover.md +209 -0
- package/references/motion/preview-rail.md +165 -0
- package/references/motion/progress-ring.md +73 -0
- package/references/motion/pull-to-refresh.md +172 -0
- package/references/motion/radio.md +73 -0
- package/references/motion/range-slider.md +290 -0
- package/references/motion/rating.md +69 -0
- package/references/motion/reorder-grid.md +69 -0
- package/references/motion/resizable-panel.md +75 -0
- package/references/motion/scroll-animation.md +397 -0
- package/references/motion/segmented-control.md +68 -0
- package/references/motion/segmented-progress.md +70 -0
- package/references/motion/select.md +196 -0
- package/references/motion/shader-background.md +351 -0
- package/references/motion/shared-layout-bg.md +80 -0
- package/references/motion/sortable-list.md +62 -0
- package/references/motion/speed-dial.md +63 -0
- package/references/motion/split-text.md +62 -0
- package/references/motion/spotlight-card.md +67 -0
- package/references/motion/stepper.md +83 -0
- package/references/motion/success-check.md +67 -0
- package/references/motion/switch.md +62 -0
- package/references/motion/table.md +519 -0
- package/references/motion/tabs.md +116 -0
- package/references/motion/text-animation.md +285 -0
- package/references/motion/text-swap.md +64 -0
- package/references/motion/theme-toggle.md +82 -0
- package/references/motion/tilt-card.md +59 -0
- package/references/motion/timeline.md +85 -0
- package/references/motion/toggle-group.md +70 -0
- package/references/motion/tooltip.md +82 -0
- package/references/motion/tree-view.md +87 -0
- package/references/motion/wheel-picker.md +142 -0
- package/scripts/build_docs.py +557 -0
- package/scripts/install-component.py +232 -0
- package/scripts/test_release.py +119 -0
- package/scripts/updater.mjs +9 -0
- package/scripts/verify_skill.py +84 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { forwardRef, useState, type ComponentPropsWithoutRef } from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/cn";
|
|
6
|
+
import { Wifi } from "lucide-react";
|
|
7
|
+
|
|
8
|
+
// iOS-style Wi-Fi card with a status dot, network label, and on/off switch.
|
|
9
|
+
export type WiFiToggleWidgetProps = Readonly<
|
|
10
|
+
{
|
|
11
|
+
// Network name shown when Wi-Fi is on.
|
|
12
|
+
networkName?: string;
|
|
13
|
+
// Initial toggle state when the widget first renders.
|
|
14
|
+
defaultOn?: boolean;
|
|
15
|
+
} & ComponentPropsWithoutRef<"div">
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
// iOS-style Wi-Fi card with a status dot, network label, and on/off switch.
|
|
19
|
+
export const WiFiToggleWidget = forwardRef<
|
|
20
|
+
HTMLDivElement,
|
|
21
|
+
WiFiToggleWidgetProps
|
|
22
|
+
>(
|
|
23
|
+
(
|
|
24
|
+
{ className, networkName = "Studio-5G", defaultOn = false, ...props },
|
|
25
|
+
ref,
|
|
26
|
+
) => {
|
|
27
|
+
const [on, setOn] = useState(defaultOn);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
ref={ref}
|
|
32
|
+
data-slot="wifi-toggle-widget"
|
|
33
|
+
className={cn(
|
|
34
|
+
"flex h-44 w-44 flex-col overflow-hidden rounded-3xl border border-neutral-100 bg-white p-4 font-sans shadow-lg shadow-black/5 select-none",
|
|
35
|
+
className,
|
|
36
|
+
)}
|
|
37
|
+
{...props}
|
|
38
|
+
>
|
|
39
|
+
<div className="flex items-center justify-between gap-2">
|
|
40
|
+
<p className="text-[10px] font-semibold tracking-widest text-neutral-400 uppercase">
|
|
41
|
+
Wi-Fi
|
|
42
|
+
</p>
|
|
43
|
+
{/* Green dot = connected, gray dot = off. */}
|
|
44
|
+
<span
|
|
45
|
+
aria-hidden
|
|
46
|
+
className={cn(
|
|
47
|
+
"h-2 w-2 shrink-0 rounded-full transition-colors",
|
|
48
|
+
on ? "bg-emerald-500" : "bg-neutral-300",
|
|
49
|
+
)}
|
|
50
|
+
/>
|
|
51
|
+
<span className="sr-only">{on ? "Connected" : "Off"}</span>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
{/* Icon and network details update based on the toggle state. */}
|
|
55
|
+
<div className="flex flex-1 flex-col items-center justify-center gap-1 py-2">
|
|
56
|
+
<div
|
|
57
|
+
className={cn(
|
|
58
|
+
"flex h-11 w-11 items-center justify-center rounded-full transition-colors",
|
|
59
|
+
on ? "bg-neutral-100" : "bg-neutral-50",
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
62
|
+
<Wifi
|
|
63
|
+
size={22}
|
|
64
|
+
className={cn(
|
|
65
|
+
"transition-colors",
|
|
66
|
+
on ? "text-neutral-900" : "text-neutral-300",
|
|
67
|
+
)}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
<p
|
|
71
|
+
className={cn(
|
|
72
|
+
"max-w-full truncate text-xs font-semibold",
|
|
73
|
+
on ? "text-neutral-900" : "text-neutral-400",
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
{on ? networkName : "No network"}
|
|
77
|
+
</p>
|
|
78
|
+
<p className="text-[10px] text-neutral-400">
|
|
79
|
+
{on ? "WPA3 · 5 GHz" : "Tap to connect"}
|
|
80
|
+
</p>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
{/* Bottom switch — slides right when Wi-Fi is on. */}
|
|
84
|
+
<div className="flex justify-center">
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
aria-label="Toggle Wi-Fi"
|
|
88
|
+
aria-pressed={on}
|
|
89
|
+
onClick={() => setOn(!on)}
|
|
90
|
+
className={cn(
|
|
91
|
+
"flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full p-0.5 transition-colors",
|
|
92
|
+
on ? "bg-emerald-400" : "bg-neutral-200",
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
<span
|
|
96
|
+
className={cn(
|
|
97
|
+
"h-5 w-5 rounded-full bg-white shadow-sm transition-transform duration-200 ease-out",
|
|
98
|
+
on ? "translate-x-5" : "translate-x-0",
|
|
99
|
+
)}
|
|
100
|
+
/>
|
|
101
|
+
</button>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
WiFiToggleWidget.displayName = "WiFiToggleWidget";
|
package/lib/cn.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cn } from "./utils";
|
package/lib/ease.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Shared motion tokens. Easing curves mirror the CSS custom properties in
|
|
2
|
+
// globals.css; springs are the canonical physics used across components.
|
|
3
|
+
// Strong custom variants — defaults like `ease-in`/`ease-out` feel weak.
|
|
4
|
+
|
|
5
|
+
export const EASE_OUT = [0.16, 1, 0.3, 1] as const;
|
|
6
|
+
export const EASE_IN_OUT = [0.77, 0, 0.175, 1] as const;
|
|
7
|
+
export const EASE_DRAWER = [0.32, 0.72, 0, 1] as const;
|
|
8
|
+
|
|
9
|
+
/** CSS string form of EASE_OUT for inline style transitions. */
|
|
10
|
+
export const EASE_OUT_CSS = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
11
|
+
|
|
12
|
+
export type SpringConfig = Readonly<{
|
|
13
|
+
type: "spring";
|
|
14
|
+
stiffness: number;
|
|
15
|
+
damping: number;
|
|
16
|
+
mass: number;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
/** Press feedback on buttons and other tappable surfaces. */
|
|
20
|
+
export const SPRING_PRESS = {
|
|
21
|
+
type: "spring",
|
|
22
|
+
stiffness: 500,
|
|
23
|
+
damping: 30,
|
|
24
|
+
mass: 0.6,
|
|
25
|
+
} as const;
|
|
26
|
+
|
|
27
|
+
/** Content swaps — label/icon slots trading places inside a control. */
|
|
28
|
+
export const SPRING_SWAP = {
|
|
29
|
+
type: "spring",
|
|
30
|
+
stiffness: 460,
|
|
31
|
+
damping: 30,
|
|
32
|
+
mass: 0.55,
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
/** Overlay panel entrances — modals and sheets summoned by pointer. */
|
|
36
|
+
export const SPRING_PANEL = {
|
|
37
|
+
type: "spring",
|
|
38
|
+
stiffness: 420,
|
|
39
|
+
damping: 40,
|
|
40
|
+
mass: 0.5,
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
/** Shared-layout glides — pills, indicators and panels morphing between positions. */
|
|
44
|
+
export const SPRING_LAYOUT = {
|
|
45
|
+
type: "spring",
|
|
46
|
+
stiffness: 360,
|
|
47
|
+
damping: 32,
|
|
48
|
+
mass: 0.6,
|
|
49
|
+
} as const;
|
|
50
|
+
|
|
51
|
+
/** Cursor-follow physics for decorative mouse tracking (magnetic, tilt, dock). */
|
|
52
|
+
export const SPRING_MOUSE = {
|
|
53
|
+
stiffness: 200,
|
|
54
|
+
damping: 15,
|
|
55
|
+
mass: 0.3,
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
/** Dragged handles and fills (sliders) — critically damped `useSpring` config,
|
|
59
|
+
* so the value follows the pointer butterily and never rebounds off an end. */
|
|
60
|
+
export const SPRING_GLIDE = {
|
|
61
|
+
stiffness: 700,
|
|
62
|
+
damping: 50,
|
|
63
|
+
mass: 0.5,
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
/** Playful bounce for badges, celebration checks, stars, and micro-pops. */
|
|
67
|
+
export const SPRING_BOUNCE = {
|
|
68
|
+
type: "spring",
|
|
69
|
+
stiffness: 300,
|
|
70
|
+
damping: 18,
|
|
71
|
+
mass: 0.8,
|
|
72
|
+
} as const;
|
|
73
|
+
|
|
74
|
+
/** Gentle, natural spring for spacious card expansions and drawer reveals. */
|
|
75
|
+
export const SPRING_GENTLE = {
|
|
76
|
+
type: "spring",
|
|
77
|
+
stiffness: 180,
|
|
78
|
+
damping: 24,
|
|
79
|
+
mass: 1.0,
|
|
80
|
+
} as const;
|
|
81
|
+
|
|
82
|
+
/** Snappy, high-velocity spring for fast toggles, segmented pills, and tabs. */
|
|
83
|
+
export const SPRING_SNAPPY = {
|
|
84
|
+
type: "spring",
|
|
85
|
+
stiffness: 600,
|
|
86
|
+
damping: 35,
|
|
87
|
+
mass: 0.5,
|
|
88
|
+
} as const;
|
|
89
|
+
|
|
90
|
+
/** Soft floating physics for tooltips, hover cards, and ambient elevation. */
|
|
91
|
+
export const SPRING_FLOAT = {
|
|
92
|
+
type: "spring",
|
|
93
|
+
stiffness: 120,
|
|
94
|
+
damping: 14,
|
|
95
|
+
mass: 0.8,
|
|
96
|
+
} as const;
|
|
97
|
+
|
|
98
|
+
/** Emphasized cubic bezier for expressive spatial navigation. */
|
|
99
|
+
export const EASE_EMPHASIZED = [0.2, 0, 0, 1] as const;
|
|
100
|
+
export const EASE_EMPHASIZED_CSS = "cubic-bezier(0.2, 0, 0, 1)";
|
|
101
|
+
|
|
102
|
+
/** Deceleration curve for incoming elements that enter at high velocity and brake. */
|
|
103
|
+
export const EASE_DECELERATE = [0.05, 0.7, 0.1, 1] as const;
|
|
104
|
+
export const EASE_DECELERATE_CSS = "cubic-bezier(0.05, 0.7, 0.1, 1)";
|
|
105
|
+
|
|
106
|
+
/** Acceleration curve for dismissed elements that exit without lingering. */
|
|
107
|
+
export const EASE_ACCELERATE = [0.3, 0, 0.8, 0.15] as const;
|
|
108
|
+
export const EASE_ACCELERATE_CSS = "cubic-bezier(0.3, 0, 0.8, 0.15)";
|
package/lib/favicon.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type RefObject, useEffect } from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What the dismissing gesture does to the control it landed on.
|
|
7
|
+
*
|
|
8
|
+
* `"pass-through"` is the platform norm (native popover light-dismiss): the
|
|
9
|
+
* tap closes the overlay *and* activates whatever was under it. Use
|
|
10
|
+
* `"consume"` where the open overlay sits over or beside controls that would
|
|
11
|
+
* be costly to trigger by accident — the dismissal then swallows the
|
|
12
|
+
* activation too, so the gesture only closes.
|
|
13
|
+
*/
|
|
14
|
+
export type DismissBehavior = "pass-through" | "consume";
|
|
15
|
+
|
|
16
|
+
export interface DismissOptions {
|
|
17
|
+
/** Default `"pass-through"`. */
|
|
18
|
+
behavior?: DismissBehavior;
|
|
19
|
+
/** Dismiss on Escape as well. Default true. */
|
|
20
|
+
escape?: boolean;
|
|
21
|
+
/** Return true for an outside target that should *not* dismiss. Must be stable. */
|
|
22
|
+
ignore?: (target: Element) => boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* What every currently open dismiss scope counts as inside itself. A consumed
|
|
27
|
+
* dismissal reads this to tell a stray gesture from one that belongs to an
|
|
28
|
+
* overlay in front of it: overlays have no shared z-order to consult, but the
|
|
29
|
+
* one the gesture landed in has said as much by registering it.
|
|
30
|
+
*/
|
|
31
|
+
const openScopes = new Set<(target: Element) => boolean>();
|
|
32
|
+
|
|
33
|
+
function claimedByAnotherScope(
|
|
34
|
+
self: (target: Element) => boolean,
|
|
35
|
+
target: Element,
|
|
36
|
+
) {
|
|
37
|
+
for (const scope of openScopes) {
|
|
38
|
+
if (scope !== self && scope(target)) return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// preventDefault on pointerdown does not suppress the click that follows, so
|
|
44
|
+
// consuming a gesture means swallowing that click itself. The swallower
|
|
45
|
+
// deliberately outlives the effect that installed it — the dismissal it
|
|
46
|
+
// belongs to has already unmounted or re-rendered by the time the click lands.
|
|
47
|
+
// It releases on that click, or on the next gesture if the pointer is dragged
|
|
48
|
+
// away and no click ever arrives, so it can never eat a later one. A keydown
|
|
49
|
+
// releases it too: a gesture that ends with neither a click nor a cancel would
|
|
50
|
+
// otherwise leave it armed, and the click Enter synthesizes on some focused
|
|
51
|
+
// control is not the one this dismissal was owed.
|
|
52
|
+
function consumeActivation(source: Event) {
|
|
53
|
+
const swallow = (event: MouseEvent) => {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
release();
|
|
57
|
+
};
|
|
58
|
+
const restart = (event: Event) => {
|
|
59
|
+
if (event !== source) release();
|
|
60
|
+
};
|
|
61
|
+
const release = () => {
|
|
62
|
+
window.removeEventListener("click", swallow, true);
|
|
63
|
+
window.removeEventListener("pointerdown", restart, true);
|
|
64
|
+
window.removeEventListener("pointercancel", restart, true);
|
|
65
|
+
window.removeEventListener("keydown", release, true);
|
|
66
|
+
};
|
|
67
|
+
window.addEventListener("click", swallow, true);
|
|
68
|
+
window.addEventListener("pointerdown", restart, true);
|
|
69
|
+
window.addEventListener("pointercancel", restart, true);
|
|
70
|
+
window.addEventListener("keydown", release, true);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Close an open overlay on Escape or a pointerdown outside `ref`. Pass `null`
|
|
75
|
+
* for `ref` when what counts as inside isn't one element, and say so with
|
|
76
|
+
* `ignore` instead.
|
|
77
|
+
*
|
|
78
|
+
* The pointerdown listener is capture-phase: a bubble-phase one is blinded by
|
|
79
|
+
* any handler in between that stops propagation, and an overlay cannot know
|
|
80
|
+
* what it is layered over. `onDismiss` and `ignore` must be stable (wrap in
|
|
81
|
+
* useCallback) so the listeners aren't re-bound every render while open.
|
|
82
|
+
*/
|
|
83
|
+
export function useDismiss(
|
|
84
|
+
open: boolean,
|
|
85
|
+
onDismiss: () => void,
|
|
86
|
+
ref: RefObject<HTMLElement | null> | null,
|
|
87
|
+
{
|
|
88
|
+
behavior = "pass-through",
|
|
89
|
+
escape: dismissOnEscape = true,
|
|
90
|
+
ignore,
|
|
91
|
+
}: DismissOptions = {},
|
|
92
|
+
) {
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (!open) return;
|
|
95
|
+
const inside = (target: Element) =>
|
|
96
|
+
Boolean(ref?.current?.contains(target)) || Boolean(ignore?.(target));
|
|
97
|
+
const onKey = (event: KeyboardEvent) => {
|
|
98
|
+
if (dismissOnEscape && event.key === "Escape") onDismiss();
|
|
99
|
+
};
|
|
100
|
+
const onPointer = (event: PointerEvent) => {
|
|
101
|
+
const target = event.target as Element | null;
|
|
102
|
+
if (!target || inside(target)) return;
|
|
103
|
+
// Outside this overlay, but inside one that is also open: the gesture is
|
|
104
|
+
// that overlay's to answer, and swallowing its click from behind would
|
|
105
|
+
// cost the user the control they actually aimed at.
|
|
106
|
+
if (behavior === "consume" && !claimedByAnotherScope(inside, target)) {
|
|
107
|
+
consumeActivation(event);
|
|
108
|
+
}
|
|
109
|
+
onDismiss();
|
|
110
|
+
};
|
|
111
|
+
openScopes.add(inside);
|
|
112
|
+
window.addEventListener("keydown", onKey);
|
|
113
|
+
window.addEventListener("pointerdown", onPointer, true);
|
|
114
|
+
return () => {
|
|
115
|
+
openScopes.delete(inside);
|
|
116
|
+
window.removeEventListener("keydown", onKey);
|
|
117
|
+
window.removeEventListener("pointerdown", onPointer, true);
|
|
118
|
+
};
|
|
119
|
+
}, [open, onDismiss, ref, behavior, dismissOnEscape, ignore]);
|
|
120
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { getFaviconUrl } from "@/lib/favicon";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a site favicon and drops it once it is known to be unusable, so
|
|
8
|
+
* callers can draw their own glyph instead of a broken image. Plenty of sites
|
|
9
|
+
* answer `/favicon.ico` with a 403 or 404, and `onError` is not enough to catch
|
|
10
|
+
* it: an image the browser starts loading from server-rendered HTML usually
|
|
11
|
+
* fails before React attaches a handler, and that event is never replayed.
|
|
12
|
+
* `decode()` settles on the image's final state instead of relying on an event
|
|
13
|
+
* firing at the right moment.
|
|
14
|
+
*/
|
|
15
|
+
export function useFavicon(url?: string) {
|
|
16
|
+
const resolved = url ? getFaviconUrl(url) : null;
|
|
17
|
+
const [failedSrc, setFailedSrc] = useState<string | null>(null);
|
|
18
|
+
const src = resolved && resolved !== failedSrc ? resolved : null;
|
|
19
|
+
|
|
20
|
+
const ref = useCallback(
|
|
21
|
+
(img: HTMLImageElement | null) => {
|
|
22
|
+
if (!img || !src) return;
|
|
23
|
+
|
|
24
|
+
let released = false;
|
|
25
|
+
img.decode().catch(() => {
|
|
26
|
+
if (!released) setFailedSrc(src);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// The node is going away or the source changed; a late rejection then
|
|
30
|
+
// describes an image we are no longer showing.
|
|
31
|
+
return () => {
|
|
32
|
+
released = true;
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
[src],
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return { src, ref };
|
|
39
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
|
|
5
|
+
export type HapticType =
|
|
6
|
+
| "selection"
|
|
7
|
+
| "light"
|
|
8
|
+
| "medium"
|
|
9
|
+
| "heavy"
|
|
10
|
+
| "success"
|
|
11
|
+
| "warning"
|
|
12
|
+
| "error";
|
|
13
|
+
|
|
14
|
+
const HAPTIC_PATTERNS: Record<HapticType, number | number[]> = {
|
|
15
|
+
selection: 10,
|
|
16
|
+
light: 15,
|
|
17
|
+
medium: 30,
|
|
18
|
+
heavy: 50,
|
|
19
|
+
success: [15, 60, 25],
|
|
20
|
+
warning: [30, 80, 30],
|
|
21
|
+
error: [40, 60, 40, 60, 40],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Provides semantic haptic feedback using navigator.vibrate where available.
|
|
26
|
+
* Degrades silently on desktop browsers or unsupported devices.
|
|
27
|
+
*/
|
|
28
|
+
export function useHaptic() {
|
|
29
|
+
const trigger = useCallback((type: HapticType = "selection") => {
|
|
30
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (typeof navigator.vibrate === "function") {
|
|
34
|
+
try {
|
|
35
|
+
const pattern = HAPTIC_PATTERNS[type];
|
|
36
|
+
navigator.vibrate(pattern);
|
|
37
|
+
} catch {
|
|
38
|
+
// Silently catch browsers blocking vibration
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
return trigger;
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns true only on devices that have a true hover (mouse / trackpad).
|
|
7
|
+
* Touch devices fire phantom `:hover` on tap that sticks until tap-elsewhere
|
|
8
|
+
* — gate hover-only effects (scale lifts, magnetic pulls) behind this.
|
|
9
|
+
*/
|
|
10
|
+
export function useHoverCapable() {
|
|
11
|
+
const [canHover, setCanHover] = useState(false);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
15
|
+
const mq = window.matchMedia("(hover: hover) and (pointer: fine)");
|
|
16
|
+
const update = () => setCanHover(mq.matches);
|
|
17
|
+
update();
|
|
18
|
+
mq.addEventListener?.("change", update);
|
|
19
|
+
return () => mq.removeEventListener?.("change", update);
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
return canHover;
|
|
23
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo, useRef } from "react";
|
|
4
|
+
import { isHoveringPointer } from "@/lib/touch";
|
|
5
|
+
|
|
6
|
+
interface BoundaryEvent {
|
|
7
|
+
pointerId: number;
|
|
8
|
+
pointerType: string;
|
|
9
|
+
buttons: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HoverGesture {
|
|
13
|
+
/** True when this enter starts a hover: the pointer arrived resting, not pressing. */
|
|
14
|
+
enter: (event: BoundaryEvent) => boolean;
|
|
15
|
+
/** True when this leave ends a hover that entered as one. */
|
|
16
|
+
leave: (event: BoundaryEvent) => boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Pairs a surface's enter with its leave, per pointer.
|
|
21
|
+
*
|
|
22
|
+
* `isHoveringPointer` answers the question the *enter* asks — is this pointer
|
|
23
|
+
* resting on the surface or pressing it — and both boundary cases go wrong if
|
|
24
|
+
* the leave is asked the same question again:
|
|
25
|
+
*
|
|
26
|
+
* - A pen with no hover never rests. It arrives in contact, taps, and the spec
|
|
27
|
+
* then requires its boundary events after `pointerup`, so the leave carries
|
|
28
|
+
* `buttons: 0` and reads as a mouse gliding off. Hover teardown then undid
|
|
29
|
+
* the tap — the panel the pen had just opened closed under it.
|
|
30
|
+
* - A mouse pressed on the surface and dragged off leaves with `buttons: 1`.
|
|
31
|
+
* Skipping teardown there strands the surface open: the release happens
|
|
32
|
+
* outside, and no second leave ever comes.
|
|
33
|
+
*
|
|
34
|
+
* So the state a hover holds is released by the pointer that took it, whatever
|
|
35
|
+
* the buttons say at the boundary, and a pointer that arrived in contact never
|
|
36
|
+
* took it in the first place. Contact is the exception tracked here, not
|
|
37
|
+
* hover: a leave from a pointer this surface never saw enter — mounted under
|
|
38
|
+
* the cursor, say — still counts, since the alternative is state with no way
|
|
39
|
+
* out.
|
|
40
|
+
*/
|
|
41
|
+
export function useHoverGesture(): HoverGesture {
|
|
42
|
+
const contact = useRef(new Set<number>());
|
|
43
|
+
|
|
44
|
+
return useMemo(
|
|
45
|
+
() => ({
|
|
46
|
+
enter: (event) => {
|
|
47
|
+
if (isHoveringPointer(event)) {
|
|
48
|
+
contact.current.delete(event.pointerId);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
contact.current.add(event.pointerId);
|
|
52
|
+
return false;
|
|
53
|
+
},
|
|
54
|
+
leave: (event) => {
|
|
55
|
+
const arrivedInContact = contact.current.delete(event.pointerId);
|
|
56
|
+
return !arrivedInContact && event.pointerType !== "touch";
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
[],
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useInView, useReducedMotion, type UseInViewOptions } from "motion/react";
|
|
4
|
+
import { useRef, type RefObject } from "react";
|
|
5
|
+
|
|
6
|
+
type InViewMargin = NonNullable<UseInViewOptions["margin"]>;
|
|
7
|
+
|
|
8
|
+
export interface UseInViewAnimationOptions {
|
|
9
|
+
once?: boolean;
|
|
10
|
+
amount?: "some" | "all" | number;
|
|
11
|
+
margin?: InViewMargin;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hook to trigger motion animations when an element scrolls into view.
|
|
16
|
+
* Automatically respects reduced-motion preferences.
|
|
17
|
+
*/
|
|
18
|
+
export function useInViewAnimation<T extends HTMLElement = HTMLElement>(
|
|
19
|
+
options: UseInViewAnimationOptions = {}
|
|
20
|
+
): {
|
|
21
|
+
ref: RefObject<T | null>;
|
|
22
|
+
isInView: boolean;
|
|
23
|
+
shouldAnimate: boolean;
|
|
24
|
+
} {
|
|
25
|
+
const { once = true, amount = 0.2, margin = "0px" } = options;
|
|
26
|
+
const ref = useRef<T | null>(null);
|
|
27
|
+
const isInView = useInView(ref, { once, amount, margin });
|
|
28
|
+
const prefersReduced = useReducedMotion();
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
ref,
|
|
32
|
+
isInView,
|
|
33
|
+
shouldAnimate: isInView && !prefersReduced,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState, type RefCallback } from "react";
|
|
4
|
+
|
|
5
|
+
export interface Dimensions {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Measure DOM element dimensions using ResizeObserver without layout thrashing.
|
|
12
|
+
*/
|
|
13
|
+
export function useMeasure<T extends HTMLElement = HTMLElement>(): [
|
|
14
|
+
RefCallback<T>,
|
|
15
|
+
Dimensions
|
|
16
|
+
] {
|
|
17
|
+
const [element, setElement] = useState<T | null>(null);
|
|
18
|
+
const [bounds, setBounds] = useState<Dimensions>({ width: 0, height: 0 });
|
|
19
|
+
const ref = useCallback<RefCallback<T>>((next) => setElement(next), []);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!element || typeof ResizeObserver === "undefined") return;
|
|
23
|
+
|
|
24
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
25
|
+
if (entry && entry.contentRect) {
|
|
26
|
+
const { width, height } = entry.contentRect;
|
|
27
|
+
setBounds({
|
|
28
|
+
width: Math.round(width),
|
|
29
|
+
height: Math.round(height),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
observer.observe(element);
|
|
35
|
+
return () => observer.disconnect();
|
|
36
|
+
}, [element]);
|
|
37
|
+
|
|
38
|
+
return [ref, bounds];
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs `start` during the render in which `open` becomes true.
|
|
7
|
+
*
|
|
8
|
+
* Opening a list starts a fresh session — an empty query, the highlight back at
|
|
9
|
+
* the top — and that is a resolution, not a side effect: a passive effect runs
|
|
10
|
+
* after the commit, so the new session would carry the last one's state for a
|
|
11
|
+
* window in which a key press can land.
|
|
12
|
+
*
|
|
13
|
+
* `start` may only set state belonging to the calling component. Anything that
|
|
14
|
+
* reaches outside it — a consumer's callback, a DOM write, moving focus — is a
|
|
15
|
+
* side effect, and React rejects a callback that sets another component's state
|
|
16
|
+
* during this one's render. Put those in an effect keyed to `open`.
|
|
17
|
+
*/
|
|
18
|
+
export function useOnOpen(open: boolean, start: () => void) {
|
|
19
|
+
const [wasOpen, setWasOpen] = useState(open);
|
|
20
|
+
if (open !== wasOpen) {
|
|
21
|
+
setWasOpen(open);
|
|
22
|
+
if (open) start();
|
|
23
|
+
}
|
|
24
|
+
}
|