@espressif/dashboard-ui-components 1.10.0 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/dist/_vendor/@radix-ui/primitive/dist/index.js +9 -0
- package/dist/_vendor/@radix-ui/react-checkbox/dist/index.js +185 -0
- package/dist/_vendor/@radix-ui/react-compose-refs/dist/index.js +28 -0
- package/dist/_vendor/@radix-ui/react-context/dist/index.js +68 -0
- package/dist/_vendor/@radix-ui/react-presence/dist/index.js +127 -0
- package/dist/_vendor/@radix-ui/react-primitive/dist/index.js +42 -0
- package/dist/_vendor/@radix-ui/react-use-controllable-state/dist/index.js +55 -0
- package/dist/_vendor/@radix-ui/react-use-layout-effect/dist/index.js +5 -0
- package/dist/_vendor/@radix-ui/react-use-previous/dist/index.js +17 -0
- package/dist/_vendor/@radix-ui/react-use-size/dist/index.js +39 -0
- package/dist/_vendor/lottie-react/build/index.es.js +537 -0
- package/dist/_vendor/lottie-web/build/player/lottie.js +14149 -0
- package/dist/_virtual/_rolldown/runtime.js +24 -0
- package/dist/assets/illustrations/bulb-cloud-drawing.js +4 -0
- package/dist/assets/illustrations/rm-dashboard-update.js +4 -0
- package/dist/assets/illustrations/rm-data-download.js +4 -0
- package/dist/assets/logos/espressif/espressif-no-text.js +4 -0
- package/dist/assets/logos/espressif/espressif-with-text-dm.js +4 -0
- package/dist/assets/logos/espressif/espressif-with-text.js +4 -0
- package/dist/assets/logos/insights/insights-no-text.js +4 -0
- package/dist/assets/logos/insights/insights-with-text-dm.js +4 -0
- package/dist/assets/logos/insights/insights-with-text.js +4 -0
- package/dist/assets/logos/launchpad/launchpad-no-text-dm.js +4 -0
- package/dist/assets/logos/launchpad/launchpad-no-text.js +4 -0
- package/dist/assets/logos/launchpad/launchpad-with-text-dm.js +4 -0
- package/dist/assets/logos/launchpad/launchpad-with-text.js +4 -0
- package/dist/assets/logos/private-agents/private-agents-no-text.js +4 -0
- package/dist/assets/logos/private-agents/private-agents-with-text-dm.js +4 -0
- package/dist/assets/logos/private-agents/private-agents-with-text.js +4 -0
- package/dist/assets/logos/rainmaker/rainmaker-no-text.js +4 -0
- package/dist/assets/logos/rainmaker/rainmaker-with-text-dm.js +4 -0
- package/dist/assets/logos/rainmaker/rainmaker-with-text.js +4 -0
- package/dist/assets/logos/rainmaker-classic/rainmaker-classic-no-text-dm.js +4 -0
- package/dist/assets/logos/rainmaker-classic/rainmaker-classic-no-text.js +4 -0
- package/dist/assets/logos/rainmaker-classic/rainmaker-classic-with-text-dm.js +4 -0
- package/dist/assets/logos/rainmaker-classic/rainmaker-classic-with-text.js +4 -0
- package/dist/assets/logos/rainmaker-neo/rainmaker-neo-no-text.js +4 -0
- package/dist/assets/logos/rainmaker-neo/rainmaker-neo-with-text-dm.js +4 -0
- package/dist/assets/logos/rainmaker-neo/rainmaker-neo-with-text.js +4 -0
- package/dist/assets/logos/ui-components/ui-components-no-text.js +4 -0
- package/dist/assets/logos/ui-components/ui-components-with-text-dm.js +4 -0
- package/dist/assets/logos/ui-components/ui-components-with-text.js +4 -0
- package/dist/assets/logos/zerocode/zerocode-no-text.js +4 -0
- package/dist/assets/logos/zerocode/zerocode-with-text-dm.js +4 -0
- package/dist/assets/logos/zerocode/zerocode-with-text.js +4 -0
- package/dist/assets/logos/zerocode-ai/zerocode-ai-no-text.js +4 -0
- package/dist/assets/logos/zerocode-ai/zerocode-ai-with-text-dm.js +4 -0
- package/dist/assets/logos/zerocode-ai/zerocode-ai-with-text.js +4 -0
- package/dist/common/animated-rainmaker-logo/animated-rainmaker-logo.constants.js +18 -0
- package/dist/common/animated-rainmaker-logo/animated-rainmaker-logo.js +24 -0
- package/dist/common/animated-rainmaker-logo/rainmaker-c-logo.js +50 -0
- package/dist/common/animated-rainmaker-logo/use-animated-rainmaker-logo-animation.js +85 -0
- package/dist/common/app-logo/app-logo.js +59 -0
- package/dist/common/app-logo/logo-config.js +297 -0
- package/dist/common/copyright-card/copyright-card.js +39 -0
- package/dist/common/footer-card/footer-card.js +22 -0
- package/dist/common/index.js +8 -8
- package/dist/common/my-account-menu/my-account-menu.js +32 -0
- package/dist/common/page-loader/page-loader.js +21 -0
- package/dist/common/profile-card/profile-card.js +26 -0
- package/dist/components/accordion/accordion.js +52 -0
- package/dist/components/advanced-search-box/advanced-search-box.js +106 -0
- package/dist/components/alert/alert.js +85 -0
- package/dist/components/animated-containers/pop-collection-item.js +28 -0
- package/dist/components/async-multi-select/async-multi-select.js +199 -0
- package/dist/components/avatar/avatar.js +41 -0
- package/dist/components/button/button.js +191 -0
- package/dist/components/button/flash-button.js +110 -0
- package/dist/components/button/invert-button.js +13 -0
- package/dist/components/calendar/calendar.js +105 -0
- package/dist/components/cards/animated-card/animated-card-animations.js +57 -0
- package/dist/components/cards/animated-card/animated-card.js +42 -0
- package/dist/components/cards/basic-details-card.js +46 -0
- package/dist/components/cards/collapsible-card.js +48 -0
- package/dist/components/cards/no-data-card/no-data-card.js +30 -0
- package/dist/components/cards/section-card.js +265 -0
- package/dist/components/cards/simple-card.js +24 -0
- package/dist/components/carousel/carousel.js +158 -0
- package/dist/components/chart/area-chart.js +135 -0
- package/dist/components/chart/bar-chart.js +151 -0
- package/dist/components/chart/chart-colors.js +85 -0
- package/dist/components/chart/chart-series-data.js +53 -0
- package/dist/components/chart/chart.js +147 -0
- package/dist/components/chart/chart.types.js +7 -0
- package/dist/components/chart/composed-chart.js +182 -0
- package/dist/components/chart/donut-chart.js +177 -0
- package/dist/components/chart/line-chart.js +137 -0
- package/dist/components/chart/treemap-chart.js +294 -0
- package/dist/components/circular-progress/circular-progress.js +125 -0
- package/dist/components/code-editor/code-editor.js +235 -0
- package/dist/components/code-editor/code-editor.utils.js +122 -0
- package/dist/components/code-editor/use-code-editor-keys.js +79 -0
- package/dist/components/code-editor/use-highlighted-html.js +102 -0
- package/dist/components/confirmation-dialog/confirmation-dialog.js +72 -0
- package/dist/components/content-container/content-container.js +20 -0
- package/dist/components/copiable-text/copiable-text.js +46 -0
- package/dist/components/data-table/data-table.js +186 -0
- package/dist/components/data-table/responsive-columns.js +65 -0
- package/dist/components/data-table/row-actions.js +27 -0
- package/dist/components/data-table/sticky-columns.js +71 -0
- package/dist/components/data-table/table-body.js +57 -0
- package/dist/components/data-table/table-header.js +21 -0
- package/dist/components/date-picker/date-picker.js +95 -0
- package/dist/components/date-range-picker/date-range-picker.js +301 -0
- package/dist/components/date-range-picker/presets.js +174 -0
- package/dist/components/date-time-picker/date-time-picker.js +144 -0
- package/dist/components/date-time-picker/date-time-picker.utils.js +32 -0
- package/dist/components/device-icon/device-icon.config.js +194 -0
- package/dist/components/device-icon/device-icon.js +17 -0
- package/dist/components/device-icon/icons/air-conditioner.js +22 -0
- package/dist/components/device-icon/icons/blind.js +24 -0
- package/dist/components/device-icon/icons/dimmer.js +14 -0
- package/dist/components/device-icon/icons/extension-board.js +42 -0
- package/dist/components/device-icon/icons/fan.js +14 -0
- package/dist/components/device-icon/icons/knob.js +14 -0
- package/dist/components/device-icon/icons/led-strip.js +22 -0
- package/dist/components/device-icon/icons/light.js +14 -0
- package/dist/components/device-icon/icons/refrigerator.js +18 -0
- package/dist/components/device-icon/icons/retro-switch.js +18 -0
- package/dist/components/device-icon/icons/router.js +20 -0
- package/dist/components/device-icon/icons/sensor.js +20 -0
- package/dist/components/device-icon/icons/socket.js +19 -0
- package/dist/components/device-icon/icons/switch.js +19 -0
- package/dist/components/device-icon/icons/thermostat.js +21 -0
- package/dist/components/device-icon/icons/washing-machine.js +22 -0
- package/dist/components/device-icon/match-device.js +61 -0
- package/dist/components/dynamic-list/dynamic-list.js +445 -0
- package/dist/components/error-display/full-size-error/full-size-error.js +20 -0
- package/dist/components/error-display/inline-error/inline-error.js +12 -0
- package/dist/components/file-input/file-input.js +318 -0
- package/dist/components/file-upload/file-upload.js +317 -0
- package/dist/components/filters-bar/filters-bar.js +36 -0
- package/dist/components/fullscreen-dialog/fullscreen-dialog.js +68 -0
- package/dist/components/icon-avatar/icon-avatar.js +130 -0
- package/dist/components/icon-text-action-card/icon-text-action-card.js +190 -0
- package/dist/components/illustration/illustration-registry.js +37 -0
- package/dist/components/illustration/illustration-variants.js +21 -0
- package/dist/components/illustration/illustration.js +68 -0
- package/dist/components/index.d.ts +0 -20
- package/dist/components/index.js +134 -6
- package/dist/components/key-value-manager/key-value-manager-add-popover.js +126 -0
- package/dist/components/key-value-manager/key-value-manager-field.js +47 -0
- package/dist/components/key-value-manager/key-value-manager-table.js +188 -0
- package/dist/components/key-value-manager/key-value-manager.js +111 -0
- package/dist/components/key-value-manager/key-value-manager.props.js +28 -0
- package/dist/components/key-value-manager/key-value-manager.utils.js +21 -0
- package/dist/components/link/link.js +67 -0
- package/dist/components/list/dropdown-list-item.js +60 -0
- package/dist/components/list/list-item.utils.js +76 -0
- package/dist/components/list/list.js +49 -0
- package/dist/components/list/list.props.js +27 -0
- package/dist/components/list/standard-list-item.js +66 -0
- package/dist/components/list-details/list-details-item-button.js +46 -0
- package/dist/components/list-details/list-details-item-dropdown.js +112 -0
- package/dist/components/list-details/list-details-item-strip.js +125 -0
- package/dist/components/list-details/list-details.js +148 -0
- package/dist/components/lottie-animation-container/lottie-animation-container.js +31 -0
- package/dist/components/lottie-animations/animation-data/access-denied.js +3980 -0
- package/dist/components/lottie-animations/animation-data/active.js +825 -0
- package/dist/components/lottie-animations/animation-data/bar-chart.js +610 -0
- package/dist/components/lottie-animations/animation-data/chart-loading.js +5368 -0
- package/dist/components/lottie-animations/animation-data/cloud-download.js +1660 -0
- package/dist/components/lottie-animations/animation-data/cloud-sync.js +932 -0
- package/dist/components/lottie-animations/animation-data/coud-upload.js +7060 -0
- package/dist/components/lottie-animations/animation-data/cross-throb.js +1506 -0
- package/dist/components/lottie-animations/animation-data/dashboard-loading.js +14330 -0
- package/dist/components/lottie-animations/animation-data/error-spread-out.js +5567 -0
- package/dist/components/lottie-animations/animation-data/error.js +1211 -0
- package/dist/components/lottie-animations/animation-data/green-success.js +14826 -0
- package/dist/components/lottie-animations/animation-data/inactive.js +723 -0
- package/dist/components/lottie-animations/animation-data/light.js +2678 -0
- package/dist/components/lottie-animations/animation-data/lock.js +900 -0
- package/dist/components/lottie-animations/animation-data/lock2.js +1686 -0
- package/dist/components/lottie-animations/animation-data/locked.js +641 -0
- package/dist/components/lottie-animations/animation-data/search-error.js +954 -0
- package/dist/components/lottie-animations/animation-data/security.js +4121 -0
- package/dist/components/lottie-animations/animation-data/success.js +404 -0
- package/dist/components/lottie-animations/animation-data/verification-in-progress.js +10138 -0
- package/dist/components/lottie-animations/animation-data/warning.js +843 -0
- package/dist/components/lottie-animations/verification-in-progress/verification-in-progress.js +19 -0
- package/dist/components/markdown-content/markdown-content.components.js +114 -0
- package/dist/components/markdown-content/markdown-content.js +39 -0
- package/dist/components/menu/menu.js +19 -0
- package/dist/components/monospace-content/monospace-content.js +80 -0
- package/dist/components/nav-bar/nav-bar-details-panel.js +51 -0
- package/dist/components/nav-bar/nav-bar-mobile-menu.js +105 -0
- package/dist/components/nav-bar/nav-bar.js +449 -0
- package/dist/components/nav-bar/use-nav-bar-overflow.js +74 -0
- package/dist/components/nav-bar/use-nav-bar-scroll.js +42 -0
- package/dist/components/overflow-badge-list/overflow-badge-list.js +58 -0
- package/dist/components/page-container/page-container-skeleton.js +72 -0
- package/dist/components/page-container/page-container.js +93 -0
- package/dist/components/pagination/pagination.js +96 -0
- package/dist/components/pagination/pagination.props.js +16 -0
- package/dist/components/progress-bar/progress-bar.js +106 -0
- package/dist/components/radio-group/radio-group.js +41 -0
- package/dist/components/requirement-list/requirement-list.js +83 -0
- package/dist/components/scrollable-sections/scrollable-sections.js +270 -0
- package/dist/components/search-box/search-box.js +54 -0
- package/dist/components/search-field-shell.js +24 -0
- package/dist/components/selectable-card-list/checkbox-card-list.js +85 -0
- package/dist/components/selectable-card-list/radio-card-list.js +99 -0
- package/dist/components/selectable-card-list/selectable-card-list-shared.js +135 -0
- package/dist/components/selectable-card-list/selectable-card-list.js +34 -0
- package/dist/components/sidebar/sidebar.js +344 -0
- package/dist/components/sidebar/types.js +6 -0
- package/dist/components/simple-clickable-card/simple-clickable-card-shared.js +309 -0
- package/dist/components/simple-clickable-card/simple-clickable-card.js +106 -0
- package/dist/components/simple-info-card/simple-info-card.js +154 -0
- package/dist/components/simple-list/simple-list.js +146 -0
- package/dist/components/simple-paginated-list/simple-paginated-list.js +178 -0
- package/dist/components/simplified-date/simplified-date.js +56 -0
- package/dist/components/skeletons/table-skeleton.js +16 -0
- package/dist/components/spinner/spinner.js +25 -0
- package/dist/components/stat-card/stat-card.js +206 -0
- package/dist/components/status-badge/status-badge.js +108 -0
- package/dist/components/status-card-list/status-card-list.js +282 -0
- package/dist/components/tag/tag.js +144 -0
- package/dist/components/tag-input/tag-input.js +161 -0
- package/dist/components/text-effects/glitch-effect/glitch-text.js +115 -0
- package/dist/components/text-effects/gradient-text/gradient-text.js +32 -0
- package/dist/components/text-effects/highlight-text/highlight-text.js +35 -0
- package/dist/components/text-effects/parse-text-markup.js +53 -0
- package/dist/components/text-effects/shimmer-text/shimmer-text.js +67 -0
- package/dist/components/time-picker/time-picker.js +23 -0
- package/dist/components/toast/toast.js +126 -0
- package/dist/components/togglable-items-list/togglable-items-list.js +28 -0
- package/dist/components/tooltip/tooltip.js +21 -0
- package/dist/components/transfer-list/transfer-list.js +413 -0
- package/dist/components/truncated-line-with-tooltip/truncated-line-with-tooltip.js +61 -0
- package/dist/components/typography/typography-variants.js +41 -0
- package/dist/components/typography/typography.js +15 -0
- package/dist/components/user-type-badge/user-type-badge.js +40 -0
- package/dist/components/user-type-badge/user-type-badge.registry.js +17 -0
- package/dist/components/vertical-stepper/vertical-stepper.js +171 -0
- package/dist/core/alert.js +33 -0
- package/dist/core/animate-ui/components/animate/code-header.js +30 -0
- package/dist/core/animate-ui/components/animate/code.js +35 -0
- package/dist/core/animate-ui/components/animate/tabs.js +188 -0
- package/dist/core/animate-ui/components/animate/tooltip.js +39 -0
- package/dist/core/animate-ui/components/base/preview-card.js +29 -0
- package/dist/core/animate-ui/components/base/progress.js +32 -0
- package/dist/core/animate-ui/components/base/radio.js +24 -0
- package/dist/core/animate-ui/components/buttons/copy.js +95 -0
- package/dist/core/animate-ui/components/radix/accordion.js +36 -0
- package/dist/core/animate-ui/components/radix/dialog.js +60 -0
- package/dist/core/animate-ui/components/radix/dropdown-menu.js +129 -0
- package/dist/core/animate-ui/components/radix/sheet.js +110 -0
- package/dist/core/animate-ui/components/radix/sidebar.js +416 -0
- package/dist/core/animate-ui/components/radix/switch.js +34 -0
- package/dist/core/animate-ui/components/radix/toggle-group.js +115 -0
- package/dist/core/animate-ui/components/radix/toggle.js +24 -0
- package/dist/core/animate-ui/primitives/animate/code-block.js +131 -0
- package/dist/core/animate-ui/primitives/animate/escape-html.js +7 -0
- package/dist/core/animate-ui/primitives/animate/shiki-highlighter.js +64 -0
- package/dist/core/animate-ui/primitives/animate/slot.js +39 -0
- package/dist/core/animate-ui/primitives/animate/tabs.js +202 -0
- package/dist/core/animate-ui/primitives/animate/tooltip.js +351 -0
- package/dist/core/animate-ui/primitives/base/preview-card.js +107 -0
- package/dist/core/animate-ui/primitives/base/progress.js +60 -0
- package/dist/core/animate-ui/primitives/base/radio.js +83 -0
- package/dist/core/animate-ui/primitives/buttons/button.js +16 -0
- package/dist/core/animate-ui/primitives/effects/highlight.js +407 -0
- package/dist/core/animate-ui/primitives/radix/accordion.js +76 -0
- package/dist/core/animate-ui/primitives/radix/dialog.js +136 -0
- package/dist/core/animate-ui/primitives/radix/dropdown-menu.js +305 -0
- package/dist/core/animate-ui/primitives/radix/sheet.js +165 -0
- package/dist/core/animate-ui/primitives/radix/switch.js +86 -0
- package/dist/core/animate-ui/primitives/radix/toggle-group.js +100 -0
- package/dist/core/animate-ui/primitives/texts/counting-number.js +75 -0
- package/dist/core/avatar.js +32 -0
- package/dist/core/badge.js +27 -0
- package/dist/core/breadcrumb.js +62 -0
- package/dist/core/button/button.js +43 -0
- package/dist/core/button/craft-button.js +78 -0
- package/dist/core/button-group.js +38 -0
- package/dist/core/button.js +40 -0
- package/dist/core/card.js +42 -0
- package/dist/core/carousel/carousel.js +149 -0
- package/dist/core/checkbox/motion-checkbox.js +103 -0
- package/dist/core/collapsible.js +54 -0
- package/dist/core/combobox/combobox.js +85 -0
- package/dist/core/command.js +61 -0
- package/dist/core/field-end-icons.js +36 -0
- package/dist/core/field-label-row.js +33 -0
- package/dist/core/form.js +92 -0
- package/dist/core/hooks/use-controlled-state.js +27 -0
- package/dist/core/hooks/use-data-state.js +39 -0
- package/dist/core/hooks/use-is-in-view.js +18 -0
- package/dist/core/hooks/use-mobile.js +19 -0
- package/dist/core/hooks/use-reveal-on-scroll-up.js +141 -0
- package/dist/core/hooks/use-scroll-overflow.js +50 -0
- package/dist/core/index.js +18 -52
- package/dist/core/input/input-password.js +30 -0
- package/dist/core/input/input.js +147 -0
- package/dist/core/input-otp/input-otp.js +183 -0
- package/dist/core/label.js +15 -0
- package/dist/core/popover.js +31 -0
- package/dist/core/scroll-area.js +42 -0
- package/dist/core/select.js +121 -0
- package/dist/core/separator.js +40 -0
- package/dist/core/skeleton.js +11 -0
- package/dist/core/table.js +59 -0
- package/dist/core/textarea/textarea.js +97 -0
- package/dist/core/utils/get-strict-context.js +18 -0
- package/dist/index.js +148 -9
- package/dist/layouts/entry-layout/entry-layout-bg.js +4 -0
- package/dist/layouts/entry-layout/entry-layout.js +52 -0
- package/dist/layouts/index.js +7 -6
- package/dist/layouts/workspace-layout/account-menu/account-menu.js +108 -0
- package/dist/layouts/workspace-layout/breadcrumbs/derive-breadcrumbs.js +37 -0
- package/dist/layouts/workspace-layout/breadcrumbs/workspace-breadcrumbs.js +22 -0
- package/dist/layouts/workspace-layout/footer/footer.js +15 -0
- package/dist/layouts/workspace-layout/header/header.js +54 -0
- package/dist/layouts/workspace-layout/workspace-layout.js +157 -0
- package/dist/tailwind-preset.js +3 -4
- package/dist/utils/cn.js +8 -0
- package/dist/utils/color.js +72 -0
- package/dist/utils/index.js +3 -2
- package/dist/utils/path-match.js +17 -0
- package/dist/utils/silver-shine.js +63 -0
- package/dist/utils/variant-gradient-underlay.js +45 -0
- package/dist/utils/variant.js +426 -0
- package/package.json +7 -4
- package/dist/chunk-2GDYZAKR.js +0 -505
- package/dist/chunk-ALCWXFUC.js +0 -733
- package/dist/chunk-CDHBLANU.js +0 -59
- package/dist/chunk-LUESSJAF.js +0 -70068
- package/dist/chunk-TMORRNEB.js +0 -323
- package/dist/chunk-TRTQSARU.js +0 -31
- package/dist/chunk-VU4CZ76T.js +0 -43
- package/dist/chunk-XNLCVHBC.js +0 -364
- package/dist/chunk-Z4776NRY.js +0 -4347
- package/src/assets/illustrations/add-to-group.svg +0 -32
- package/src/assets/illustrations/chip.svg +0 -51
- package/src/assets/illustrations/create-new-group.svg +0 -27
- package/src/assets/illustrations/new-ota.svg +0 -61
- package/src/assets/illustrations/secured-key.svg +0 -48
- /package/dist/assets/{entry-layout-bg-JPI7GJ42.webp → entry-layout-bg-DUM0UhT3.webp} +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { Checkbox as Checkbox$1, CheckboxIndicator } from "../../_vendor/@radix-ui/react-checkbox/dist/index.js";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { motion } from "motion/react";
|
|
7
|
+
//#region src/core/checkbox/motion-checkbox.tsx
|
|
8
|
+
function getAnimateState(checked) {
|
|
9
|
+
if (checked === "indeterminate") return "indeterminate";
|
|
10
|
+
return checked ? "checked" : "unchecked";
|
|
11
|
+
}
|
|
12
|
+
function Checkbox({ className, onCheckedChange, ...props }) {
|
|
13
|
+
const [checkedState, setCheckedState] = React$1.useState(props?.checked ?? props?.defaultChecked ?? false);
|
|
14
|
+
React$1.useEffect(() => {
|
|
15
|
+
if (props?.checked !== void 0) setCheckedState(props.checked);
|
|
16
|
+
}, [props?.checked]);
|
|
17
|
+
const handleCheckedChange = React$1.useCallback((checked) => {
|
|
18
|
+
setCheckedState(checked);
|
|
19
|
+
onCheckedChange?.(checked);
|
|
20
|
+
}, [onCheckedChange]);
|
|
21
|
+
const animateState = getAnimateState(checkedState);
|
|
22
|
+
return /* @__PURE__ */ jsx("span", {
|
|
23
|
+
className: "relative inline-flex shrink-0",
|
|
24
|
+
children: /* @__PURE__ */ jsx(Checkbox$1, {
|
|
25
|
+
...props,
|
|
26
|
+
onCheckedChange: handleCheckedChange,
|
|
27
|
+
asChild: true,
|
|
28
|
+
children: /* @__PURE__ */ jsx(motion.button, {
|
|
29
|
+
"data-slot": "checkbox",
|
|
30
|
+
className: cn("peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-colors duration-500 outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
31
|
+
whileTap: { scale: .95 },
|
|
32
|
+
whileHover: { scale: 1.05 },
|
|
33
|
+
...props,
|
|
34
|
+
children: /* @__PURE__ */ jsx(CheckboxIndicator, {
|
|
35
|
+
forceMount: true,
|
|
36
|
+
asChild: true,
|
|
37
|
+
children: /* @__PURE__ */ jsxs(motion.svg, {
|
|
38
|
+
"data-slot": "checkbox-indicator",
|
|
39
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
40
|
+
fill: "none",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
strokeWidth: "3.5",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
className: "size-3.5",
|
|
45
|
+
initial: "unchecked",
|
|
46
|
+
animate: animateState,
|
|
47
|
+
children: [/* @__PURE__ */ jsx(motion.path, {
|
|
48
|
+
strokeLinecap: "round",
|
|
49
|
+
strokeLinejoin: "round",
|
|
50
|
+
d: "M4.5 12.75l6 6 9-13.5",
|
|
51
|
+
variants: {
|
|
52
|
+
checked: {
|
|
53
|
+
pathLength: 1,
|
|
54
|
+
opacity: 1,
|
|
55
|
+
transition: {
|
|
56
|
+
duration: .2,
|
|
57
|
+
delay: .2
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
unchecked: {
|
|
61
|
+
pathLength: 0,
|
|
62
|
+
opacity: 0,
|
|
63
|
+
transition: { duration: .2 }
|
|
64
|
+
},
|
|
65
|
+
indeterminate: {
|
|
66
|
+
pathLength: 0,
|
|
67
|
+
opacity: 0,
|
|
68
|
+
transition: { duration: .15 }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}), /* @__PURE__ */ jsx(motion.path, {
|
|
72
|
+
strokeLinecap: "round",
|
|
73
|
+
strokeLinejoin: "round",
|
|
74
|
+
d: "M5 12h14",
|
|
75
|
+
variants: {
|
|
76
|
+
checked: {
|
|
77
|
+
pathLength: 0,
|
|
78
|
+
opacity: 0,
|
|
79
|
+
transition: { duration: .15 }
|
|
80
|
+
},
|
|
81
|
+
unchecked: {
|
|
82
|
+
pathLength: 0,
|
|
83
|
+
opacity: 0,
|
|
84
|
+
transition: { duration: .15 }
|
|
85
|
+
},
|
|
86
|
+
indeterminate: {
|
|
87
|
+
pathLength: 1,
|
|
88
|
+
opacity: 1,
|
|
89
|
+
transition: {
|
|
90
|
+
duration: .2,
|
|
91
|
+
delay: .15
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
})]
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { Checkbox };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../utils/cn.js";
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
6
|
+
//#region src/core/collapsible.tsx
|
|
7
|
+
var Collapsible = CollapsiblePrimitive.Root;
|
|
8
|
+
var CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
|
9
|
+
/**
|
|
10
|
+
* Animated container that holds the collapsible body.
|
|
11
|
+
*
|
|
12
|
+
* Lifecycle (inherited from Radix `@radix-ui/react-collapsible`):
|
|
13
|
+
* - While the parent `Collapsible` is closed and `forceMount` is unset, the
|
|
14
|
+
* subtree is gated by Radix's `Presence` and `isOpen && children`, so it is
|
|
15
|
+
* never rendered into the DOM. `useEffect`/`useQuery`/etc. inside it do not
|
|
16
|
+
* fire.
|
|
17
|
+
* - On first expand, the subtree mounts and effects fire.
|
|
18
|
+
* - On collapse, the subtree unmounts after the close animation. On the next
|
|
19
|
+
* expand it remounts, so any data-fetching effect runs again. Cache at the
|
|
20
|
+
* data layer (e.g. React Query) if you need to avoid refetching per toggle.
|
|
21
|
+
*
|
|
22
|
+
* Footgun — JSX eager evaluation:
|
|
23
|
+
* Any synchronous expression placed directly as a child of `CollapsibleContent`
|
|
24
|
+
* is evaluated by the parent during its own render, before Radix sees it. No
|
|
25
|
+
* collapsible primitive can prevent this. Wrap fetching/expensive work inside
|
|
26
|
+
* a component so its effects fire on mount.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Safe: DeviceDetails only mounts when expanded, so its fetch only runs then.
|
|
30
|
+
* <CollapsibleContent>
|
|
31
|
+
* <DeviceDetails id={id} />
|
|
32
|
+
* </CollapsibleContent>
|
|
33
|
+
*
|
|
34
|
+
* // Unsafe: fetchData(id) runs on every parent render for every card,
|
|
35
|
+
* // regardless of open state.
|
|
36
|
+
* <CollapsibleContent>
|
|
37
|
+
* {fetchData(id)}
|
|
38
|
+
* </CollapsibleContent>
|
|
39
|
+
*
|
|
40
|
+
* Pass `forceMount` if you explicitly need the subtree mounted while closed
|
|
41
|
+
* (e.g. SEO crawlers, layout measurement).
|
|
42
|
+
*/
|
|
43
|
+
var CollapsibleContent = React$1.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleContent, {
|
|
44
|
+
ref,
|
|
45
|
+
className: "grid data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up",
|
|
46
|
+
...props,
|
|
47
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
48
|
+
className: cn("overflow-hidden", className),
|
|
49
|
+
children
|
|
50
|
+
})
|
|
51
|
+
}));
|
|
52
|
+
CollapsibleContent.displayName = "CollapsibleContent";
|
|
53
|
+
//#endregion
|
|
54
|
+
export { Collapsible, CollapsibleContent, CollapsibleTrigger };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../popover.js";
|
|
4
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "../command.js";
|
|
5
|
+
import * as React$1 from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Check, ChevronsUpDown } from "lucide-react";
|
|
8
|
+
//#region src/core/combobox/combobox.tsx
|
|
9
|
+
function AsyncCombobox({ value, onValueChange, options, onSearchChange, isLoading = false, placeholder = "Select...", emptyText = "No results.", searchPlaceholder = "Search...", label, required, disabled, className, clearable = false, hasMore = false, onLoadMore }) {
|
|
10
|
+
const [open, setOpen] = React$1.useState(false);
|
|
11
|
+
const [inputValue, setInputValue] = React$1.useState("");
|
|
12
|
+
const displayValue = options.find((o) => o.value === value)?.label ?? (value || "");
|
|
13
|
+
const handleSelect = (selected) => {
|
|
14
|
+
onValueChange?.(value === selected && clearable ? void 0 : selected);
|
|
15
|
+
if (!clearable) setOpen(false);
|
|
16
|
+
};
|
|
17
|
+
const handleSearchChange = React$1.useCallback((q) => {
|
|
18
|
+
setInputValue(q);
|
|
19
|
+
onSearchChange?.(q);
|
|
20
|
+
}, [onSearchChange]);
|
|
21
|
+
const trigger = /* @__PURE__ */ jsxs("button", {
|
|
22
|
+
type: "button",
|
|
23
|
+
role: "combobox",
|
|
24
|
+
"aria-expanded": open,
|
|
25
|
+
disabled,
|
|
26
|
+
className: cn("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background transition-[box-shadow,border-color] duration-200 ease-in-out placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", !displayValue && "text-muted-foreground", className),
|
|
27
|
+
onClick: () => setOpen(!open),
|
|
28
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
29
|
+
className: "truncate",
|
|
30
|
+
children: displayValue || placeholder
|
|
31
|
+
}), /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })]
|
|
32
|
+
});
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "space-y-2 flex-1",
|
|
35
|
+
children: [label != null && /* @__PURE__ */ jsx("div", {
|
|
36
|
+
className: "flex items-center justify-between",
|
|
37
|
+
children: /* @__PURE__ */ jsxs("label", {
|
|
38
|
+
className: "flex items-center gap-2 text-sm leading-none font-medium select-none",
|
|
39
|
+
children: [label, required && /* @__PURE__ */ jsx("span", {
|
|
40
|
+
className: "text-destructive",
|
|
41
|
+
children: "*"
|
|
42
|
+
})]
|
|
43
|
+
})
|
|
44
|
+
}), /* @__PURE__ */ jsxs(Popover, {
|
|
45
|
+
open,
|
|
46
|
+
onOpenChange: setOpen,
|
|
47
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
48
|
+
asChild: true,
|
|
49
|
+
children: trigger
|
|
50
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
51
|
+
className: "w-[var(--radix-popover-trigger-width)] p-0",
|
|
52
|
+
align: "start",
|
|
53
|
+
children: /* @__PURE__ */ jsxs(Command, {
|
|
54
|
+
shouldFilter: false,
|
|
55
|
+
children: [/* @__PURE__ */ jsx(CommandInput, {
|
|
56
|
+
placeholder: searchPlaceholder,
|
|
57
|
+
value: inputValue,
|
|
58
|
+
onValueChange: handleSearchChange
|
|
59
|
+
}), /* @__PURE__ */ jsxs(CommandList, { children: [
|
|
60
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
61
|
+
className: "flex items-center justify-center py-6",
|
|
62
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-4 border-primary border-t-transparent" })
|
|
63
|
+
}) : emptyText }),
|
|
64
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: options.map((opt) => /* @__PURE__ */ jsxs(CommandItem, {
|
|
65
|
+
value: opt.value,
|
|
66
|
+
onSelect: () => handleSelect(opt.value),
|
|
67
|
+
children: [/* @__PURE__ */ jsx(Check, { className: cn("mr-2 h-4 w-4", value === opt.value ? "opacity-100" : "opacity-0") }), opt.label]
|
|
68
|
+
}, opt.value)) }),
|
|
69
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx("div", {
|
|
70
|
+
className: "border-t p-2",
|
|
71
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
72
|
+
type: "button",
|
|
73
|
+
className: "text-sm text-primary hover:underline w-full text-center",
|
|
74
|
+
onClick: () => onLoadMore(),
|
|
75
|
+
children: "Load more"
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
] })]
|
|
79
|
+
})
|
|
80
|
+
})]
|
|
81
|
+
})]
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { AsyncCombobox };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { cn } from "../utils/cn.js";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Search } from "lucide-react";
|
|
5
|
+
import { Command } from "cmdk";
|
|
6
|
+
//#region src/core/command.tsx
|
|
7
|
+
var Command$1 = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command, {
|
|
8
|
+
ref,
|
|
9
|
+
className: cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className),
|
|
10
|
+
...props
|
|
11
|
+
}));
|
|
12
|
+
Command$1.displayName = Command.displayName;
|
|
13
|
+
var CommandInput = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", {
|
|
14
|
+
className: "flex items-center border-b px-3",
|
|
15
|
+
"cmdk-input-wrapper": "",
|
|
16
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }), /* @__PURE__ */ jsx(Command.Input, {
|
|
17
|
+
ref,
|
|
18
|
+
className: cn("flex h-10 w-full rounded-md bg-transparent py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
19
|
+
...props
|
|
20
|
+
})]
|
|
21
|
+
}));
|
|
22
|
+
CommandInput.displayName = Command.Input.displayName;
|
|
23
|
+
var CommandList = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.List, {
|
|
24
|
+
ref,
|
|
25
|
+
className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
|
|
26
|
+
...props
|
|
27
|
+
}));
|
|
28
|
+
CommandList.displayName = Command.List.displayName;
|
|
29
|
+
var CommandEmpty = React$1.forwardRef((props, ref) => /* @__PURE__ */ jsx(Command.Empty, {
|
|
30
|
+
ref,
|
|
31
|
+
className: "py-6 text-center text-sm",
|
|
32
|
+
...props
|
|
33
|
+
}));
|
|
34
|
+
CommandEmpty.displayName = Command.Empty.displayName;
|
|
35
|
+
var CommandGroup = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Group, {
|
|
36
|
+
ref,
|
|
37
|
+
className: cn("overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", className),
|
|
38
|
+
...props
|
|
39
|
+
}));
|
|
40
|
+
CommandGroup.displayName = Command.Group.displayName;
|
|
41
|
+
var CommandSeparator = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Separator, {
|
|
42
|
+
ref,
|
|
43
|
+
className: cn("-mx-1 h-px bg-border", className),
|
|
44
|
+
...props
|
|
45
|
+
}));
|
|
46
|
+
CommandSeparator.displayName = Command.Separator.displayName;
|
|
47
|
+
var CommandItem = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Item, {
|
|
48
|
+
ref,
|
|
49
|
+
className: cn("relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", className),
|
|
50
|
+
...props
|
|
51
|
+
}));
|
|
52
|
+
CommandItem.displayName = Command.Item.displayName;
|
|
53
|
+
var CommandShortcut = ({ className, ...props }) => {
|
|
54
|
+
return /* @__PURE__ */ jsx("span", {
|
|
55
|
+
className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className),
|
|
56
|
+
...props
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
CommandShortcut.displayName = "CommandShortcut";
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Command$1 as Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { cn } from "../utils/cn.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { XIcon } from "lucide-react";
|
|
5
|
+
//#region src/core/field-end-icons.tsx
|
|
6
|
+
/** Every decorator inside an `Input` end slot renders at this size. */
|
|
7
|
+
var FIELD_ICON_SIZE = 16;
|
|
8
|
+
/**
|
|
9
|
+
* Trailing content for an `Input` `endIcon` slot: an optional clear button
|
|
10
|
+
* followed by an optional decorative icon, both 16px and inline, so a
|
|
11
|
+
* clearable field keeps the same layout whether or not it has a value. The
|
|
12
|
+
* slot itself is `pointer-events-none`; the button opts back in.
|
|
13
|
+
*/
|
|
14
|
+
function FieldEndIcons({ icon, onClear, clearLabel = "Clear", className }) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
16
|
+
className: cn("flex items-center gap-1.5", className),
|
|
17
|
+
children: [onClear && /* @__PURE__ */ jsx("button", {
|
|
18
|
+
type: "button",
|
|
19
|
+
"aria-label": clearLabel,
|
|
20
|
+
onClick: onClear,
|
|
21
|
+
className: "pointer-events-auto rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
22
|
+
children: /* @__PURE__ */ jsx(XIcon, {
|
|
23
|
+
size: FIELD_ICON_SIZE,
|
|
24
|
+
"aria-hidden": true
|
|
25
|
+
})
|
|
26
|
+
}), icon]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Input padding-end that leaves room for one or two 16px end icons. */
|
|
30
|
+
function fieldEndPaddingClassName(hasClear, hasIcon) {
|
|
31
|
+
if (hasClear && hasIcon) return "pe-16";
|
|
32
|
+
if (hasClear || hasIcon) return "pe-9";
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { FIELD_ICON_SIZE, FieldEndIcons, fieldEndPaddingClassName };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { cn } from "../utils/cn.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/core/field-label-row.tsx
|
|
5
|
+
/** Shared with `MonospaceContent` and any other UI that should match non-floating field labels. */
|
|
6
|
+
var inputLabelClassName = "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50";
|
|
7
|
+
/** Hint text placed at the end of a label row. `leading-none` keeps the row 14px tall like the label. */
|
|
8
|
+
var fieldHintClassName = "text-sm leading-none text-muted-foreground";
|
|
9
|
+
/**
|
|
10
|
+
* The label row every enhanced form control shares (`Input`, `Textarea`,
|
|
11
|
+
* `SelectTrigger`, the date pickers): label with an optional required
|
|
12
|
+
* marker on the left, optional hint on the right, one line of `text-sm`
|
|
13
|
+
* at `leading-none`. Rendering it from one place keeps the distance
|
|
14
|
+
* between label text and control identical across control types.
|
|
15
|
+
*/
|
|
16
|
+
function FieldLabelRow({ htmlFor, label, required = false, hintContent, className }) {
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
18
|
+
className: cn("flex items-end justify-between gap-2", className),
|
|
19
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
20
|
+
htmlFor,
|
|
21
|
+
className: cn(inputLabelClassName, "shrink-0 whitespace-nowrap"),
|
|
22
|
+
children: [label, required && /* @__PURE__ */ jsx("span", {
|
|
23
|
+
className: "text-destructive",
|
|
24
|
+
children: "*"
|
|
25
|
+
})]
|
|
26
|
+
}), hintContent && /* @__PURE__ */ jsx("span", {
|
|
27
|
+
className: cn(fieldHintClassName, "min-w-0 text-end"),
|
|
28
|
+
children: hintContent
|
|
29
|
+
})]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { FieldLabelRow, fieldHintClassName, inputLabelClassName };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../utils/cn.js";
|
|
3
|
+
import { Label } from "./label.js";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
7
|
+
import { Controller, FormProvider, useFormContext } from "react-hook-form";
|
|
8
|
+
//#region src/core/form.tsx
|
|
9
|
+
var Form = FormProvider;
|
|
10
|
+
var FormFieldContext = React$1.createContext(null);
|
|
11
|
+
var FormField = ({ ...props }) => {
|
|
12
|
+
return /* @__PURE__ */ jsx(FormFieldContext.Provider, {
|
|
13
|
+
value: { name: props.name },
|
|
14
|
+
children: /* @__PURE__ */ jsx(Controller, { ...props })
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var useFormField = () => {
|
|
18
|
+
const fieldContext = React$1.useContext(FormFieldContext);
|
|
19
|
+
const itemContext = React$1.useContext(FormItemContext);
|
|
20
|
+
const { getFieldState, formState } = useFormContext();
|
|
21
|
+
if (!fieldContext) throw new Error("useFormField should be used within <FormField>");
|
|
22
|
+
if (!itemContext) throw new Error("useFormField should be used within <FormItem>");
|
|
23
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
24
|
+
const { id } = itemContext;
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
name: fieldContext.name,
|
|
28
|
+
formItemId: `${id}-form-item`,
|
|
29
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
30
|
+
formMessageId: `${id}-form-item-message`,
|
|
31
|
+
...fieldState
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
var FormItemContext = React$1.createContext(null);
|
|
35
|
+
var FormItem = React$1.forwardRef(({ className, ...props }, ref) => {
|
|
36
|
+
const id = React$1.useId();
|
|
37
|
+
return /* @__PURE__ */ jsx(FormItemContext.Provider, {
|
|
38
|
+
value: { id },
|
|
39
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
40
|
+
ref,
|
|
41
|
+
className: cn("space-y-2", className),
|
|
42
|
+
...props
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
FormItem.displayName = "FormItem";
|
|
47
|
+
var FormLabel = React$1.forwardRef(({ className, ...props }, ref) => {
|
|
48
|
+
const { error, formItemId } = useFormField();
|
|
49
|
+
return /* @__PURE__ */ jsx(Label, {
|
|
50
|
+
ref,
|
|
51
|
+
className: cn("flex items-center gap-2", error && "text-destructive", className),
|
|
52
|
+
htmlFor: formItemId,
|
|
53
|
+
...props
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
FormLabel.displayName = "FormLabel";
|
|
57
|
+
var FormControl = React$1.forwardRef(({ ...props }, ref) => {
|
|
58
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
59
|
+
return /* @__PURE__ */ jsx(Slot, {
|
|
60
|
+
ref,
|
|
61
|
+
id: formItemId,
|
|
62
|
+
"aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
|
|
63
|
+
"aria-invalid": !!error,
|
|
64
|
+
...props
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
FormControl.displayName = "FormControl";
|
|
68
|
+
var FormDescription = React$1.forwardRef(({ className, ...props }, ref) => {
|
|
69
|
+
const { formDescriptionId } = useFormField();
|
|
70
|
+
return /* @__PURE__ */ jsx("p", {
|
|
71
|
+
ref,
|
|
72
|
+
id: formDescriptionId,
|
|
73
|
+
className: cn("text-[0.8rem] text-muted-foreground", className),
|
|
74
|
+
...props
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
FormDescription.displayName = "FormDescription";
|
|
78
|
+
var FormMessage = React$1.forwardRef(({ className, children, ...props }, ref) => {
|
|
79
|
+
const { error, formMessageId } = useFormField();
|
|
80
|
+
const body = error ? String(error?.message ?? "") : children;
|
|
81
|
+
if (!body) return null;
|
|
82
|
+
return /* @__PURE__ */ jsx("p", {
|
|
83
|
+
ref,
|
|
84
|
+
id: formMessageId,
|
|
85
|
+
className: cn("text-[0.8rem] font-medium text-destructive", className),
|
|
86
|
+
...props,
|
|
87
|
+
children: body
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
FormMessage.displayName = "FormMessage";
|
|
91
|
+
//#endregion
|
|
92
|
+
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
//#region src/core/hooks/use-controlled-state.tsx
|
|
3
|
+
/**
|
|
4
|
+
* Controlled / uncontrolled state pair with React's usual semantics: while
|
|
5
|
+
* `value` is defined the hook reports exactly that value and the setter only
|
|
6
|
+
* notifies `onChange`; the owner decides whether the change takes effect.
|
|
7
|
+
* Without `value` the hook owns the state, seeded from `defaultValue`.
|
|
8
|
+
*
|
|
9
|
+
* The internal copy still tracks a controlled `value` so a component that
|
|
10
|
+
* later drops `value` keeps the last controlled state instead of snapping
|
|
11
|
+
* back to `defaultValue`.
|
|
12
|
+
*/
|
|
13
|
+
function useControlledState(props) {
|
|
14
|
+
const { value, defaultValue, onChange } = props;
|
|
15
|
+
const isControlled = value !== void 0;
|
|
16
|
+
const [internalState, setInternalState] = React$1.useState(isControlled ? value : defaultValue);
|
|
17
|
+
React$1.useEffect(() => {
|
|
18
|
+
if (isControlled) setInternalState(value);
|
|
19
|
+
}, [isControlled, value]);
|
|
20
|
+
const setState = React$1.useCallback((next, ...args) => {
|
|
21
|
+
if (!isControlled) setInternalState(next);
|
|
22
|
+
onChange?.(next, ...args);
|
|
23
|
+
}, [isControlled, onChange]);
|
|
24
|
+
return [isControlled ? value : internalState, setState];
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { useControlledState };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
//#region src/core/hooks/use-data-state.tsx
|
|
4
|
+
function parseDatasetValue(value) {
|
|
5
|
+
if (value === null) return null;
|
|
6
|
+
if (value === "" || value === "true") return true;
|
|
7
|
+
if (value === "false") return false;
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function useDataState(key, forwardedRef, onChange) {
|
|
11
|
+
const localRef = React$1.useRef(null);
|
|
12
|
+
React$1.useImperativeHandle(forwardedRef, () => localRef.current);
|
|
13
|
+
const getSnapshot = () => {
|
|
14
|
+
const el = localRef.current;
|
|
15
|
+
return el ? parseDatasetValue(el.getAttribute(`data-${key}`)) : null;
|
|
16
|
+
};
|
|
17
|
+
const subscribe = (callback) => {
|
|
18
|
+
const el = localRef.current;
|
|
19
|
+
if (!el) return () => {};
|
|
20
|
+
const observer = new MutationObserver((records) => {
|
|
21
|
+
for (const record of records) if (record.attributeName === `data-${key}`) {
|
|
22
|
+
callback();
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
observer.observe(el, {
|
|
27
|
+
attributes: true,
|
|
28
|
+
attributeFilter: [`data-${key}`]
|
|
29
|
+
});
|
|
30
|
+
return () => observer.disconnect();
|
|
31
|
+
};
|
|
32
|
+
const value = React$1.useSyncExternalStore(subscribe, getSnapshot);
|
|
33
|
+
React$1.useEffect(() => {
|
|
34
|
+
if (onChange) onChange(value);
|
|
35
|
+
}, [value, onChange]);
|
|
36
|
+
return [value, localRef];
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { useDataState };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
import { useInView } from "motion/react";
|
|
3
|
+
//#region src/core/hooks/use-is-in-view.tsx
|
|
4
|
+
function useIsInView(ref, options = {}) {
|
|
5
|
+
const { inView, inViewOnce = false, inViewMargin = "0px" } = options;
|
|
6
|
+
const localRef = React$1.useRef(null);
|
|
7
|
+
React$1.useImperativeHandle(ref, () => localRef.current);
|
|
8
|
+
const inViewResult = useInView(localRef, {
|
|
9
|
+
once: inViewOnce,
|
|
10
|
+
margin: inViewMargin
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ref: localRef,
|
|
14
|
+
isInView: !inView || inViewResult
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useIsInView };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
//#region src/core/hooks/use-mobile.tsx
|
|
3
|
+
var MOBILE_BREAKPOINT = 768;
|
|
4
|
+
var MOBILE_MEDIA_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`;
|
|
5
|
+
function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React$1.useState(void 0);
|
|
7
|
+
React$1.useEffect(() => {
|
|
8
|
+
const mql = window.matchMedia(MOBILE_MEDIA_QUERY);
|
|
9
|
+
const onChange = () => {
|
|
10
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
11
|
+
};
|
|
12
|
+
mql.addEventListener("change", onChange);
|
|
13
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
14
|
+
return () => mql.removeEventListener("change", onChange);
|
|
15
|
+
}, []);
|
|
16
|
+
return !!isMobile;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { MOBILE_BREAKPOINT, MOBILE_MEDIA_QUERY, useIsMobile };
|