@ctrl-ui/react 0.8.1 → 0.8.4
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/README.md +32 -23
- package/dist/action-bar.d.ts +11 -12
- package/dist/activity.d.ts +24 -25
- package/dist/audio-recorder.d.ts +16 -16
- package/dist/audio-visualizer.d.ts +3 -4
- package/dist/blocks/chat.d.ts +3 -4
- package/dist/blocks/chat.js +6 -3
- package/dist/blocks/coding-agent.d.ts +11 -12
- package/dist/blocks/coding-agent.js +10 -9
- package/dist/blocks/file-explorer-data.d.ts +11 -12
- package/dist/blocks/file-explorer.d.ts +3 -3
- package/dist/blocks/settings-data.d.ts +8 -9
- package/dist/blocks/settings.d.ts +4 -4
- package/dist/blocks/theme-toggle.d.ts +11 -12
- package/dist/blocks/theme-toggle.js +14 -4
- package/dist/chat-composer-attachment.d.ts +20 -21
- package/dist/chat-composer-attachment.js +24 -20
- package/dist/chat-composer-editor/extensions/mention.d.ts +5 -6
- package/dist/chat-composer-editor/ghost.d.ts +3 -4
- package/dist/chat-composer-editor/schema.d.ts +2 -3
- package/dist/chat-composer-editor/serialize.d.ts +3 -4
- package/dist/chat-composer-editor/types.d.ts +5 -6
- package/dist/chat-composer-editor.d.ts +2 -3
- package/dist/chat-composer-editor.js +18 -4
- package/dist/chat-composer.d.ts +17 -18
- package/dist/chat-composer.js +14 -8
- package/dist/chat-layout.d.ts +12 -21
- package/dist/chat-layout.js +28 -83
- package/dist/chat-message.d.ts +14 -15
- package/dist/context-model.d.ts +7 -8
- package/dist/context.d.ts +21 -22
- package/dist/control-props.d.ts +10 -11
- package/dist/control-variants.d.ts +6 -7
- package/dist/dynamic-notification-glass.d.ts +3 -4
- package/dist/dynamic-notification-liquid.d.ts +3 -4
- package/dist/dynamic-notification-siri-wave.d.ts +2 -3
- package/dist/dynamic-notification.d.ts +28 -29
- package/dist/email/email.d.ts +6 -7
- package/dist/email/email.js +12 -3
- package/dist/email/length.d.ts +3 -0
- package/dist/email/length.js +34 -0
- package/dist/email/templates.d.ts +7 -8
- package/dist/email/templates.js +5 -5
- package/dist/email/theme.d.ts +16 -5
- package/dist/email/theme.js +21 -6
- package/dist/environment-variables.d.ts +35 -36
- package/dist/extensions/create-track-highlight.d.ts +3 -4
- package/dist/extensions/supports-anchor-transitions.d.ts +2 -3
- package/dist/extensions/track-highlight.d.ts +3 -4
- package/dist/hooks/use-audio-recorder.d.ts +14 -15
- package/dist/hooks/use-chat-composer.d.ts +5 -6
- package/dist/hooks/use-chat-message.d.ts +7 -8
- package/dist/hooks/use-color-area.d.ts +5 -6
- package/dist/hooks/use-copy-to-clipboard.d.ts +7 -8
- package/dist/hooks/use-dropzone.d.ts +11 -12
- package/dist/hooks/use-dynamic-notification.d.ts +6 -7
- package/dist/hooks/use-environment-variables.d.ts +9 -10
- package/dist/hooks/use-keyboard-navigation.d.ts +3 -0
- package/dist/hooks/use-keyboard-navigation.js +22 -0
- package/dist/hooks/use-mobile.d.ts +2 -3
- package/dist/hooks/use-textarea-trigger-menu.d.ts +2 -3
- package/dist/hooks/use-trigger-menu.d.ts +7 -8
- package/dist/hooks/use-user-ask.d.ts +6 -7
- package/dist/inline-attachment.d.ts +16 -17
- package/dist/inline-citation.d.ts +22 -23
- package/dist/knob-contracts/accordion-knobs.d.ts +3 -4
- package/dist/knob-contracts/accordion-knobs.js +1 -0
- package/dist/knob-contracts/action-bar-knobs.d.ts +3 -4
- package/dist/knob-contracts/activity-knobs.d.ts +3 -4
- package/dist/knob-contracts/alert-knobs.d.ts +3 -4
- package/dist/knob-contracts/alert-knobs.js +12 -1
- package/dist/knob-contracts/audio-recorder-knobs.d.ts +3 -4
- package/dist/knob-contracts/audio-visualizer-knobs.d.ts +3 -4
- package/dist/knob-contracts/avatar-knobs.d.ts +3 -4
- package/dist/knob-contracts/avatar-knobs.js +2 -1
- package/dist/knob-contracts/badge-knobs.d.ts +3 -4
- package/dist/knob-contracts/button-group-knobs.d.ts +3 -4
- package/dist/knob-contracts/button-knobs.d.ts +3 -4
- package/dist/knob-contracts/button-knobs.js +1 -0
- package/dist/knob-contracts/calendar-knobs.d.ts +3 -4
- package/dist/knob-contracts/card-knobs.d.ts +3 -4
- package/dist/knob-contracts/chat-composer-attachment-knobs.d.ts +3 -4
- package/dist/knob-contracts/chat-composer-attachment-knobs.js +3 -1
- package/dist/knob-contracts/chat-composer-knobs.d.ts +3 -4
- package/dist/knob-contracts/chat-composer-knobs.js +1 -0
- package/dist/knob-contracts/chat-layout-knobs.d.ts +3 -4
- package/dist/knob-contracts/chat-layout-knobs.js +2 -3
- package/dist/knob-contracts/chat-message-knobs.d.ts +3 -4
- package/dist/knob-contracts/choice-knobs.d.ts +3 -4
- package/dist/knob-contracts/choice-knobs.js +2 -1
- package/dist/knob-contracts/code-diff-knobs.d.ts +3 -4
- package/dist/knob-contracts/code-diff-knobs.js +1 -0
- package/dist/knob-contracts/code-knobs.d.ts +3 -4
- package/dist/knob-contracts/code-knobs.js +3 -1
- package/dist/knob-contracts/collapsible-knobs.d.ts +3 -4
- package/dist/knob-contracts/color-picker-knobs.d.ts +3 -4
- package/dist/knob-contracts/context-knobs.d.ts +3 -4
- package/dist/knob-contracts/dockable-panel-knobs.d.ts +3 -4
- package/dist/knob-contracts/dockable-panel-knobs.js +1 -0
- package/dist/knob-contracts/dropzone-knobs.d.ts +3 -4
- package/dist/knob-contracts/dropzone-knobs.js +1 -0
- package/dist/knob-contracts/dynamic-notification-knobs.d.ts +3 -4
- package/dist/knob-contracts/empty-knobs.d.ts +3 -4
- package/dist/knob-contracts/empty-knobs.js +14 -1
- package/dist/knob-contracts/environment-variables-knobs.d.ts +3 -4
- package/dist/knob-contracts/environment-variables-knobs.js +2 -1
- package/dist/knob-contracts/field-knobs.d.ts +3 -4
- package/dist/knob-contracts/gradient-editor-knobs.d.ts +3 -4
- package/dist/knob-contracts/gradient-editor-knobs.js +3 -1
- package/dist/knob-contracts/infinite-canvas-knobs.d.ts +3 -4
- package/dist/knob-contracts/inline-attachment-knobs.d.ts +3 -4
- package/dist/knob-contracts/inline-attachment-knobs.js +2 -1
- package/dist/knob-contracts/inline-citation-knobs.d.ts +3 -4
- package/dist/knob-contracts/inline-citation-knobs.js +1 -0
- package/dist/knob-contracts/item-knobs.d.ts +3 -4
- package/dist/knob-contracts/kbd-knobs.d.ts +3 -4
- package/dist/knob-contracts/markdown-block-knobs.d.ts +3 -4
- package/dist/knob-contracts/markdown-block-knobs.js +2 -0
- package/dist/knob-contracts/markdown-knobs.d.ts +3 -4
- package/dist/knob-contracts/markdown-knobs.js +1 -0
- package/dist/knob-contracts/morphing-panel-knobs.d.ts +3 -4
- package/dist/knob-contracts/pagination-knobs.d.ts +3 -4
- package/dist/knob-contracts/phone-input-knobs.d.ts +3 -4
- package/dist/knob-contracts/phone-input-knobs.js +1 -0
- package/dist/knob-contracts/popup-knobs.d.ts +3 -4
- package/dist/knob-contracts/progressive-blur-knobs.d.ts +3 -4
- package/dist/knob-contracts/progressive-blur-knobs.js +1 -0
- package/dist/knob-contracts/range-knobs.d.ts +3 -4
- package/dist/knob-contracts/resizable-knobs.d.ts +3 -4
- package/dist/knob-contracts/resizable-knobs.js +1 -0
- package/dist/knob-contracts/rich-tooltip-knobs.d.ts +3 -4
- package/dist/knob-contracts/scroll-area-knobs.d.ts +3 -4
- package/dist/knob-contracts/separator-knobs.d.ts +3 -4
- package/dist/knob-contracts/sidebar-knobs.d.ts +3 -4
- package/dist/knob-contracts/sidebar-knobs.js +1 -0
- package/dist/knob-contracts/skeleton-knobs.d.ts +3 -4
- package/dist/knob-contracts/skeleton-knobs.js +9 -1
- package/dist/knob-contracts/source-badge-knobs.d.ts +3 -4
- package/dist/knob-contracts/spinner-knobs.d.ts +3 -4
- package/dist/knob-contracts/stepper-knobs.d.ts +3 -4
- package/dist/knob-contracts/stepper-knobs.js +1 -0
- package/dist/knob-contracts/switch-knobs.d.ts +3 -4
- package/dist/knob-contracts/switch-knobs.js +7 -1
- package/dist/knob-contracts/table-knobs.d.ts +3 -4
- package/dist/knob-contracts/table-of-contents-knobs.d.ts +3 -4
- package/dist/knob-contracts/table-of-contents-knobs.js +25 -0
- package/dist/knob-contracts/tabs-knobs.d.ts +3 -4
- package/dist/knob-contracts/tabs-knobs.js +2 -1
- package/dist/knob-contracts/task-list-knobs.d.ts +3 -4
- package/dist/knob-contracts/task-list-knobs.js +1 -0
- package/dist/knob-contracts/thread-rail-knobs.d.ts +3 -4
- package/dist/knob-contracts/timeline-knobs.d.ts +3 -4
- package/dist/knob-contracts/toolbar-knobs.d.ts +3 -4
- package/dist/knob-contracts/toolbar-knobs.js +1 -0
- package/dist/knob-contracts/track-highlight-knobs.d.ts +3 -4
- package/dist/knob-contracts/transcript-divider-knobs.d.ts +3 -4
- package/dist/knob-contracts/tree-knobs.d.ts +3 -4
- package/dist/knob-contracts/user-ask-knobs.d.ts +3 -4
- package/dist/knob-contracts/user-ask-knobs.js +1 -0
- package/dist/lib/cn.d.ts +2 -3
- package/dist/lib/code-tokens.d.ts +12 -13
- package/dist/lib/color.d.ts +26 -27
- package/dist/lib/contrast.d.ts +12 -13
- package/dist/lib/diff.d.ts +14 -15
- package/dist/lib/dropzone-validation.d.ts +25 -26
- package/dist/lib/env-file.d.ts +12 -13
- package/dist/lib/format-audio-recorder-duration.d.ts +2 -3
- package/dist/lib/liquid-glass-optics.d.ts +2 -3
- package/dist/lib/phone-input-format.d.ts +3 -4
- package/dist/lib/phone-input-format.js +1 -1
- package/dist/lib/phone-number.d.ts +8 -9
- package/dist/lib/trigger-detect.d.ts +4 -5
- package/dist/markdown-block.d.ts +11 -12
- package/dist/scripts/contrast-eval.d.ts +16 -17
- package/dist/scripts/contrast-eval.js +13 -7
- package/dist/skin-provider.d.ts +14 -0
- package/dist/skin-provider.js +21 -0
- package/dist/skin.d.ts +14 -33
- package/dist/skin.js +3 -46
- package/dist/source-badge.d.ts +7 -8
- package/dist/styles/index.css +2 -4
- package/dist/styles/recipes/accordion.css +8 -2
- package/dist/styles/recipes/action-bar.css +5 -2
- package/dist/styles/recipes/alert.css +95 -16
- package/dist/styles/recipes/avatar.css +17 -1
- package/dist/styles/recipes/badge.css +0 -1
- package/dist/styles/recipes/button.css +34 -8
- package/dist/styles/recipes/calendar.css +0 -6
- package/dist/styles/recipes/chat-composer-attachment.css +51 -53
- package/dist/styles/recipes/chat-composer.css +26 -21
- package/dist/styles/recipes/chat-layout.css +21 -62
- package/dist/styles/recipes/chat-message.css +11 -5
- package/dist/styles/recipes/choice.css +9 -2
- package/dist/styles/recipes/code-diff.css +8 -1
- package/dist/styles/recipes/code.css +39 -17
- package/dist/styles/recipes/collapsible.css +0 -3
- package/dist/styles/recipes/color-picker-details.css +1 -2
- package/dist/styles/recipes/color-picker-values.css +0 -4
- package/dist/styles/recipes/dockable-panel.css +8 -1
- package/dist/styles/recipes/dropzone.css +9 -2
- package/dist/styles/recipes/empty.css +118 -17
- package/dist/styles/recipes/environment-variables.css +8 -1
- package/dist/styles/recipes/field-parts.css +1 -6
- package/dist/styles/recipes/field.css +9 -5
- package/dist/styles/recipes/gradient-editor.css +16 -5
- package/dist/styles/recipes/inline-attachment.css +13 -8
- package/dist/styles/recipes/inline-citation.css +8 -4
- package/dist/styles/recipes/item.css +1 -1
- package/dist/styles/recipes/kbd.css +8 -0
- package/dist/styles/recipes/markdown-block.css +16 -2
- package/dist/styles/recipes/markdown.css +12 -0
- package/dist/styles/recipes/morphing-panel.css +1 -1
- package/dist/styles/recipes/pagination.css +0 -4
- package/dist/styles/recipes/phone-input.css +8 -4
- package/dist/styles/recipes/popup-lists.css +11 -0
- package/dist/styles/recipes/popup-toast.css +1 -29
- package/dist/styles/recipes/popup.css +2 -2
- package/dist/styles/recipes/progressive-blur.css +28 -7
- package/dist/styles/recipes/range.css +50 -1
- package/dist/styles/recipes/resizable.css +8 -10
- package/dist/styles/recipes/rich-tooltip.css +0 -4
- package/dist/styles/recipes/scroll-area.css +8 -2
- package/dist/styles/recipes/sidebar-menu.css +150 -0
- package/dist/styles/recipes/sidebar.css +56 -110
- package/dist/styles/recipes/skeleton.css +85 -3
- package/dist/styles/recipes/source-badge.css +0 -3
- package/dist/styles/recipes/stepper.css +8 -1
- package/dist/styles/recipes/switch.css +89 -17
- package/dist/styles/recipes/table-of-contents.css +211 -45
- package/dist/styles/recipes/table.css +0 -1
- package/dist/styles/recipes/tabs.css +19 -2
- package/dist/styles/recipes/task-list.css +8 -2
- package/dist/styles/recipes/thread-rail.css +0 -4
- package/dist/styles/recipes/toolbar.css +18 -4
- package/dist/styles/recipes/track-highlight.css +63 -5
- package/dist/styles/recipes/tree.css +2 -0
- package/dist/styles/recipes/user-ask.css +8 -4
- package/dist/styles/theme.css +130 -138
- package/dist/surface-variants.d.ts +4 -5
- package/dist/task-list.d.ts +16 -17
- package/dist/thread-rail.d.ts +21 -22
- package/dist/transcript-divider.d.ts +6 -7
- package/dist/ui/accordion.d.ts +10 -11
- package/dist/ui/alert-dialog.d.ts +11 -12
- package/dist/ui/alert-dialog.js +8 -6
- package/dist/ui/alert.d.ts +9 -10
- package/dist/ui/alert.js +3 -3
- package/dist/ui/aspect-ratio.d.ts +3 -4
- package/dist/ui/autocomplete.d.ts +19 -20
- package/dist/ui/autocomplete.js +5 -3
- package/dist/ui/avatar.d.ts +9 -10
- package/dist/ui/badge.d.ts +9 -10
- package/dist/ui/button-group.d.ts +7 -8
- package/dist/ui/button-group.js +3 -2
- package/dist/ui/button.d.ts +17 -18
- package/dist/ui/button.js +20 -5
- package/dist/ui/calendar.d.ts +3 -4
- package/dist/ui/card.d.ts +16 -17
- package/dist/ui/checkbox-group.d.ts +4 -5
- package/dist/ui/checkbox-group.js +3 -2
- package/dist/ui/checkbox.d.ts +3 -4
- package/dist/ui/code-diff.d.ts +8 -9
- package/dist/ui/code.d.ts +32 -23
- package/dist/ui/code.js +41 -20
- package/dist/ui/collapsible.d.ts +7 -8
- package/dist/ui/color-picker.d.ts +40 -41
- package/dist/ui/color-picker.js +5 -3
- package/dist/ui/combobox-disabled-selection.d.ts +3 -4
- package/dist/ui/combobox.d.ts +21 -20
- package/dist/ui/combobox.js +5 -3
- package/dist/ui/command.d.ts +19 -18
- package/dist/ui/command.js +38 -12
- package/dist/ui/context-menu.d.ts +30 -31
- package/dist/ui/context-menu.js +8 -5
- package/dist/ui/dialog.d.ts +13 -13
- package/dist/ui/dialog.js +10 -8
- package/dist/ui/dockable-panel-geometry.d.ts +7 -8
- package/dist/ui/dockable-panel.d.ts +21 -22
- package/dist/ui/drawer.d.ts +17 -18
- package/dist/ui/drawer.js +7 -6
- package/dist/ui/dropdown-menu.d.ts +36 -29
- package/dist/ui/dropdown-menu.js +116 -9
- package/dist/ui/dropzone.d.ts +24 -24
- package/dist/ui/empty.d.ts +14 -14
- package/dist/ui/empty.js +3 -3
- package/dist/ui/field.d.ts +26 -27
- package/dist/ui/form.d.ts +4 -5
- package/dist/ui/gradient-editor.d.ts +16 -17
- package/dist/ui/hover-card.d.ts +6 -7
- package/dist/ui/hover-card.js +5 -3
- package/dist/ui/infinite-canvas.d.ts +11 -12
- package/dist/ui/input-group.d.ts +6 -7
- package/dist/ui/input-otp.d.ts +7 -8
- package/dist/ui/input.d.ts +3 -4
- package/dist/ui/item.d.ts +20 -21
- package/dist/ui/kbd.d.ts +7 -5
- package/dist/ui/kbd.js +4 -2
- package/dist/ui/markdown-elements.d.ts +20 -21
- package/dist/ui/markdown.d.ts +5 -6
- package/dist/ui/menubar.d.ts +25 -26
- package/dist/ui/menubar.js +8 -5
- package/dist/ui/meter.d.ts +11 -12
- package/dist/ui/morphing-panel.d.ts +8 -9
- package/dist/ui/native-select.d.ts +3 -4
- package/dist/ui/native-select.js +1 -1
- package/dist/ui/navigation-menu.d.ts +17 -18
- package/dist/ui/navigation-menu.js +5 -3
- package/dist/ui/number-field.d.ts +15 -16
- package/dist/ui/pagination.d.ts +10 -11
- package/dist/ui/phone-input.d.ts +5 -6
- package/dist/ui/phone-input.js +40 -37
- package/dist/ui/popover.d.ts +11 -12
- package/dist/ui/popover.js +5 -3
- package/dist/ui/progress.d.ts +11 -12
- package/dist/ui/progressive-blur.d.ts +4 -5
- package/dist/ui/radio-group.d.ts +5 -6
- package/dist/ui/resizable.d.ts +12 -13
- package/dist/ui/responsive-dialog.d.ts +11 -12
- package/dist/ui/rich-tooltip-tour.d.ts +5 -6
- package/dist/ui/rich-tooltip.d.ts +21 -23
- package/dist/ui/rich-tooltip.js +5 -5
- package/dist/ui/scroll-area.d.ts +7 -8
- package/dist/ui/scroll-area.js +9 -6
- package/dist/ui/select.d.ts +21 -14
- package/dist/ui/select.js +7 -4
- package/dist/ui/separator.d.ts +2 -3
- package/dist/ui/sheet.d.ts +8 -9
- package/dist/ui/sheet.js +7 -5
- package/dist/ui/sidebar-menu.d.ts +24 -15
- package/dist/ui/sidebar-menu.js +30 -4
- package/dist/ui/sidebar-provider.d.ts +32 -7
- package/dist/ui/sidebar-provider.js +82 -22
- package/dist/ui/sidebar-resize-rail.d.ts +8 -0
- package/dist/ui/sidebar-resize-rail.js +192 -0
- package/dist/ui/sidebar.d.ts +20 -14
- package/dist/ui/sidebar.js +122 -57
- package/dist/ui/skeleton.d.ts +7 -4
- package/dist/ui/skeleton.js +9 -2
- package/dist/ui/slider.d.ts +6 -5
- package/dist/ui/slider.js +16 -13
- package/dist/ui/spinner.d.ts +3 -4
- package/dist/ui/stepper.d.ts +22 -23
- package/dist/ui/switch.d.ts +3 -4
- package/dist/ui/switch.js +12 -1
- package/dist/ui/table-of-contents.d.ts +7 -8
- package/dist/ui/table-of-contents.js +4 -2
- package/dist/ui/table.d.ts +17 -18
- package/dist/ui/tabs.d.ts +14 -11
- package/dist/ui/textarea.d.ts +3 -4
- package/dist/ui/timeline.d.ts +18 -19
- package/dist/ui/toast.d.ts +9 -9
- package/dist/ui/toast.js +21 -14
- package/dist/ui/toggle.d.ts +5 -6
- package/dist/ui/toggle.js +3 -2
- package/dist/ui/toolbar.d.ts +15 -16
- package/dist/ui/toolbar.js +15 -4
- package/dist/ui/tooltip.d.ts +6 -13
- package/dist/ui/tooltip.js +7 -8
- package/dist/ui/tree.d.ts +18 -19
- package/dist/ui/tree.js +3 -2
- package/dist/ui/trigger-menu.d.ts +15 -16
- package/dist/ui/trigger-menu.js +5 -3
- package/dist/ui/use-switch-drag.d.ts +7 -0
- package/dist/ui/use-switch-drag.js +104 -0
- package/dist/user-ask.d.ts +24 -25
- package/package.json +15 -15
- package/dist/code-block-editor.d.ts +0 -59
- package/dist/code-block-editor.js +0 -250
- package/dist/knob-contracts/code-block-editor-knobs.d.ts +0 -5
- package/dist/knob-contracts/code-block-editor-knobs.js +0 -11
- package/dist/lib/code-block-shiki.d.ts +0 -9
- package/dist/lib/code-block-shiki.js +0 -6
- package/dist/skin.config.d.ts +0 -5
- package/dist/skin.config.js +0 -12
- package/dist/styles/recipes/code-block-editor.css +0 -136
- package/dist/styles/skin-theme.css +0 -137
- package/dist/styles/skin.css +0 -143
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import {
|
|
4
|
-
import { TooltipProvider } from "./tooltip.js";
|
|
3
|
+
import { useSkin } from "../skin-provider.js";
|
|
5
4
|
import { SIDEBAR_COOKIE_NAME } from "../control-props.js";
|
|
5
|
+
import { TooltipProvider } from "./tooltip.js";
|
|
6
6
|
import { useIsMobile } from "../hooks/use-mobile.js";
|
|
7
|
-
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
7
|
+
import { createContext, useContext, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
8
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
8
9
|
import { jsx } from "react/jsx-runtime";
|
|
9
10
|
//#region src/ui/sidebar-provider.tsx
|
|
10
11
|
const SIDEBAR_COOKIE_MAX_AGE = 604800;
|
|
@@ -12,21 +13,71 @@ const SIDEBAR_WIDTH = "16rem";
|
|
|
12
13
|
const SIDEBAR_WIDTH_ICON = "3rem";
|
|
13
14
|
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
14
15
|
const SIDEBAR_MOBILE_BREAKPOINT = 1024;
|
|
16
|
+
const SidebarElementsContext = createContext(null);
|
|
17
|
+
const SidebarSurfaceContext = createContext(null);
|
|
18
|
+
function useSidebarElements() {
|
|
19
|
+
const elements = useContext(SidebarElementsContext);
|
|
20
|
+
if (!elements) throw new Error("Sidebar parts must be used within a SidebarProvider.");
|
|
21
|
+
return elements;
|
|
22
|
+
}
|
|
23
|
+
function useSidebarSurface() {
|
|
24
|
+
const surface = useContext(SidebarSurfaceContext);
|
|
25
|
+
if (!surface) throw new Error("SidebarRail must be used within a Sidebar.");
|
|
26
|
+
return surface;
|
|
27
|
+
}
|
|
28
|
+
function focusOutsideCollapsedContent({ offcanvasRef, railRef, triggerRef }) {
|
|
29
|
+
const container = offcanvasRef.current;
|
|
30
|
+
if (!container?.contains(document.activeElement)) return;
|
|
31
|
+
const target = railRef.current ?? triggerRef.current;
|
|
32
|
+
if (target) target.focus({ preventScroll: true });
|
|
33
|
+
else container.focus({ preventScroll: true });
|
|
34
|
+
}
|
|
15
35
|
const SidebarContext = createContext(null);
|
|
16
36
|
function useSidebar() {
|
|
17
37
|
const context = useContext(SidebarContext);
|
|
18
38
|
if (!context) throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
19
39
|
return context;
|
|
20
40
|
}
|
|
21
|
-
function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange, persistOpen = true, keyboardShortcut = SIDEBAR_KEYBOARD_SHORTCUT, ref, className, style, children, ...props }) {
|
|
41
|
+
function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange, defaultWidth, minWidth = 224, maxWidth = 420, width: widthProp, onWidthChange, persistOpen = true, keyboardShortcut = SIDEBAR_KEYBOARD_SHORTCUT, ref, className, style, children, ...props }) {
|
|
42
|
+
const skin = useSkin();
|
|
22
43
|
const isMobile = useIsMobile(SIDEBAR_MOBILE_BREAKPOINT);
|
|
23
44
|
const [openMobile, setOpenMobile] = useState(false);
|
|
45
|
+
const wrapperRef = useRef(null);
|
|
46
|
+
const offcanvasRef = useRef(null);
|
|
47
|
+
const railRef = useRef(null);
|
|
48
|
+
const triggerRef = useRef(null);
|
|
49
|
+
const elements = {
|
|
50
|
+
wrapperRef,
|
|
51
|
+
offcanvasRef,
|
|
52
|
+
railRef,
|
|
53
|
+
triggerRef
|
|
54
|
+
};
|
|
55
|
+
const [internalWidth, setInternalWidth] = useState(defaultWidth);
|
|
56
|
+
function clampWidth(nextWidth) {
|
|
57
|
+
return Math.min(maxWidth, Math.max(minWidth, nextWidth));
|
|
58
|
+
}
|
|
59
|
+
const requestedWidth = widthProp ?? internalWidth;
|
|
60
|
+
const width = requestedWidth === void 0 ? void 0 : clampWidth(requestedWidth);
|
|
61
|
+
function setWidth(nextWidth) {
|
|
62
|
+
const clampedWidth = clampWidth(nextWidth);
|
|
63
|
+
if (widthProp === void 0) setInternalWidth(clampedWidth);
|
|
64
|
+
onWidthChange?.(clampedWidth);
|
|
65
|
+
}
|
|
24
66
|
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
25
67
|
const open = openProp ?? internalOpen;
|
|
68
|
+
useLayoutEffect(() => {
|
|
69
|
+
if (!open && !isMobile) focusOutsideCollapsedContent({
|
|
70
|
+
wrapperRef,
|
|
71
|
+
offcanvasRef,
|
|
72
|
+
railRef,
|
|
73
|
+
triggerRef
|
|
74
|
+
});
|
|
75
|
+
}, [open, isMobile]);
|
|
26
76
|
const setOpen = (value) => {
|
|
27
77
|
const openState = typeof value === "function" ? value(open) : value;
|
|
28
|
-
if (
|
|
29
|
-
|
|
78
|
+
if (!openState && !isMobile) focusOutsideCollapsedContent(elements);
|
|
79
|
+
if (openProp === void 0) setInternalOpen(openState);
|
|
80
|
+
onOpenChange?.(openState);
|
|
30
81
|
if (persistOpen) document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
31
82
|
};
|
|
32
83
|
const toggleSidebar = () => isMobile ? setOpenMobile((prev) => !prev) : setOpen(!open);
|
|
@@ -52,29 +103,38 @@ function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange, per
|
|
|
52
103
|
isMobile,
|
|
53
104
|
openMobile,
|
|
54
105
|
setOpenMobile,
|
|
55
|
-
toggleSidebar
|
|
106
|
+
toggleSidebar,
|
|
107
|
+
width,
|
|
108
|
+
setWidth,
|
|
109
|
+
minWidth,
|
|
110
|
+
maxWidth
|
|
56
111
|
};
|
|
57
112
|
const wrapperStyle = {
|
|
58
|
-
"--sidebar-width":
|
|
113
|
+
"--sidebar-width": skin.sidebarWidth ?? SIDEBAR_WIDTH,
|
|
59
114
|
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
|
60
|
-
...style
|
|
115
|
+
...style,
|
|
116
|
+
...width === void 0 ? {} : { "--sidebar-width": `${width}px` }
|
|
61
117
|
};
|
|
118
|
+
const wrapper = useRender({
|
|
119
|
+
defaultTagName: "div",
|
|
120
|
+
ref: [ref ?? null, wrapperRef],
|
|
121
|
+
props: {
|
|
122
|
+
...props,
|
|
123
|
+
"data-control-ui": "sidebar",
|
|
124
|
+
"data-control-family": "sidebar",
|
|
125
|
+
"data-slot": "wrapper",
|
|
126
|
+
style: wrapperStyle,
|
|
127
|
+
className: cn("group/sidebar-wrapper flex min-h-svh w-full", className),
|
|
128
|
+
children
|
|
129
|
+
}
|
|
130
|
+
});
|
|
62
131
|
return /* @__PURE__ */ jsx(SidebarContext.Provider, {
|
|
63
132
|
value: contextValue,
|
|
64
|
-
children: /* @__PURE__ */ jsx(
|
|
65
|
-
|
|
66
|
-
children: /* @__PURE__ */ jsx(
|
|
67
|
-
ref,
|
|
68
|
-
"data-control-ui": "sidebar",
|
|
69
|
-
"data-control-family": "sidebar",
|
|
70
|
-
"data-slot": "wrapper",
|
|
71
|
-
style: wrapperStyle,
|
|
72
|
-
className: cn("group/sidebar-wrapper flex min-h-svh w-full", className),
|
|
73
|
-
...props,
|
|
74
|
-
children
|
|
75
|
-
})
|
|
133
|
+
children: /* @__PURE__ */ jsx(SidebarElementsContext.Provider, {
|
|
134
|
+
value: elements,
|
|
135
|
+
children: /* @__PURE__ */ jsx(TooltipProvider, { children: wrapper })
|
|
76
136
|
})
|
|
77
137
|
});
|
|
78
138
|
}
|
|
79
139
|
//#endregion
|
|
80
|
-
export { SidebarProvider, useSidebar };
|
|
140
|
+
export { SidebarProvider, SidebarSurfaceContext, useSidebar, useSidebarElements, useSidebarSurface };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SidebarKnobStyle } from "../knob-contracts/sidebar-knobs.js";
|
|
2
|
+
import { CSSProperties, ComponentProps } from "react";
|
|
3
|
+
//#region src/ui/sidebar-resize-rail.d.ts
|
|
4
|
+
export type SidebarResizeRailProps = ComponentProps<"div"> & {
|
|
5
|
+
style?: CSSProperties & SidebarKnobStyle;
|
|
6
|
+
};
|
|
7
|
+
export declare function SidebarResizeRail({ className, ref, onPointerDown, onClick, onKeyDown, ...props }: SidebarResizeRailProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
8
|
+
//#endregion
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { useSidebar, useSidebarElements, useSidebarSurface } from "./sidebar-provider.js";
|
|
4
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
5
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/ui/sidebar-resize-rail.tsx
|
|
8
|
+
const DRAG_THRESHOLD_PX = 5;
|
|
9
|
+
const KEYBOARD_STEP_PX = 10;
|
|
10
|
+
function SidebarResizeRail({ className, ref, onPointerDown, onClick, onKeyDown, ...props }) {
|
|
11
|
+
const { open, setOpen, setWidth, toggleSidebar, minWidth, maxWidth } = useSidebar();
|
|
12
|
+
const { wrapperRef, railRef } = useSidebarElements();
|
|
13
|
+
const { side, collapsible } = useSidebarSurface();
|
|
14
|
+
const widthMeasureRef = useRef(null);
|
|
15
|
+
const cancelGestureRef = useRef(null);
|
|
16
|
+
const draggedRef = useRef(false);
|
|
17
|
+
const [measuredWidth, setMeasuredWidth] = useState();
|
|
18
|
+
useLayoutEffect(() => {
|
|
19
|
+
const measure = widthMeasureRef.current;
|
|
20
|
+
if (!measure) return;
|
|
21
|
+
const updateMeasuredWidth = () => setMeasuredWidth(Math.round(measure.getBoundingClientRect().width));
|
|
22
|
+
updateMeasuredWidth();
|
|
23
|
+
const observer = new ResizeObserver(updateMeasuredWidth);
|
|
24
|
+
observer.observe(measure);
|
|
25
|
+
return () => observer.disconnect();
|
|
26
|
+
}, []);
|
|
27
|
+
useEffect(() => () => cancelGestureRef.current?.(), []);
|
|
28
|
+
function clampWidth(nextWidth) {
|
|
29
|
+
return Math.min(maxWidth, Math.max(minWidth, nextWidth));
|
|
30
|
+
}
|
|
31
|
+
function handlePointerDown(event) {
|
|
32
|
+
onPointerDown?.(event);
|
|
33
|
+
if (event.defaultPrevented || event.button !== 0) return;
|
|
34
|
+
const mountedWrapper = wrapperRef.current;
|
|
35
|
+
const measure = widthMeasureRef.current;
|
|
36
|
+
if (!mountedWrapper || !measure) return;
|
|
37
|
+
const wrapper = mountedWrapper;
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
cancelGestureRef.current?.();
|
|
40
|
+
draggedRef.current = false;
|
|
41
|
+
const handle = event.currentTarget;
|
|
42
|
+
handle.focus({ preventScroll: true });
|
|
43
|
+
handle.setPointerCapture(event.pointerId);
|
|
44
|
+
const pointerId = event.pointerId;
|
|
45
|
+
const startX = event.clientX;
|
|
46
|
+
const wrapperBounds = wrapper.getBoundingClientRect();
|
|
47
|
+
const initialWidth = measure.getBoundingClientRect().width;
|
|
48
|
+
const previousWidth = wrapper.style.getPropertyValue("--sidebar-width");
|
|
49
|
+
const previousCursor = document.body.style.cursor;
|
|
50
|
+
const previousUserSelect = document.body.style.userSelect;
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
let draftWidth = initialWidth;
|
|
53
|
+
const initiallyCollapsed = !open && collapsible !== "none";
|
|
54
|
+
let collapsedDuringDrag = initiallyCollapsed;
|
|
55
|
+
function restoreWidth() {
|
|
56
|
+
wrapper.style.setProperty("--sidebar-width", previousWidth);
|
|
57
|
+
}
|
|
58
|
+
function endGesture() {
|
|
59
|
+
controller.abort();
|
|
60
|
+
document.body.style.cursor = previousCursor;
|
|
61
|
+
document.body.style.userSelect = previousUserSelect;
|
|
62
|
+
wrapper.removeAttribute("data-resizing");
|
|
63
|
+
handle.removeAttribute("data-resizing");
|
|
64
|
+
if (handle.hasPointerCapture(pointerId)) handle.releasePointerCapture(pointerId);
|
|
65
|
+
cancelGestureRef.current = null;
|
|
66
|
+
}
|
|
67
|
+
function cancelGesture() {
|
|
68
|
+
endGesture();
|
|
69
|
+
restoreWidth();
|
|
70
|
+
draggedRef.current = false;
|
|
71
|
+
if (collapsedDuringDrag !== initiallyCollapsed) setOpen(open);
|
|
72
|
+
}
|
|
73
|
+
cancelGestureRef.current = cancelGesture;
|
|
74
|
+
function updateCollapse(cursorWidth) {
|
|
75
|
+
const shouldCollapse = collapsible !== "none" && cursorWidth < minWidth;
|
|
76
|
+
if (shouldCollapse !== collapsedDuringDrag) {
|
|
77
|
+
collapsedDuringDrag = shouldCollapse;
|
|
78
|
+
setOpen(!shouldCollapse);
|
|
79
|
+
}
|
|
80
|
+
return shouldCollapse;
|
|
81
|
+
}
|
|
82
|
+
function movePointer(pointer) {
|
|
83
|
+
if (pointer.pointerId !== pointerId) return;
|
|
84
|
+
const withinClickDistance = Math.abs(pointer.clientX - startX) <= DRAG_THRESHOLD_PX;
|
|
85
|
+
if (!draggedRef.current && withinClickDistance) return;
|
|
86
|
+
draggedRef.current = true;
|
|
87
|
+
document.body.style.cursor = "col-resize";
|
|
88
|
+
document.body.style.userSelect = "none";
|
|
89
|
+
wrapper.setAttribute("data-resizing", "true");
|
|
90
|
+
handle.setAttribute("data-resizing", "true");
|
|
91
|
+
const cursorWidth = side === "left" ? pointer.clientX - wrapperBounds.left : wrapperBounds.right - pointer.clientX;
|
|
92
|
+
if (updateCollapse(cursorWidth)) return;
|
|
93
|
+
draftWidth = clampWidth(cursorWidth);
|
|
94
|
+
wrapper.style.setProperty("--sidebar-width", `${draftWidth}px`);
|
|
95
|
+
}
|
|
96
|
+
function finishPointer(pointer) {
|
|
97
|
+
if (pointer.pointerId !== pointerId) return;
|
|
98
|
+
endGesture();
|
|
99
|
+
restoreWidth();
|
|
100
|
+
if (draggedRef.current && !collapsedDuringDrag) setWidth(draftWidth);
|
|
101
|
+
}
|
|
102
|
+
function cancelPointer(pointer) {
|
|
103
|
+
if (pointer.pointerId === pointerId) cancelGesture();
|
|
104
|
+
}
|
|
105
|
+
function cancelWithEscape(keyboard) {
|
|
106
|
+
if (keyboard.key !== "Escape") return;
|
|
107
|
+
keyboard.preventDefault();
|
|
108
|
+
cancelGesture();
|
|
109
|
+
}
|
|
110
|
+
window.addEventListener("pointermove", movePointer, { signal: controller.signal });
|
|
111
|
+
window.addEventListener("pointerup", finishPointer, { signal: controller.signal });
|
|
112
|
+
window.addEventListener("pointercancel", cancelPointer, { signal: controller.signal });
|
|
113
|
+
handle.addEventListener("lostpointercapture", cancelPointer, { signal: controller.signal });
|
|
114
|
+
window.addEventListener("blur", cancelGesture, { signal: controller.signal });
|
|
115
|
+
window.addEventListener("keydown", cancelWithEscape, { signal: controller.signal });
|
|
116
|
+
}
|
|
117
|
+
function handleClick(event) {
|
|
118
|
+
onClick?.(event);
|
|
119
|
+
if (event.defaultPrevented) return;
|
|
120
|
+
if (draggedRef.current) {
|
|
121
|
+
draggedRef.current = false;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (collapsible !== "none") toggleSidebar();
|
|
125
|
+
}
|
|
126
|
+
function resizeWithArrow(expand) {
|
|
127
|
+
if (isCollapsed) {
|
|
128
|
+
if (expand) setOpen(true);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (measuredWidth === void 0) return;
|
|
132
|
+
setWidth(clampWidth(measuredWidth + (expand ? KEYBOARD_STEP_PX : -10)));
|
|
133
|
+
}
|
|
134
|
+
function expandToWidth(nextWidth) {
|
|
135
|
+
if (collapsible !== "none") setOpen(true);
|
|
136
|
+
setWidth(nextWidth);
|
|
137
|
+
}
|
|
138
|
+
function handleKeyDown(event) {
|
|
139
|
+
onKeyDown?.(event);
|
|
140
|
+
if (event.defaultPrevented) return;
|
|
141
|
+
switch (event.key) {
|
|
142
|
+
case "Enter":
|
|
143
|
+
case " ":
|
|
144
|
+
event.preventDefault();
|
|
145
|
+
if (collapsible !== "none") toggleSidebar();
|
|
146
|
+
return;
|
|
147
|
+
case "Home":
|
|
148
|
+
case "End":
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
expandToWidth(event.key === "Home" ? minWidth : maxWidth);
|
|
151
|
+
return;
|
|
152
|
+
case "ArrowLeft":
|
|
153
|
+
case "ArrowRight":
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
resizeWithArrow(event.key === (side === "left" ? "ArrowRight" : "ArrowLeft"));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const isCollapsed = !open && collapsible !== "none";
|
|
160
|
+
const widthDescription = measuredWidth === void 0 ? void 0 : `${measuredWidth} pixels`;
|
|
161
|
+
return useRender({
|
|
162
|
+
defaultTagName: "div",
|
|
163
|
+
ref: [ref ?? null, railRef],
|
|
164
|
+
props: {
|
|
165
|
+
...props,
|
|
166
|
+
role: "separator",
|
|
167
|
+
"aria-orientation": "vertical",
|
|
168
|
+
"aria-label": props["aria-label"] ?? "Resize sidebar",
|
|
169
|
+
"aria-valuenow": isCollapsed ? 0 : measuredWidth,
|
|
170
|
+
"aria-valuemin": collapsible === "none" ? minWidth : 0,
|
|
171
|
+
"aria-valuemax": maxWidth,
|
|
172
|
+
"aria-valuetext": isCollapsed ? "collapsed" : widthDescription,
|
|
173
|
+
tabIndex: 0,
|
|
174
|
+
"data-control-ui": "sidebar",
|
|
175
|
+
"data-control-family": "sidebar",
|
|
176
|
+
"data-slot": "rail",
|
|
177
|
+
"data-resizable": "",
|
|
178
|
+
"data-resize-ready": measuredWidth === void 0 ? void 0 : "",
|
|
179
|
+
onPointerDown: handlePointerDown,
|
|
180
|
+
onClick: handleClick,
|
|
181
|
+
onKeyDown: handleKeyDown,
|
|
182
|
+
className: cn("absolute inset-y-0 z-20 hidden cursor-col-resize touch-none outline-hidden group-data-[side=left]:-right-1 group-data-[side=right]:-left-1 group-data-[side=left]:group-data-[collapsible=offcanvas]:-right-2 group-data-[side=right]:group-data-[collapsible=offcanvas]:-left-2 lg:block", className),
|
|
183
|
+
children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
184
|
+
ref: widthMeasureRef,
|
|
185
|
+
"aria-hidden": true,
|
|
186
|
+
className: "pointer-events-none invisible absolute w-(--sidebar-width)"
|
|
187
|
+
}), props.children] })
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
export { SidebarResizeRail };
|
package/dist/ui/sidebar.d.ts
CHANGED
|
@@ -1,31 +1,37 @@
|
|
|
1
1
|
import { Button } from "./button.js";
|
|
2
2
|
import { SidebarKnobStyle } from "../knob-contracts/sidebar-knobs.js";
|
|
3
|
-
import {
|
|
3
|
+
import { SidebarLayout } from "../skin.js";
|
|
4
|
+
import { SidebarGroup, SidebarGroupContent, SidebarGroupContentProps, SidebarGroupLabel, SidebarGroupLabelProps, SidebarMenu, SidebarMenuAction, SidebarMenuActionProps, SidebarMenuButton, SidebarMenuButtonProps, SidebarMenuButtonSize, SidebarMenuButtonVariant, SidebarMenuItem, SidebarMenuSub, SidebarSelectionIndicator, sidebarMenuButtonSizes, sidebarMenuButtonVariants } from "./sidebar-menu.js";
|
|
4
5
|
import { SidebarProvider, SidebarProviderProps, SidebarStyle, useSidebar } from "./sidebar-provider.js";
|
|
6
|
+
import { SidebarResizeRailProps } from "./sidebar-resize-rail.js";
|
|
5
7
|
import { CSSProperties, ComponentProps } from "react";
|
|
6
8
|
//#region src/ui/sidebar.d.ts
|
|
7
|
-
type SidebarRailProps = Omit<ComponentProps<"button">, "style"> & {
|
|
9
|
+
export type SidebarRailProps = (Omit<ComponentProps<"button">, "style"> & {
|
|
10
|
+
resizable?: false;
|
|
8
11
|
style?: CSSProperties & SidebarKnobStyle;
|
|
9
|
-
}
|
|
10
|
-
|
|
12
|
+
}) | (SidebarResizeRailProps & {
|
|
13
|
+
resizable: true;
|
|
14
|
+
});
|
|
15
|
+
export type SidebarInsetProps = Omit<ComponentProps<"main">, "style"> & {
|
|
11
16
|
style?: CSSProperties & SidebarKnobStyle;
|
|
12
17
|
};
|
|
13
18
|
type SidebarSurfaceStyle = CSSProperties & SidebarKnobStyle;
|
|
14
|
-
|
|
19
|
+
export type SidebarProps = Omit<ComponentProps<"div">, "style"> & {
|
|
15
20
|
side?: "left" | "right";
|
|
16
|
-
variant?:
|
|
21
|
+
variant?: SidebarLayout;
|
|
17
22
|
collapsible?: "offcanvas" | "icon" | "none";
|
|
18
23
|
style?: SidebarSurfaceStyle;
|
|
19
|
-
}
|
|
20
|
-
declare function
|
|
21
|
-
declare function
|
|
22
|
-
declare function
|
|
23
|
-
declare function
|
|
24
|
+
};
|
|
25
|
+
export declare function Sidebar({ side, collapsible, ...props }: SidebarProps): import("react").JSX.Element;
|
|
26
|
+
export declare function SidebarTrigger({ className, onClick, size, ref, ...props }: ComponentProps<typeof Button>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
27
|
+
export declare function SidebarRail(props: SidebarRailProps): any;
|
|
28
|
+
export declare function SidebarInset({ className, ...props }: SidebarInsetProps): import("react").JSX.Element;
|
|
29
|
+
export declare function SidebarHeader({ className, ...props }: ComponentProps<"div"> & {
|
|
24
30
|
style?: CSSProperties & SidebarKnobStyle;
|
|
25
31
|
}): import("react").JSX.Element;
|
|
26
|
-
declare function SidebarFooter({ className, ...props }: ComponentProps<"div"> & {
|
|
32
|
+
export declare function SidebarFooter({ className, ...props }: ComponentProps<"div"> & {
|
|
27
33
|
style?: CSSProperties & SidebarKnobStyle;
|
|
28
34
|
}): import("react").JSX.Element;
|
|
29
|
-
declare function SidebarContent({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
35
|
+
export declare function SidebarContent({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
30
36
|
//#endregion
|
|
31
|
-
export {
|
|
37
|
+
export { SidebarGroup, SidebarGroupContent, type SidebarGroupContentProps, SidebarGroupLabel, type SidebarGroupLabelProps, SidebarMenu, SidebarMenuAction, type SidebarMenuActionProps, SidebarMenuButton, type SidebarMenuButtonProps, type SidebarMenuButtonSize, type SidebarMenuButtonVariant, SidebarMenuItem, SidebarMenuSub, SidebarProvider, type SidebarProviderProps, type SidebarSelectionIndicator, type SidebarStyle, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
|
package/dist/ui/sidebar.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import {
|
|
3
|
+
import { useSkin } from "../skin-provider.js";
|
|
4
4
|
import { Button } from "./button.js";
|
|
5
5
|
import { ScrollArea } from "./scroll-area.js";
|
|
6
6
|
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "./sheet.js";
|
|
7
|
-
import { SidebarProvider, useSidebar } from "./sidebar-provider.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { SidebarProvider, SidebarSurfaceContext, useSidebar, useSidebarElements, useSidebarSurface } from "./sidebar-provider.js";
|
|
8
|
+
import { SidebarResizeRail } from "./sidebar-resize-rail.js";
|
|
9
|
+
import { SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, sidebarMenuButtonSizes, sidebarMenuButtonVariants } from "./sidebar-menu.js";
|
|
10
|
+
import { useState } from "react";
|
|
11
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
12
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
13
|
import { PanelLeftIcon } from "lucide-react";
|
|
14
|
+
import { createPortal } from "react-dom";
|
|
11
15
|
//#region src/ui/sidebar.tsx
|
|
12
16
|
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
13
17
|
const sidebarTriggerWidth = {
|
|
@@ -16,19 +20,64 @@ const sidebarTriggerWidth = {
|
|
|
16
20
|
md: "w-[var(--control-h-md)]",
|
|
17
21
|
lg: "w-[var(--control-h-lg)]"
|
|
18
22
|
};
|
|
19
|
-
function Sidebar({ side = "left",
|
|
23
|
+
function Sidebar({ side = "left", collapsible = "offcanvas", ...props }) {
|
|
24
|
+
const [railContainer, setRailContainer] = useState(null);
|
|
25
|
+
return /* @__PURE__ */ jsx(SidebarSurfaceContext.Provider, {
|
|
26
|
+
value: {
|
|
27
|
+
side,
|
|
28
|
+
collapsible,
|
|
29
|
+
railContainer
|
|
30
|
+
},
|
|
31
|
+
children: /* @__PURE__ */ jsx(SidebarSurface, {
|
|
32
|
+
...props,
|
|
33
|
+
railContainerRef: setRailContainer
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function SidebarSurface({ variant, ref, className, children, style, railContainerRef, ...props }) {
|
|
38
|
+
const { side, collapsible } = useSidebarSurface();
|
|
39
|
+
const { offcanvasRef } = useSidebarElements();
|
|
40
|
+
const skin = useSkin();
|
|
20
41
|
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
21
|
-
const resolvedVariant = variant ??
|
|
22
|
-
|
|
42
|
+
const resolvedVariant = variant ?? skin.sidebarLayout ?? "sidebar";
|
|
43
|
+
const container = useRender({
|
|
44
|
+
defaultTagName: "div",
|
|
45
|
+
ref: collapsible === "offcanvas" ? [ref ?? null, offcanvasRef] : ref,
|
|
46
|
+
props: {
|
|
47
|
+
...props,
|
|
48
|
+
"data-control-ui": "sidebar",
|
|
49
|
+
"data-control-family": "sidebar",
|
|
50
|
+
"data-slot": "container",
|
|
51
|
+
tabIndex: -1,
|
|
52
|
+
className: cn("fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) lg:flex", side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", resolvedVariant === "floating" || resolvedVariant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)", className),
|
|
53
|
+
children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
54
|
+
"data-control-ui": "sidebar",
|
|
55
|
+
"data-control-family": "sidebar",
|
|
56
|
+
"data-slot": "inner",
|
|
57
|
+
className: "flex h-full w-full flex-col",
|
|
58
|
+
inert: state === "collapsed" && collapsible === "offcanvas",
|
|
59
|
+
children
|
|
60
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
61
|
+
ref: railContainerRef,
|
|
62
|
+
className: "contents"
|
|
63
|
+
})] })
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
if (collapsible === "none") return /* @__PURE__ */ jsxs("div", {
|
|
23
67
|
ref,
|
|
24
68
|
"data-control-ui": "sidebar",
|
|
25
69
|
"data-control-family": "sidebar",
|
|
26
70
|
"data-slot": "root",
|
|
27
71
|
"data-surface": "panel",
|
|
28
|
-
|
|
72
|
+
"data-variant": resolvedVariant,
|
|
73
|
+
"data-side": side,
|
|
74
|
+
className: cn("group relative flex h-full w-(--sidebar-width) flex-col", className),
|
|
29
75
|
style,
|
|
30
76
|
...props,
|
|
31
|
-
children
|
|
77
|
+
children: [children, /* @__PURE__ */ jsx("div", {
|
|
78
|
+
ref: railContainerRef,
|
|
79
|
+
className: "contents"
|
|
80
|
+
})]
|
|
32
81
|
});
|
|
33
82
|
if (isMobile) {
|
|
34
83
|
const mobileSheetStyle = {
|
|
@@ -51,6 +100,7 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
|
|
|
51
100
|
"data-control-family": "sidebar",
|
|
52
101
|
"data-slot": "root",
|
|
53
102
|
"data-surface": "panel",
|
|
103
|
+
"data-variant": resolvedVariant,
|
|
54
104
|
"data-mobile": "",
|
|
55
105
|
"data-side": side,
|
|
56
106
|
className: cn("flex min-h-0 flex-1 flex-col", className),
|
|
@@ -68,7 +118,7 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
|
|
|
68
118
|
});
|
|
69
119
|
}
|
|
70
120
|
return /* @__PURE__ */ jsxs("div", {
|
|
71
|
-
className: "group peer hidden lg:block",
|
|
121
|
+
className: cn("group peer hidden lg:block", side === "right" && "order-last"),
|
|
72
122
|
"data-control-ui": "sidebar",
|
|
73
123
|
"data-control-family": "sidebar",
|
|
74
124
|
"data-slot": "root",
|
|
@@ -83,57 +133,72 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
|
|
|
83
133
|
"data-control-family": "sidebar",
|
|
84
134
|
"data-slot": "gap",
|
|
85
135
|
className: cn("relative w-(--sidebar-width)", "group-data-[collapsible=offcanvas]:w-0", resolvedVariant === "floating" || resolvedVariant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)")
|
|
86
|
-
}),
|
|
87
|
-
ref,
|
|
88
|
-
"data-control-ui": "sidebar",
|
|
89
|
-
"data-control-family": "sidebar",
|
|
90
|
-
"data-slot": "container",
|
|
91
|
-
className: cn("fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) lg:flex", side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", resolvedVariant === "floating" || resolvedVariant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)", className),
|
|
92
|
-
...props,
|
|
93
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
94
|
-
"data-control-ui": "sidebar",
|
|
95
|
-
"data-control-family": "sidebar",
|
|
96
|
-
"data-slot": "inner",
|
|
97
|
-
className: "flex h-full w-full flex-col",
|
|
98
|
-
children
|
|
99
|
-
})
|
|
100
|
-
})]
|
|
136
|
+
}), container]
|
|
101
137
|
});
|
|
102
138
|
}
|
|
103
|
-
function SidebarTrigger({ className, onClick, size = "sm", ...props }) {
|
|
139
|
+
function SidebarTrigger({ className, onClick, size = "sm", ref, ...props }) {
|
|
104
140
|
const { toggleSidebar, isMobile, openMobile, open } = useSidebar();
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
className: "
|
|
120
|
-
|
|
121
|
-
|
|
141
|
+
const { triggerRef, railRef } = useSidebarElements();
|
|
142
|
+
return useRender({
|
|
143
|
+
defaultTagName: "button",
|
|
144
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
145
|
+
variant: "ghost",
|
|
146
|
+
size
|
|
147
|
+
}),
|
|
148
|
+
ref: [ref ?? null, triggerRef],
|
|
149
|
+
props: {
|
|
150
|
+
...props,
|
|
151
|
+
"data-control-ui": "sidebar",
|
|
152
|
+
"data-slot": "trigger",
|
|
153
|
+
"data-sidebar-trigger": "",
|
|
154
|
+
"aria-expanded": isMobile ? openMobile : open,
|
|
155
|
+
className: cn(sidebarTriggerWidth[size], "px-0", className),
|
|
156
|
+
onClick: (event) => {
|
|
157
|
+
onClick?.(event);
|
|
158
|
+
if (event.defaultPrevented) return;
|
|
159
|
+
toggleSidebar();
|
|
160
|
+
if (!isMobile && !open) railRef.current?.focus({ preventScroll: true });
|
|
161
|
+
},
|
|
162
|
+
children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(PanelLeftIcon, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
|
|
163
|
+
className: "sr-only",
|
|
164
|
+
children: "Toggle Sidebar"
|
|
165
|
+
})] })
|
|
166
|
+
}
|
|
122
167
|
});
|
|
123
168
|
}
|
|
124
|
-
function SidebarRail(
|
|
125
|
-
const {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
function SidebarRail(props) {
|
|
170
|
+
const { isMobile } = useSidebar();
|
|
171
|
+
const { railContainer } = useSidebarSurface();
|
|
172
|
+
if (isMobile || !railContainer) return null;
|
|
173
|
+
if (props.resizable) {
|
|
174
|
+
const { resizable, ...resizeProps } = props;
|
|
175
|
+
return createPortal(/* @__PURE__ */ jsx(SidebarResizeRail, { ...resizeProps }), railContainer);
|
|
176
|
+
}
|
|
177
|
+
const { resizable, ...toggleProps } = props;
|
|
178
|
+
return createPortal(/* @__PURE__ */ jsx(SidebarToggleRail, { ...toggleProps }), railContainer);
|
|
179
|
+
}
|
|
180
|
+
function SidebarToggleRail({ className, ref, onClick, ...props }) {
|
|
181
|
+
const { toggleSidebar, open } = useSidebar();
|
|
182
|
+
const { railRef } = useSidebarElements();
|
|
183
|
+
return useRender({
|
|
184
|
+
defaultTagName: "button",
|
|
185
|
+
ref: [ref ?? null, railRef],
|
|
186
|
+
props: {
|
|
187
|
+
...props,
|
|
188
|
+
type: "button",
|
|
189
|
+
"data-control-ui": "sidebar",
|
|
190
|
+
"data-control-family": "sidebar",
|
|
191
|
+
"data-slot": "rail",
|
|
192
|
+
"aria-label": props["aria-label"] ?? "Toggle Sidebar",
|
|
193
|
+
"aria-expanded": open,
|
|
194
|
+
tabIndex: -1,
|
|
195
|
+
onClick: (event) => {
|
|
196
|
+
onClick?.(event);
|
|
197
|
+
if (!event.defaultPrevented) toggleSidebar();
|
|
198
|
+
},
|
|
199
|
+
title: "Toggle Sidebar",
|
|
200
|
+
className: cn("absolute inset-y-0 z-20 hidden -translate-x-1/2 group-data-[side=left]:-right-4 group-data-[side=right]:left-0 lg:flex", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "group-data-[collapsible=offcanvas]:translate-x-0", className)
|
|
201
|
+
}
|
|
137
202
|
});
|
|
138
203
|
}
|
|
139
204
|
function SidebarInset({ className, ...props }) {
|
|
@@ -180,4 +245,4 @@ function SidebarContent({ className, children, ...props }) {
|
|
|
180
245
|
});
|
|
181
246
|
}
|
|
182
247
|
//#endregion
|
|
183
|
-
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider, SidebarRail, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
|
|
248
|
+
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider, SidebarRail, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
|
package/dist/ui/skeleton.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { SkeletonKnobStyle } from "../knob-contracts/skeleton-knobs.js";
|
|
2
2
|
import { CSSProperties, ComponentProps } from "react";
|
|
3
3
|
//#region src/ui/skeleton.d.ts
|
|
4
|
-
declare
|
|
4
|
+
export declare const skeletonVariants: readonly ["shimmer", "pulse", "none"];
|
|
5
|
+
export type SkeletonVariant = (typeof skeletonVariants)[number];
|
|
6
|
+
export type SkeletonProps = Omit<ComponentProps<"div">, "style"> & {
|
|
5
7
|
style?: CSSProperties & SkeletonKnobStyle;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
8
|
+
variant?: SkeletonVariant;
|
|
9
|
+
};
|
|
10
|
+
export declare function Skeleton({ variant, className, ...props }: SkeletonProps): import("react").JSX.Element;
|
|
11
|
+
//#endregion
|