@nikala-ui/folio 0.13.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 +20 -0
- package/README.md +221 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +28 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +33 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +359 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/preview.d.ts +7 -0
- package/dist/cli/commands/preview.d.ts.map +1 -0
- package/dist/cli/commands/preview.js +25 -0
- package/dist/cli/commands/preview.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +7 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +34 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +55 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/app-types.d.ts +18 -0
- package/dist/client/app-types.d.ts.map +1 -0
- package/dist/client/app-types.js +2 -0
- package/dist/client/app-types.js.map +1 -0
- package/dist/client/app.d.ts +5 -0
- package/dist/client/app.d.ts.map +1 -0
- package/dist/client/app.jsx +51 -0
- package/dist/client/app.jsx.map +1 -0
- package/dist/client/base.css +90 -0
- package/dist/client/components/docs-layout-shell.d.ts +23 -0
- package/dist/client/components/docs-layout-shell.d.ts.map +1 -0
- package/dist/client/components/docs-layout-shell.jsx +15 -0
- package/dist/client/components/docs-layout-shell.jsx.map +1 -0
- package/dist/client/components/docs-page-content.d.ts +9 -0
- package/dist/client/components/docs-page-content.d.ts.map +1 -0
- package/dist/client/components/docs-page-content.jsx +10 -0
- package/dist/client/components/docs-page-content.jsx.map +1 -0
- package/dist/client/entry.d.ts +2 -0
- package/dist/client/entry.d.ts.map +1 -0
- package/dist/client/entry.jsx +32 -0
- package/dist/client/entry.jsx.map +1 -0
- package/dist/client/index.html +23 -0
- package/dist/client/navigation/page-navigation.d.ts +9 -0
- package/dist/client/navigation/page-navigation.d.ts.map +1 -0
- package/dist/client/navigation/page-navigation.js +51 -0
- package/dist/client/navigation/page-navigation.js.map +1 -0
- package/dist/client/page-actions.d.ts +10 -0
- package/dist/client/page-actions.d.ts.map +1 -0
- package/dist/client/page-actions.js +63 -0
- package/dist/client/page-actions.js.map +1 -0
- package/dist/client/public/favicon.ico +0 -0
- package/dist/client/routing/use-docs-router.d.ts +17 -0
- package/dist/client/routing/use-docs-router.d.ts.map +1 -0
- package/dist/client/routing/use-docs-router.js +87 -0
- package/dist/client/routing/use-docs-router.js.map +1 -0
- package/dist/client/ssr-entry.d.ts +3 -0
- package/dist/client/ssr-entry.d.ts.map +1 -0
- package/dist/client/ssr-entry.jsx +13 -0
- package/dist/client/ssr-entry.jsx.map +1 -0
- package/dist/client/style.css +186 -0
- package/dist/client/utils/sidebar.d.ts +2 -0
- package/dist/client/utils/sidebar.d.ts.map +1 -0
- package/dist/client/utils/sidebar.js +2 -0
- package/dist/client/utils/sidebar.js.map +1 -0
- package/dist/components/mdx-components.d.ts +65 -0
- package/dist/components/mdx-components.d.ts.map +1 -0
- package/dist/components/mdx-components.jsx +133 -0
- package/dist/components/mdx-components.jsx.map +1 -0
- package/dist/components/ui/api-table.d.ts +29 -0
- package/dist/components/ui/api-table.d.ts.map +1 -0
- package/dist/components/ui/api-table.jsx +66 -0
- package/dist/components/ui/api-table.jsx.map +1 -0
- package/dist/components/ui/badge.d.ts +17 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.jsx +33 -0
- package/dist/components/ui/badge.jsx.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +51 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.jsx +62 -0
- package/dist/components/ui/breadcrumb.jsx.map +1 -0
- package/dist/components/ui/button.d.ts +19 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.jsx +54 -0
- package/dist/components/ui/button.jsx.map +1 -0
- package/dist/components/ui/callout.d.ts +21 -0
- package/dist/components/ui/callout.d.ts.map +1 -0
- package/dist/components/ui/callout.jsx +76 -0
- package/dist/components/ui/callout.jsx.map +1 -0
- package/dist/components/ui/card.d.ts +44 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.jsx +45 -0
- package/dist/components/ui/card.jsx.map +1 -0
- package/dist/components/ui/code-block.d.ts +23 -0
- package/dist/components/ui/code-block.d.ts.map +1 -0
- package/dist/components/ui/code-block.jsx +263 -0
- package/dist/components/ui/code-block.jsx.map +1 -0
- package/dist/components/ui/collapsible.d.ts +27 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.jsx +29 -0
- package/dist/components/ui/collapsible.jsx.map +1 -0
- package/dist/components/ui/command.d.ts +57 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.jsx +224 -0
- package/dist/components/ui/command.jsx.map +1 -0
- package/dist/components/ui/component-viewer.d.ts +33 -0
- package/dist/components/ui/component-viewer.d.ts.map +1 -0
- package/dist/components/ui/component-viewer.jsx +210 -0
- package/dist/components/ui/component-viewer.jsx.map +1 -0
- package/dist/components/ui/container.d.ts +13 -0
- package/dist/components/ui/container.d.ts.map +1 -0
- package/dist/components/ui/container.jsx +29 -0
- package/dist/components/ui/container.jsx.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +58 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.jsx +112 -0
- package/dist/components/ui/dropdown-menu.jsx.map +1 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group.jsx +33 -0
- package/dist/components/ui/input-group.jsx.map +1 -0
- package/dist/components/ui/kbd.d.ts +15 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.jsx +42 -0
- package/dist/components/ui/kbd.jsx.map +1 -0
- package/dist/components/ui/list.d.ts +36 -0
- package/dist/components/ui/list.d.ts.map +1 -0
- package/dist/components/ui/list.jsx +131 -0
- package/dist/components/ui/list.jsx.map +1 -0
- package/dist/components/ui/logo.d.ts +9 -0
- package/dist/components/ui/logo.d.ts.map +1 -0
- package/dist/components/ui/logo.jsx +31 -0
- package/dist/components/ui/logo.jsx.map +1 -0
- package/dist/components/ui/navbar.d.ts +57 -0
- package/dist/components/ui/navbar.d.ts.map +1 -0
- package/dist/components/ui/navbar.jsx +174 -0
- package/dist/components/ui/navbar.jsx.map +1 -0
- package/dist/components/ui/package-manager-tabs.d.ts +21 -0
- package/dist/components/ui/package-manager-tabs.d.ts.map +1 -0
- package/dist/components/ui/package-manager-tabs.jsx +167 -0
- package/dist/components/ui/package-manager-tabs.jsx.map +1 -0
- package/dist/components/ui/pager.d.ts +27 -0
- package/dist/components/ui/pager.d.ts.map +1 -0
- package/dist/components/ui/pager.jsx +50 -0
- package/dist/components/ui/pager.jsx.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +9 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.jsx +160 -0
- package/dist/components/ui/scroll-area.jsx.map +1 -0
- package/dist/components/ui/section-heading.d.ts +23 -0
- package/dist/components/ui/section-heading.d.ts.map +1 -0
- package/dist/components/ui/section-heading.jsx +82 -0
- package/dist/components/ui/section-heading.jsx.map +1 -0
- package/dist/components/ui/separator.d.ts +13 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.jsx +16 -0
- package/dist/components/ui/separator.jsx.map +1 -0
- package/dist/components/ui/sidebar.d.ts +103 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.jsx +315 -0
- package/dist/components/ui/sidebar.jsx.map +1 -0
- package/dist/components/ui/skeleton.d.ts +9 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.jsx +11 -0
- package/dist/components/ui/skeleton.jsx.map +1 -0
- package/dist/components/ui/spinner.d.ts +11 -0
- package/dist/components/ui/spinner.d.ts.map +1 -0
- package/dist/components/ui/spinner.jsx +21 -0
- package/dist/components/ui/spinner.jsx.map +1 -0
- package/dist/components/ui/table-of-contents.d.ts +20 -0
- package/dist/components/ui/table-of-contents.d.ts.map +1 -0
- package/dist/components/ui/table-of-contents.jsx +77 -0
- package/dist/components/ui/table-of-contents.jsx.map +1 -0
- package/dist/components/ui/table.d.ts +58 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.jsx +61 -0
- package/dist/components/ui/table.jsx.map +1 -0
- package/dist/components/ui/tabs.d.ts +42 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.jsx +93 -0
- package/dist/components/ui/tabs.jsx.map +1 -0
- package/dist/components/ui/theme-toggle.d.ts +19 -0
- package/dist/components/ui/theme-toggle.d.ts.map +1 -0
- package/dist/components/ui/theme-toggle.jsx +142 -0
- package/dist/components/ui/theme-toggle.jsx.map +1 -0
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.jsx +18 -0
- package/dist/components/ui/tooltip.jsx.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/core/content-scanner.d.ts +10 -0
- package/dist/core/content-scanner.d.ts.map +1 -0
- package/dist/core/content-scanner.js +218 -0
- package/dist/core/content-scanner.js.map +1 -0
- package/dist/core/route-tree.d.ts +24 -0
- package/dist/core/route-tree.d.ts.map +1 -0
- package/dist/core/route-tree.js +221 -0
- package/dist/core/route-tree.js.map +1 -0
- package/dist/hooks/create-click-outside.d.ts +18 -0
- package/dist/hooks/create-click-outside.d.ts.map +1 -0
- package/dist/hooks/create-click-outside.js +55 -0
- package/dist/hooks/create-click-outside.js.map +1 -0
- package/dist/hooks/create-clipboard.d.ts +20 -0
- package/dist/hooks/create-clipboard.d.ts.map +1 -0
- package/dist/hooks/create-clipboard.js +48 -0
- package/dist/hooks/create-clipboard.js.map +1 -0
- package/dist/hooks/create-color-mode.d.ts +27 -0
- package/dist/hooks/create-color-mode.d.ts.map +1 -0
- package/dist/hooks/create-color-mode.js +86 -0
- package/dist/hooks/create-color-mode.js.map +1 -0
- package/dist/hooks/create-controllable-signal.d.ts +17 -0
- package/dist/hooks/create-controllable-signal.d.ts.map +1 -0
- package/dist/hooks/create-controllable-signal.js +35 -0
- package/dist/hooks/create-controllable-signal.js.map +1 -0
- package/dist/hooks/create-focus-trap.d.ts +15 -0
- package/dist/hooks/create-focus-trap.d.ts.map +1 -0
- package/dist/hooks/create-focus-trap.js +72 -0
- package/dist/hooks/create-focus-trap.js.map +1 -0
- package/dist/hooks/create-keybindings.d.ts +34 -0
- package/dist/hooks/create-keybindings.d.ts.map +1 -0
- package/dist/hooks/create-keybindings.js +113 -0
- package/dist/hooks/create-keybindings.js.map +1 -0
- package/dist/hooks/create-lock-scroll.d.ts +20 -0
- package/dist/hooks/create-lock-scroll.d.ts.map +1 -0
- package/dist/hooks/create-lock-scroll.js +77 -0
- package/dist/hooks/create-lock-scroll.js.map +1 -0
- package/dist/hooks/create-resize-observer.d.ts +27 -0
- package/dist/hooks/create-resize-observer.d.ts.map +1 -0
- package/dist/hooks/create-resize-observer.js +59 -0
- package/dist/hooks/create-resize-observer.js.map +1 -0
- package/dist/hooks/create-scroll-position.d.ts +29 -0
- package/dist/hooks/create-scroll-position.d.ts.map +1 -0
- package/dist/hooks/create-scroll-position.js +101 -0
- package/dist/hooks/create-scroll-position.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cn.d.ts +6 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/mdx/compiler.d.ts +13 -0
- package/dist/mdx/compiler.d.ts.map +1 -0
- package/dist/mdx/compiler.js +38 -0
- package/dist/mdx/compiler.js.map +1 -0
- package/dist/mdx/highlighter.d.ts +22 -0
- package/dist/mdx/highlighter.d.ts.map +1 -0
- package/dist/mdx/highlighter.js +190 -0
- package/dist/mdx/highlighter.js.map +1 -0
- package/dist/mdx/rehype-shiki.d.ts +3 -0
- package/dist/mdx/rehype-shiki.d.ts.map +1 -0
- package/dist/mdx/rehype-shiki.js +83 -0
- package/dist/mdx/rehype-shiki.js.map +1 -0
- package/dist/navigation/index.d.ts +3 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +3 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/repository-links.d.ts +3 -0
- package/dist/navigation/repository-links.d.ts.map +1 -0
- package/dist/navigation/repository-links.js +35 -0
- package/dist/navigation/repository-links.js.map +1 -0
- package/dist/navigation/sidebar-state.d.ts +6 -0
- package/dist/navigation/sidebar-state.d.ts.map +1 -0
- package/dist/navigation/sidebar-state.js +20 -0
- package/dist/navigation/sidebar-state.js.map +1 -0
- package/dist/navigation/sidebar-tree.d.ts +7 -0
- package/dist/navigation/sidebar-tree.d.ts.map +1 -0
- package/dist/navigation/sidebar-tree.js +11 -0
- package/dist/navigation/sidebar-tree.js.map +1 -0
- package/dist/providers/theme-provider.d.ts +33 -0
- package/dist/providers/theme-provider.d.ts.map +1 -0
- package/dist/providers/theme-provider.jsx +158 -0
- package/dist/providers/theme-provider.jsx.map +1 -0
- package/dist/providers/theme-script.d.ts +16 -0
- package/dist/providers/theme-script.d.ts.map +1 -0
- package/dist/providers/theme-script.jsx +41 -0
- package/dist/providers/theme-script.jsx.map +1 -0
- package/dist/providers/theme-transitions.d.ts +12 -0
- package/dist/providers/theme-transitions.d.ts.map +1 -0
- package/dist/providers/theme-transitions.js +115 -0
- package/dist/providers/theme-transitions.js.map +1 -0
- package/dist/registry/api-table.json +21 -0
- package/dist/registry/badge.json +18 -0
- package/dist/registry/breadcrumb.json +17 -0
- package/dist/registry/button.json +21 -0
- package/dist/registry/callout.json +19 -0
- package/dist/registry/card.json +17 -0
- package/dist/registry/code-block.json +28 -0
- package/dist/registry/collapsible.json +18 -0
- package/dist/registry/command.json +27 -0
- package/dist/registry/component-viewer.json +25 -0
- package/dist/registry/container.json +18 -0
- package/dist/registry/create-click-outside.json +13 -0
- package/dist/registry/create-clipboard.json +13 -0
- package/dist/registry/create-color-mode.json +13 -0
- package/dist/registry/create-controllable-signal.json +13 -0
- package/dist/registry/create-focus-trap.json +13 -0
- package/dist/registry/create-keybindings.json +13 -0
- package/dist/registry/create-lock-scroll.json +13 -0
- package/dist/registry/create-resize-observer.json +13 -0
- package/dist/registry/create-scroll-position.json +13 -0
- package/dist/registry/dropdown-menu.json +22 -0
- package/dist/registry/input-group.json +21 -0
- package/dist/registry/kbd.json +18 -0
- package/dist/registry/list.json +20 -0
- package/dist/registry/logo.json +17 -0
- package/dist/registry/navbar.json +19 -0
- package/dist/registry/package-manager-tabs.json +24 -0
- package/dist/registry/pager.json +21 -0
- package/dist/registry/scroll-area.json +21 -0
- package/dist/registry/section-heading.json +21 -0
- package/dist/registry/separator.json +17 -0
- package/dist/registry/sidebar.json +24 -0
- package/dist/registry/skeleton.json +17 -0
- package/dist/registry/spinner.json +18 -0
- package/dist/registry/table-of-contents.json +23 -0
- package/dist/registry/table.json +17 -0
- package/dist/registry/tabs.json +20 -0
- package/dist/registry/theme-manager.json +39 -0
- package/dist/registry/tooltip.json +18 -0
- package/dist/search/provider.d.ts +14 -0
- package/dist/search/provider.d.ts.map +1 -0
- package/dist/search/provider.js +14 -0
- package/dist/search/provider.js.map +1 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +565 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/plugin.d.ts +10 -0
- package/dist/server/plugin.d.ts.map +1 -0
- package/dist/server/plugin.js +522 -0
- package/dist/server/plugin.js.map +1 -0
- package/dist/theme-accent.d.ts +8 -0
- package/dist/theme-accent.d.ts.map +1 -0
- package/dist/theme-accent.js +18 -0
- package/dist/theme-accent.js.map +1 -0
- package/dist/theme-mode.d.ts +4 -0
- package/dist/theme-mode.d.ts.map +1 -0
- package/dist/theme-mode.js +5 -0
- package/dist/theme-mode.js.map +1 -0
- package/dist/themes/default/content/breadcrumbs.d.ts +4 -0
- package/dist/themes/default/content/breadcrumbs.d.ts.map +1 -0
- package/dist/themes/default/content/breadcrumbs.jsx +31 -0
- package/dist/themes/default/content/breadcrumbs.jsx.map +1 -0
- package/dist/themes/default/content/pager.d.ts +5 -0
- package/dist/themes/default/content/pager.d.ts.map +1 -0
- package/dist/themes/default/content/pager.jsx +9 -0
- package/dist/themes/default/content/pager.jsx.map +1 -0
- package/dist/themes/default/content/table-of-contents.d.ts +4 -0
- package/dist/themes/default/content/table-of-contents.d.ts.map +1 -0
- package/dist/themes/default/content/table-of-contents.jsx +19 -0
- package/dist/themes/default/content/table-of-contents.jsx.map +1 -0
- package/dist/themes/default/icons.d.ts +3 -0
- package/dist/themes/default/icons.d.ts.map +1 -0
- package/dist/themes/default/icons.js +15 -0
- package/dist/themes/default/icons.js.map +1 -0
- package/dist/themes/default/index.d.ts +12 -0
- package/dist/themes/default/index.d.ts.map +1 -0
- package/dist/themes/default/index.js +30 -0
- package/dist/themes/default/index.js.map +1 -0
- package/dist/themes/default/layout.d.ts +4 -0
- package/dist/themes/default/layout.d.ts.map +1 -0
- package/dist/themes/default/layout.jsx +194 -0
- package/dist/themes/default/layout.jsx.map +1 -0
- package/dist/themes/default/navbar.d.ts +4 -0
- package/dist/themes/default/navbar.d.ts.map +1 -0
- package/dist/themes/default/navbar.jsx +83 -0
- package/dist/themes/default/navbar.jsx.map +1 -0
- package/dist/themes/default/navigation/mobile-table-of-contents.d.ts +4 -0
- package/dist/themes/default/navigation/mobile-table-of-contents.d.ts.map +1 -0
- package/dist/themes/default/navigation/mobile-table-of-contents.jsx +38 -0
- package/dist/themes/default/navigation/mobile-table-of-contents.jsx.map +1 -0
- package/dist/themes/default/navigation/sidebar-tree.d.ts +8 -0
- package/dist/themes/default/navigation/sidebar-tree.d.ts.map +1 -0
- package/dist/themes/default/navigation/sidebar-tree.jsx +124 -0
- package/dist/themes/default/navigation/sidebar-tree.jsx.map +1 -0
- package/dist/themes/default/overlays/search-dialog.d.ts +4 -0
- package/dist/themes/default/overlays/search-dialog.d.ts.map +1 -0
- package/dist/themes/default/overlays/search-dialog.jsx +52 -0
- package/dist/themes/default/overlays/search-dialog.jsx.map +1 -0
- package/dist/themes/default/sidebar.d.ts +4 -0
- package/dist/themes/default/sidebar.d.ts.map +1 -0
- package/dist/themes/default/sidebar.jsx +92 -0
- package/dist/themes/default/sidebar.jsx.map +1 -0
- package/dist/themes/index.d.ts +4 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +5 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/themes/types.d.ts +91 -0
- package/dist/themes/types.d.ts.map +1 -0
- package/dist/themes/types.js +2 -0
- package/dist/themes/types.js.map +1 -0
- package/dist/types.d.ts +132 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/vendor/docs-src/components/mdx-components.tsx +144 -0
- package/dist/vendor/docs-src/components/ui/api-table.tsx +117 -0
- package/dist/vendor/docs-src/components/ui/badge.tsx +56 -0
- package/dist/vendor/docs-src/components/ui/breadcrumb.tsx +136 -0
- package/dist/vendor/docs-src/components/ui/button.tsx +82 -0
- package/dist/vendor/docs-src/components/ui/callout.tsx +137 -0
- package/dist/vendor/docs-src/components/ui/card.tsx +113 -0
- package/dist/vendor/docs-src/components/ui/code-block.tsx +347 -0
- package/dist/vendor/docs-src/components/ui/collapsible.tsx +73 -0
- package/dist/vendor/docs-src/components/ui/command.tsx +382 -0
- package/dist/vendor/docs-src/components/ui/component-viewer.tsx +363 -0
- package/dist/vendor/docs-src/components/ui/container.tsx +45 -0
- package/dist/vendor/docs-src/components/ui/dropdown-menu.tsx +298 -0
- package/dist/vendor/docs-src/components/ui/input-group.tsx +80 -0
- package/dist/vendor/docs-src/components/ui/kbd.tsx +73 -0
- package/dist/vendor/docs-src/components/ui/list.tsx +222 -0
- package/dist/vendor/docs-src/components/ui/logo.tsx +68 -0
- package/dist/vendor/docs-src/components/ui/navbar.tsx +375 -0
- package/dist/vendor/docs-src/components/ui/package-manager-tabs.tsx +226 -0
- package/dist/vendor/docs-src/components/ui/pager.tsx +102 -0
- package/dist/vendor/docs-src/components/ui/scroll-area.tsx +228 -0
- package/dist/vendor/docs-src/components/ui/section-heading.tsx +115 -0
- package/dist/vendor/docs-src/components/ui/separator.tsx +37 -0
- package/dist/vendor/docs-src/components/ui/sidebar.tsx +712 -0
- package/dist/vendor/docs-src/components/ui/skeleton.tsx +24 -0
- package/dist/vendor/docs-src/components/ui/spinner.tsx +41 -0
- package/dist/vendor/docs-src/components/ui/table-of-contents.tsx +131 -0
- package/dist/vendor/docs-src/components/ui/table.tsx +160 -0
- package/dist/vendor/docs-src/components/ui/tabs.tsx +204 -0
- package/dist/vendor/docs-src/components/ui/theme-toggle.tsx +238 -0
- package/dist/vendor/docs-src/components/ui/tooltip.tsx +41 -0
- package/dist/vendor/docs-src/hooks/create-click-outside.ts +82 -0
- package/dist/vendor/docs-src/hooks/create-clipboard.ts +69 -0
- package/dist/vendor/docs-src/hooks/create-color-mode.ts +115 -0
- package/dist/vendor/docs-src/hooks/create-controllable-signal.ts +56 -0
- package/dist/vendor/docs-src/hooks/create-focus-trap.ts +94 -0
- package/dist/vendor/docs-src/hooks/create-keybindings.ts +148 -0
- package/dist/vendor/docs-src/hooks/create-lock-scroll.ts +97 -0
- package/dist/vendor/docs-src/hooks/create-resize-observer.ts +89 -0
- package/dist/vendor/docs-src/hooks/create-scroll-position.ts +129 -0
- package/dist/vendor/docs-src/lib/cn.ts +9 -0
- package/dist/vendor/docs-src/providers/theme-provider.tsx +203 -0
- package/dist/vendor/docs-src/providers/theme-script.tsx +54 -0
- package/dist/vendor/docs-src/providers/theme-transitions.ts +139 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { splitProps, type Component, For, Show, type JSX } from "solid-js";
|
|
2
|
+
import { Sun, Moon, Monitor } from "lucide-solid";
|
|
3
|
+
import {
|
|
4
|
+
useTheme,
|
|
5
|
+
type AccentColor,
|
|
6
|
+
type Radius,
|
|
7
|
+
type Theme,
|
|
8
|
+
} from "../../providers/theme-provider";
|
|
9
|
+
import {
|
|
10
|
+
runThemeTransition,
|
|
11
|
+
type ThemeEffect,
|
|
12
|
+
} from "../../providers/theme-transitions";
|
|
13
|
+
import { Button, type ButtonProps } from "./button";
|
|
14
|
+
import {
|
|
15
|
+
DropdownMenu,
|
|
16
|
+
DropdownMenuTrigger,
|
|
17
|
+
DropdownMenuContent,
|
|
18
|
+
DropdownMenuItem,
|
|
19
|
+
DropdownMenuGroup,
|
|
20
|
+
DropdownMenuLabel,
|
|
21
|
+
DropdownMenuSeparator,
|
|
22
|
+
} from "./dropdown-menu";
|
|
23
|
+
import { cn } from "@/lib/cn";
|
|
24
|
+
|
|
25
|
+
export interface ThemeToggleProps
|
|
26
|
+
extends Omit<JSX.ButtonHTMLAttributes<HTMLButtonElement>, "onClick"> {
|
|
27
|
+
/** Display mode: "button" (direct 1-click toggle), "mini" (compact dropdown), "max" (full customizer panel). Defaults to "mini". */
|
|
28
|
+
mode?: "button" | "mini" | "max";
|
|
29
|
+
/** Transition animation effect when changing themes ("none", "circular", "fade") */
|
|
30
|
+
effect?: ThemeEffect;
|
|
31
|
+
/** Button visual style variant when rendered as a button or dropdown trigger */
|
|
32
|
+
variant?: ButtonProps["variant"];
|
|
33
|
+
/** Button size */
|
|
34
|
+
size?: ButtonProps["size"];
|
|
35
|
+
class?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ACCENT_OPTIONS: { name: AccentColor; label: string; color: string }[] = [
|
|
39
|
+
{ name: "yellow", label: "Yellow", color: "bg-yellow-500" },
|
|
40
|
+
{ name: "red", label: "Red", color: "bg-red-500" },
|
|
41
|
+
{ name: "violet", label: "Violet", color: "bg-violet-500" },
|
|
42
|
+
{ name: "sky", label: "Sky", color: "bg-sky-500" },
|
|
43
|
+
{ name: "emerald", label: "Emerald", color: "bg-emerald-500" },
|
|
44
|
+
{ name: "zinc", label: "Zinc", color: "bg-zinc-800 dark:bg-zinc-200" },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const RADIUS_OPTIONS: { value: Radius; label: string }[] = [
|
|
48
|
+
{ value: "0", label: "0" },
|
|
49
|
+
{ value: "0.3", label: "0.3" },
|
|
50
|
+
{ value: "0.5", label: "0.5" },
|
|
51
|
+
{ value: "0.75", label: "0.75" },
|
|
52
|
+
{ value: "1.0", label: "1.0" },
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Interactive UI theme switcher supporting button, mini (dropdown), and max (customizer panel) modes with View Transition animations.
|
|
57
|
+
*/
|
|
58
|
+
export const ThemeToggle: Component<ThemeToggleProps> = (props) => {
|
|
59
|
+
const [local, rest] = splitProps(props, ["mode", "effect", "variant", "size", "class"]);
|
|
60
|
+
const { theme, setTheme, accent, setAccent, radius, setRadius } = useTheme();
|
|
61
|
+
|
|
62
|
+
const mode = () => local.mode || "mini";
|
|
63
|
+
const effect = () => local.effect || "none";
|
|
64
|
+
|
|
65
|
+
/* Reactive accessor determining whether dark mode is active */
|
|
66
|
+
const isDarkMode = () => {
|
|
67
|
+
const currentTheme = theme();
|
|
68
|
+
if (currentTheme === "dark") return true;
|
|
69
|
+
if (currentTheme === "light") return false;
|
|
70
|
+
if (typeof window !== "undefined") {
|
|
71
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const changeThemeWithEffect = (newTheme: Theme, e: MouseEvent) => {
|
|
77
|
+
runThemeTransition(effect(), e, () => {
|
|
78
|
+
setTheme(newTheme);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const handleToggleClick = (e: MouseEvent) => {
|
|
83
|
+
const nextTheme: Theme = isDarkMode() ? "light" : "dark";
|
|
84
|
+
changeThemeWithEffect(nextTheme, e);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<Show
|
|
89
|
+
when={mode() !== "button"}
|
|
90
|
+
fallback={
|
|
91
|
+
/* Button Mode: Direct 1-click Dark/Light switcher without dropdown */
|
|
92
|
+
<Button
|
|
93
|
+
variant={local.variant || "ghost"}
|
|
94
|
+
size={local.size || "icon"}
|
|
95
|
+
onClick={handleToggleClick}
|
|
96
|
+
class={cn("relative cursor-pointer", local.class)}
|
|
97
|
+
aria-label="Toggle theme"
|
|
98
|
+
{...rest}
|
|
99
|
+
>
|
|
100
|
+
<Show
|
|
101
|
+
when={isDarkMode()}
|
|
102
|
+
fallback={<Sun class="h-4 w-4 text-foreground transition-transform" />}
|
|
103
|
+
>
|
|
104
|
+
<Moon class="h-4 w-4 text-foreground transition-transform" />
|
|
105
|
+
</Show>
|
|
106
|
+
<span class="sr-only">Toggle theme</span>
|
|
107
|
+
</Button>
|
|
108
|
+
}
|
|
109
|
+
>
|
|
110
|
+
<DropdownMenu placement="bottom-end">
|
|
111
|
+
<DropdownMenuTrigger
|
|
112
|
+
as={Button}
|
|
113
|
+
variant={local.variant || "ghost"}
|
|
114
|
+
size={local.size || "icon"}
|
|
115
|
+
class={cn("relative cursor-pointer", local.class)}
|
|
116
|
+
{...rest}
|
|
117
|
+
>
|
|
118
|
+
{/* Reactive Sun / Moon Icon Toggle */}
|
|
119
|
+
<Show
|
|
120
|
+
when={isDarkMode()}
|
|
121
|
+
fallback={<Sun class="h-4 w-4 text-foreground transition-transform" />}
|
|
122
|
+
>
|
|
123
|
+
<Moon class="h-4 w-4 text-foreground transition-transform" />
|
|
124
|
+
</Show>
|
|
125
|
+
<span class="sr-only">Toggle theme</span>
|
|
126
|
+
</DropdownMenuTrigger>
|
|
127
|
+
|
|
128
|
+
<Show
|
|
129
|
+
when={mode() === "max"}
|
|
130
|
+
fallback={
|
|
131
|
+
/* Mini Mode: Compact Dropdown */
|
|
132
|
+
<DropdownMenuContent>
|
|
133
|
+
<DropdownMenuItem onClick={(e: MouseEvent) => changeThemeWithEffect("light", e)}>
|
|
134
|
+
<Sun class="mr-2 h-4 w-4 text-muted-foreground" />
|
|
135
|
+
Light
|
|
136
|
+
</DropdownMenuItem>
|
|
137
|
+
|
|
138
|
+
<DropdownMenuItem onClick={(e: MouseEvent) => changeThemeWithEffect("dark", e)}>
|
|
139
|
+
<Moon class="mr-2 h-4 w-4 text-muted-foreground" />
|
|
140
|
+
Dark
|
|
141
|
+
</DropdownMenuItem>
|
|
142
|
+
|
|
143
|
+
<DropdownMenuItem onClick={(e: MouseEvent) => changeThemeWithEffect("system", e)}>
|
|
144
|
+
<Monitor class="mr-2 h-4 w-4 text-muted-foreground" />
|
|
145
|
+
System
|
|
146
|
+
</DropdownMenuItem>
|
|
147
|
+
</DropdownMenuContent>
|
|
148
|
+
}
|
|
149
|
+
>
|
|
150
|
+
{/* Max Mode: Full Theme Customizer Panel */}
|
|
151
|
+
<DropdownMenuContent class="w-64">
|
|
152
|
+
<div class="p-2 space-y-2">
|
|
153
|
+
<DropdownMenuGroup>
|
|
154
|
+
<DropdownMenuLabel class="px-0 pt-0 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
155
|
+
Theme Mode
|
|
156
|
+
</DropdownMenuLabel>
|
|
157
|
+
<div class="grid grid-cols-3 gap-1 my-1.5">
|
|
158
|
+
<Button
|
|
159
|
+
variant={theme() === "light" ? "default" : "outline"}
|
|
160
|
+
size="sm"
|
|
161
|
+
onClick={(e: MouseEvent) => changeThemeWithEffect("light", e)}
|
|
162
|
+
class="h-8 text-xs cursor-pointer"
|
|
163
|
+
>
|
|
164
|
+
Light
|
|
165
|
+
</Button>
|
|
166
|
+
<Button
|
|
167
|
+
variant={theme() === "dark" ? "default" : "outline"}
|
|
168
|
+
size="sm"
|
|
169
|
+
onClick={(e: MouseEvent) => changeThemeWithEffect("dark", e)}
|
|
170
|
+
class="h-8 text-xs cursor-pointer"
|
|
171
|
+
>
|
|
172
|
+
Dark
|
|
173
|
+
</Button>
|
|
174
|
+
<Button
|
|
175
|
+
variant={theme() === "system" ? "default" : "outline"}
|
|
176
|
+
size="sm"
|
|
177
|
+
onClick={(e: MouseEvent) => changeThemeWithEffect("system", e)}
|
|
178
|
+
class="h-8 text-xs cursor-pointer"
|
|
179
|
+
>
|
|
180
|
+
System
|
|
181
|
+
</Button>
|
|
182
|
+
</div>
|
|
183
|
+
</DropdownMenuGroup>
|
|
184
|
+
|
|
185
|
+
<DropdownMenuSeparator class="my-2" />
|
|
186
|
+
|
|
187
|
+
<DropdownMenuGroup>
|
|
188
|
+
<DropdownMenuLabel class="px-0 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
189
|
+
Brand Accent Color
|
|
190
|
+
</DropdownMenuLabel>
|
|
191
|
+
<div class="flex flex-wrap gap-1.5 my-1.5">
|
|
192
|
+
<For each={ACCENT_OPTIONS}>
|
|
193
|
+
{(opt) => (
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
title={opt.label}
|
|
197
|
+
onClick={() => setAccent(opt.name)}
|
|
198
|
+
class={cn(
|
|
199
|
+
"h-6 w-6 rounded-md transition-all cursor-pointer border border-border flex items-center justify-center",
|
|
200
|
+
opt.color,
|
|
201
|
+
accent() === opt.name
|
|
202
|
+
? "ring-2 ring-primary ring-offset-2 ring-offset-background scale-110"
|
|
203
|
+
: "hover:scale-105"
|
|
204
|
+
)}
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
</For>
|
|
208
|
+
</div>
|
|
209
|
+
</DropdownMenuGroup>
|
|
210
|
+
|
|
211
|
+
<DropdownMenuSeparator class="my-2" />
|
|
212
|
+
|
|
213
|
+
<DropdownMenuGroup>
|
|
214
|
+
<DropdownMenuLabel class="px-0 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
215
|
+
Border Radius
|
|
216
|
+
</DropdownMenuLabel>
|
|
217
|
+
<div class="grid grid-cols-5 gap-1 my-1.5">
|
|
218
|
+
<For each={RADIUS_OPTIONS}>
|
|
219
|
+
{(r) => (
|
|
220
|
+
<Button
|
|
221
|
+
variant={radius() === r.value ? "default" : "outline"}
|
|
222
|
+
size="sm"
|
|
223
|
+
onClick={() => setRadius(r.value)}
|
|
224
|
+
class="h-7 text-xs px-1 cursor-pointer"
|
|
225
|
+
>
|
|
226
|
+
{r.label}
|
|
227
|
+
</Button>
|
|
228
|
+
)}
|
|
229
|
+
</For>
|
|
230
|
+
</div>
|
|
231
|
+
</DropdownMenuGroup>
|
|
232
|
+
</div>
|
|
233
|
+
</DropdownMenuContent>
|
|
234
|
+
</Show>
|
|
235
|
+
</DropdownMenu>
|
|
236
|
+
</Show>
|
|
237
|
+
);
|
|
238
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { splitProps, type Component, type ComponentProps } from "solid-js";
|
|
2
|
+
import { Tooltip as KobalteTooltip } from "@kobalte/core/tooltip";
|
|
3
|
+
import { cn } from "@/lib/cn";
|
|
4
|
+
|
|
5
|
+
export const Tooltip = KobalteTooltip;
|
|
6
|
+
|
|
7
|
+
export const TooltipTrigger = KobalteTooltip.Trigger;
|
|
8
|
+
|
|
9
|
+
export const TooltipArrow: Component<ComponentProps<typeof KobalteTooltip.Arrow>> = (props) => {
|
|
10
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<KobalteTooltip.Arrow
|
|
14
|
+
size={8}
|
|
15
|
+
class={cn("fill-popover stroke-border", local.class)}
|
|
16
|
+
{...rest}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export interface TooltipContentProps extends ComponentProps<typeof KobalteTooltip.Content> {
|
|
22
|
+
class?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const TooltipContent: Component<TooltipContentProps> = (props) => {
|
|
26
|
+
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<KobalteTooltip.Portal>
|
|
30
|
+
<KobalteTooltip.Content
|
|
31
|
+
class={cn(
|
|
32
|
+
"z-50 rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md transition-all animate-in fade-in-0 zoom-in-95 data-closed:animate-out data-[closed]:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
33
|
+
local.class
|
|
34
|
+
)}
|
|
35
|
+
{...rest}
|
|
36
|
+
>
|
|
37
|
+
{local.children}
|
|
38
|
+
</KobalteTooltip.Content>
|
|
39
|
+
</KobalteTooltip.Portal>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { onMount, onCleanup, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export interface CreateClickOutsideOptions {
|
|
4
|
+
/** Target HTML element or accessor returning the container element */
|
|
5
|
+
target:
|
|
6
|
+
| HTMLElement
|
|
7
|
+
| Accessor<HTMLElement | undefined>
|
|
8
|
+
| (HTMLElement | Accessor<HTMLElement | undefined>)[];
|
|
9
|
+
/** Callback fired when a click/pointer event occurs outside the target element(s) */
|
|
10
|
+
onInteractOutside: (event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
11
|
+
/** Whether the listener is active. Defaults to true. */
|
|
12
|
+
enabled?: boolean | Accessor<boolean>;
|
|
13
|
+
/** Optional element or accessor to ignore when checking outside clicks (e.g. trigger button) */
|
|
14
|
+
ignore?:
|
|
15
|
+
| HTMLElement
|
|
16
|
+
| Accessor<HTMLElement | undefined>
|
|
17
|
+
| (HTMLElement | Accessor<HTMLElement | undefined>)[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* SolidJS reactive primitive for detecting user interactions outside specified element(s).
|
|
22
|
+
*
|
|
23
|
+
* @param options Configuration options including target element(s), callback, and optional ignore elements.
|
|
24
|
+
*/
|
|
25
|
+
export function createClickOutside(options: CreateClickOutsideOptions): void {
|
|
26
|
+
const isEnabled = () => {
|
|
27
|
+
if (typeof options.enabled === "function") {
|
|
28
|
+
return options.enabled();
|
|
29
|
+
}
|
|
30
|
+
return options.enabled ?? true;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getElement = (
|
|
34
|
+
el: HTMLElement | Accessor<HTMLElement | undefined> | undefined
|
|
35
|
+
): HTMLElement | undefined => {
|
|
36
|
+
if (!el) return undefined;
|
|
37
|
+
if (typeof el === "function") {
|
|
38
|
+
return (el as Accessor<HTMLElement | undefined>)();
|
|
39
|
+
}
|
|
40
|
+
return el;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const getElements = (
|
|
44
|
+
targets:
|
|
45
|
+
| HTMLElement
|
|
46
|
+
| Accessor<HTMLElement | undefined>
|
|
47
|
+
| (HTMLElement | Accessor<HTMLElement | undefined>)[]
|
|
48
|
+
| undefined
|
|
49
|
+
): HTMLElement[] => {
|
|
50
|
+
if (!targets) return [];
|
|
51
|
+
const list = Array.isArray(targets) ? targets : [targets];
|
|
52
|
+
return list.map(getElement).filter((e): e is HTMLElement => e !== undefined);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const handlePointerDown = (event: MouseEvent | PointerEvent | TouchEvent) => {
|
|
56
|
+
if (!isEnabled()) return;
|
|
57
|
+
|
|
58
|
+
const targetNode = event.target as Node | null;
|
|
59
|
+
if (!targetNode) return;
|
|
60
|
+
|
|
61
|
+
const mainElements = getElements(options.target);
|
|
62
|
+
if (mainElements.length === 0) return;
|
|
63
|
+
|
|
64
|
+
const isInsideTarget = mainElements.some((el) => el.contains(targetNode));
|
|
65
|
+
if (isInsideTarget) return;
|
|
66
|
+
|
|
67
|
+
const ignoreElements = getElements(options.ignore);
|
|
68
|
+
const isInsideIgnore = ignoreElements.some((el) => el.contains(targetNode));
|
|
69
|
+
if (isInsideIgnore) return;
|
|
70
|
+
|
|
71
|
+
options.onInteractOutside(event);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
onMount(() => {
|
|
75
|
+
if (typeof window === "undefined") return;
|
|
76
|
+
|
|
77
|
+
window.addEventListener("pointerdown", handlePointerDown, true);
|
|
78
|
+
onCleanup(() => {
|
|
79
|
+
window.removeEventListener("pointerdown", handlePointerDown, true);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createSignal, onCleanup, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export interface CreateClipboardOptions {
|
|
4
|
+
/** Time in milliseconds to maintain the copied state before resetting. Defaults to 2000ms. */
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CreateClipboardReturn {
|
|
9
|
+
/** Signal accessor indicating if content was recently copied */
|
|
10
|
+
copied: Accessor<boolean>;
|
|
11
|
+
/** Function to copy text to clipboard */
|
|
12
|
+
copy: (text: string) => Promise<boolean>;
|
|
13
|
+
/** Error state if clipboard write fails */
|
|
14
|
+
error: Accessor<Error | undefined>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* SolidJS reactive primitive for copying text to clipboard with automatic reset state.
|
|
19
|
+
*
|
|
20
|
+
* @param options Configuration options including copied status reset timeout duration.
|
|
21
|
+
*/
|
|
22
|
+
export function createClipboard(options: CreateClipboardOptions = {}): CreateClipboardReturn {
|
|
23
|
+
const timeoutDuration = options.timeout ?? 2000;
|
|
24
|
+
const [copied, setCopied] = createSignal(false);
|
|
25
|
+
const [error, setError] = createSignal<Error | undefined>(undefined);
|
|
26
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
27
|
+
|
|
28
|
+
const clearTimer = () => {
|
|
29
|
+
if (timer) {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
timer = undefined;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const copy = async (text: string): Promise<boolean> => {
|
|
36
|
+
clearTimer();
|
|
37
|
+
setError(undefined);
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
if (typeof window !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
|
|
41
|
+
await navigator.clipboard.writeText(text);
|
|
42
|
+
setCopied(true);
|
|
43
|
+
|
|
44
|
+
timer = setTimeout(() => {
|
|
45
|
+
setCopied(false);
|
|
46
|
+
}, timeoutDuration);
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
throw new Error("Clipboard API not supported");
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const copyError = err instanceof Error ? err : new Error(String(err));
|
|
54
|
+
setError(copyError);
|
|
55
|
+
setCopied(false);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
onCleanup(() => {
|
|
61
|
+
clearTimer();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
copied,
|
|
66
|
+
copy,
|
|
67
|
+
error,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createEffect, createSignal, onCleanup, onMount, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export type ColorMode = "light" | "dark" | "system";
|
|
4
|
+
|
|
5
|
+
export interface CreateColorModeOptions {
|
|
6
|
+
/** Initial color mode fallback. Defaults to 'system'. */
|
|
7
|
+
initialValue?: ColorMode;
|
|
8
|
+
/** LocalStorage key for persisting color mode state. Defaults to 'nikala-color-mode'. */
|
|
9
|
+
storageKey?: string;
|
|
10
|
+
/** HTML attribute to apply dark mode class on document.documentElement. Defaults to 'class'. */
|
|
11
|
+
attribute?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CreateColorModeReturn {
|
|
15
|
+
/** Accessor for current active color mode ('light', 'dark', 'system') */
|
|
16
|
+
mode: Accessor<ColorMode>;
|
|
17
|
+
/** Function to update current color mode */
|
|
18
|
+
setMode: (mode: ColorMode) => void;
|
|
19
|
+
/** Function to toggle color mode between 'light' and 'dark' */
|
|
20
|
+
toggleColorMode: () => void;
|
|
21
|
+
/** Accessor indicating if current resolved mode is dark */
|
|
22
|
+
isDark: Accessor<boolean>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* SolidJS reactive primitive for managing dark/light color mode themes and system preferences.
|
|
27
|
+
*
|
|
28
|
+
* @param options Configuration options including storage key and initial mode.
|
|
29
|
+
*/
|
|
30
|
+
export function createColorMode(
|
|
31
|
+
options: CreateColorModeOptions = {}
|
|
32
|
+
): CreateColorModeReturn {
|
|
33
|
+
const initialMode = options.initialValue ?? "system";
|
|
34
|
+
const storageKey = options.storageKey ?? "nikala-color-mode";
|
|
35
|
+
const attribute = options.attribute ?? "class";
|
|
36
|
+
|
|
37
|
+
const [mode, setModeSignal] = createSignal<ColorMode>(initialMode);
|
|
38
|
+
const [systemDark, setSystemDark] = createSignal(false);
|
|
39
|
+
|
|
40
|
+
const isDark = () => {
|
|
41
|
+
const currentMode = mode();
|
|
42
|
+
if (currentMode === "system") return systemDark();
|
|
43
|
+
return currentMode === "dark";
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const applyTheme = (dark: boolean) => {
|
|
47
|
+
if (typeof document === "undefined") return;
|
|
48
|
+
const root = document.documentElement;
|
|
49
|
+
if (attribute === "class") {
|
|
50
|
+
if (dark) root.classList.add("dark");
|
|
51
|
+
else root.classList.remove("dark");
|
|
52
|
+
} else {
|
|
53
|
+
root.setAttribute(attribute, dark ? "dark" : "light");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const setMode = (newMode: ColorMode) => {
|
|
58
|
+
setModeSignal(newMode);
|
|
59
|
+
if (typeof window !== "undefined") {
|
|
60
|
+
try {
|
|
61
|
+
localStorage.setItem(storageKey, newMode);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.warn(`[nikala-ui/hooks] Error setting color mode storage:`, e);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const toggleColorMode = () => {
|
|
69
|
+
const next = isDark() ? "light" : "dark";
|
|
70
|
+
setMode(next);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
createEffect(() => {
|
|
74
|
+
applyTheme(isDark());
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
onMount(() => {
|
|
78
|
+
if (typeof window === "undefined") return;
|
|
79
|
+
|
|
80
|
+
// Check system preference
|
|
81
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
82
|
+
setSystemDark(mediaQuery.matches);
|
|
83
|
+
|
|
84
|
+
const handleMediaChange = (e: MediaQueryListEvent) => {
|
|
85
|
+
setSystemDark(e.matches);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
if (mediaQuery.addEventListener) {
|
|
89
|
+
mediaQuery.addEventListener("change", handleMediaChange);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check localStorage
|
|
93
|
+
try {
|
|
94
|
+
const stored = localStorage.getItem(storageKey) as ColorMode | null;
|
|
95
|
+
if (stored && ["light", "dark", "system"].includes(stored)) {
|
|
96
|
+
setModeSignal(stored);
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.warn(`[nikala-ui/hooks] Error reading color mode storage:`, e);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
onCleanup(() => {
|
|
103
|
+
if (mediaQuery.removeEventListener) {
|
|
104
|
+
mediaQuery.removeEventListener("change", handleMediaChange);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
mode,
|
|
111
|
+
setMode,
|
|
112
|
+
toggleColorMode,
|
|
113
|
+
isDark,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createSignal, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export interface CreateControllableSignalOptions<T> {
|
|
4
|
+
/** Controlled value accessor or raw value */
|
|
5
|
+
value?: Accessor<T | undefined> | T;
|
|
6
|
+
/** Uncontrolled default initial value */
|
|
7
|
+
defaultValue?: T;
|
|
8
|
+
/** Callback fired whenever the value changes */
|
|
9
|
+
onChange?: (value: T) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* SolidJS reactive primitive for managing state supporting both controlled and uncontrolled modes.
|
|
14
|
+
*
|
|
15
|
+
* @param options Configuration options for value, defaultValue, and onChange callback.
|
|
16
|
+
* @returns A tuple containing [valueAccessor, setValueFunction].
|
|
17
|
+
*/
|
|
18
|
+
export function createControllableSignal<T>(
|
|
19
|
+
options: CreateControllableSignalOptions<T>
|
|
20
|
+
): [Accessor<T | undefined>, (nextValue: T | ((prev: T | undefined) => T)) => void] {
|
|
21
|
+
const [internalValue, setInternalValue] = createSignal<T | undefined>(
|
|
22
|
+
options.defaultValue
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const getValue = (): T | undefined => {
|
|
26
|
+
if (typeof options.value === "function") {
|
|
27
|
+
return (options.value as Accessor<T | undefined>)();
|
|
28
|
+
}
|
|
29
|
+
return options.value;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const isControlled = () => getValue() !== undefined;
|
|
33
|
+
|
|
34
|
+
const value = () => {
|
|
35
|
+
const controlledVal = getValue();
|
|
36
|
+
return controlledVal !== undefined ? controlledVal : internalValue();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const setValue = (nextValue: T | ((prev: T | undefined) => T)) => {
|
|
40
|
+
const current = value();
|
|
41
|
+
const resolvedNext =
|
|
42
|
+
typeof nextValue === "function"
|
|
43
|
+
? (nextValue as (prev: T | undefined) => T)(current)
|
|
44
|
+
: nextValue;
|
|
45
|
+
|
|
46
|
+
if (!isControlled()) {
|
|
47
|
+
setInternalValue(resolvedNext as any);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (typeof options.onChange === "function") {
|
|
51
|
+
options.onChange(resolvedNext);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return [value, setValue];
|
|
56
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createEffect, onCleanup, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export interface CreateFocusTrapOptions {
|
|
4
|
+
/** Whether focus trap is actively enabled. Defaults to true. */
|
|
5
|
+
enabled?: boolean | Accessor<boolean>;
|
|
6
|
+
/** Whether to return focus to previously focused element on cleanup. Defaults to true. */
|
|
7
|
+
returnFocusOnDeactivate?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const FOCUSABLE_SELECTOR =
|
|
11
|
+
'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable]';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* SolidJS reactive primitive for trapping keyboard focus inside target container element.
|
|
15
|
+
*
|
|
16
|
+
* @param target Target element or accessor returning HTML element.
|
|
17
|
+
* @param options Configuration options for focus trap behavior.
|
|
18
|
+
*/
|
|
19
|
+
export function createFocusTrap(
|
|
20
|
+
target: HTMLElement | Accessor<HTMLElement | undefined>,
|
|
21
|
+
options: CreateFocusTrapOptions = {}
|
|
22
|
+
): void {
|
|
23
|
+
const getTarget = (): HTMLElement | undefined => {
|
|
24
|
+
if (typeof target === "function") {
|
|
25
|
+
return (target as Accessor<HTMLElement | undefined>)();
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const isEnabled = (): boolean => {
|
|
31
|
+
if (typeof options.enabled === "function") {
|
|
32
|
+
return options.enabled();
|
|
33
|
+
}
|
|
34
|
+
return options.enabled ?? true;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
createEffect(() => {
|
|
38
|
+
if (typeof window === "undefined" || !isEnabled()) return;
|
|
39
|
+
|
|
40
|
+
const container = getTarget();
|
|
41
|
+
if (!container) return;
|
|
42
|
+
|
|
43
|
+
const previousActiveElement = document.activeElement as HTMLElement | null;
|
|
44
|
+
|
|
45
|
+
const getFocusableElements = (): HTMLElement[] => {
|
|
46
|
+
return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(
|
|
47
|
+
(el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const focusable = getFocusableElements();
|
|
52
|
+
if (focusable.length > 0) {
|
|
53
|
+
focusable[0].focus();
|
|
54
|
+
} else {
|
|
55
|
+
container.focus();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
59
|
+
if (event.key !== "Tab") return;
|
|
60
|
+
|
|
61
|
+
const elements = getFocusableElements();
|
|
62
|
+
if (elements.length === 0) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const firstElement = elements[0];
|
|
68
|
+
const lastElement = elements[elements.length - 1];
|
|
69
|
+
const activeElement = document.activeElement;
|
|
70
|
+
|
|
71
|
+
if (event.shiftKey) {
|
|
72
|
+
if (activeElement === firstElement || !container.contains(activeElement)) {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
lastElement.focus();
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
if (activeElement === lastElement || !container.contains(activeElement)) {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
firstElement.focus();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
85
|
+
|
|
86
|
+
onCleanup(() => {
|
|
87
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
88
|
+
|
|
89
|
+
if (options.returnFocusOnDeactivate !== false && previousActiveElement) {
|
|
90
|
+
previousActiveElement.focus?.();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|