@ctrl-ui/react 0.8.7 → 0.8.8
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/dist/action-bar.d.ts +15 -7
- package/dist/action-bar.js +40 -20
- package/dist/activity.js +8 -16
- package/dist/audio-recorder.d.ts +14 -4
- package/dist/audio-recorder.js +82 -29
- package/dist/audio-visualizer.js +1 -1
- package/dist/blocks/coding-agent.js +39 -39
- package/dist/blocks/design-canvas-inspector.js +2 -2
- package/dist/blocks/design-canvas.d.ts +5 -1
- package/dist/blocks/design-canvas.js +200 -94
- package/dist/blocks/discussion.d.ts +28 -0
- package/dist/blocks/discussion.js +67 -0
- package/dist/blocks/file-explorer-data.d.ts +1 -0
- package/dist/blocks/file-explorer-data.js +4 -1
- package/dist/blocks/file-explorer.d.ts +9 -1
- package/dist/blocks/file-explorer.js +461 -192
- package/dist/blocks/settings.d.ts +2 -1
- package/dist/blocks/settings.js +102 -80
- package/dist/blocks/team-chat.d.ts +12 -0
- package/dist/blocks/team-chat.js +26 -0
- package/dist/blocks/theme-toggle.js +23 -31
- package/dist/chat-composer-attachment.d.ts +4 -1
- package/dist/chat-composer-attachment.js +35 -10
- package/dist/chat-composer-editor/extensions/mention.d.ts +5 -1
- package/dist/chat-composer-editor/extensions/mention.js +58 -27
- package/dist/chat-composer-editor/ghost.js +2 -4
- package/dist/chat-composer-editor/types.d.ts +5 -0
- package/dist/chat-composer-editor.d.ts +1 -1
- package/dist/chat-composer-editor.js +57 -30
- package/dist/chat-composer.d.ts +13 -32
- package/dist/chat-composer.js +53 -13
- package/dist/chat-layout.d.ts +19 -0
- package/dist/chat-layout.js +91 -40
- package/dist/chat-message/social.d.ts +26 -0
- package/dist/chat-message/social.js +122 -0
- package/dist/chat-message.d.ts +28 -29
- package/dist/chat-message.js +106 -25
- package/dist/context.d.ts +2 -2
- package/dist/context.js +39 -24
- package/dist/dynamic-notification-canvas-loop.d.ts +24 -0
- package/dist/dynamic-notification-canvas-loop.js +113 -0
- package/dist/dynamic-notification-glass.js +23 -114
- package/dist/dynamic-notification-liquid.js +14 -118
- package/dist/dynamic-notification.d.ts +16 -8
- package/dist/dynamic-notification.js +86 -23
- package/dist/email/email-brand.d.ts +7 -4
- package/dist/email/email-brand.js +9 -6
- package/dist/email/email-code.d.ts +3 -2
- package/dist/email/email-code.js +11 -9
- package/dist/email/email-footer.d.ts +5 -3
- package/dist/email/email-footer.js +11 -5
- package/dist/email/email.d.ts +31 -9
- package/dist/email/email.js +50 -26
- package/dist/email/templates.d.ts +10 -9
- package/dist/email/templates.js +102 -38
- package/dist/email/theme.js +1 -1
- package/dist/environment-variables.d.ts +4 -2
- package/dist/environment-variables.js +52 -32
- package/dist/filter-bar/editor.js +20 -8
- package/dist/filter-bar/model.d.ts +1 -0
- package/dist/filter-bar/model.js +10 -1
- package/dist/filter-bar/motion.js +4 -4
- package/dist/filter-bar/parts.js +20 -9
- package/dist/filter-bar/types.d.ts +1 -0
- package/dist/filter-bar.js +20 -14
- package/dist/hooks/use-audio-recorder.js +12 -6
- package/dist/hooks/use-chat-composer.d.ts +19 -7
- package/dist/hooks/use-chat-composer.js +32 -5
- package/dist/hooks/use-chat-message.d.ts +28 -2
- package/dist/hooks/use-chat-message.js +41 -10
- package/dist/hooks/use-chat-thread-scroll.js +43 -7
- package/dist/hooks/use-color-area.d.ts +3 -3
- package/dist/hooks/use-color-area.js +13 -12
- package/dist/hooks/use-copy-to-clipboard.d.ts +2 -1
- package/dist/hooks/use-copy-to-clipboard.js +20 -20
- package/dist/hooks/use-dynamic-notification.d.ts +6 -2
- package/dist/hooks/use-dynamic-notification.js +26 -10
- package/dist/hooks/use-mobile.d.ts +3 -2
- package/dist/hooks/use-mobile.js +8 -4
- package/dist/hooks/use-textarea-trigger-menu.js +2 -1
- package/dist/hooks/use-trigger-menu.d.ts +54 -0
- package/dist/hooks/use-trigger-menu.js +102 -47
- package/dist/hooks/use-user-ask.d.ts +2 -0
- package/dist/hooks/use-user-ask.js +35 -41
- package/dist/inline-attachment.d.ts +6 -2
- package/dist/inline-attachment.js +36 -15
- package/dist/inline-citation.d.ts +12 -5
- package/dist/inline-citation.js +26 -17
- package/dist/knob-contracts/audio-recorder-knobs.d.ts +1 -1
- package/dist/knob-contracts/audio-recorder-knobs.js +2 -1
- package/dist/knob-contracts/audio-visualizer-knobs.d.ts +1 -1
- package/dist/knob-contracts/audio-visualizer-knobs.js +2 -1
- package/dist/knob-contracts/avatar-knobs.d.ts +1 -1
- package/dist/knob-contracts/avatar-knobs.js +6 -1
- package/dist/knob-contracts/badge-knobs.d.ts +1 -1
- package/dist/knob-contracts/badge-knobs.js +2 -1
- package/dist/knob-contracts/breadcrumb-knobs.d.ts +4 -0
- package/dist/knob-contracts/breadcrumb-knobs.js +8 -0
- package/dist/knob-contracts/button-knobs.d.ts +1 -1
- package/dist/knob-contracts/button-knobs.js +1 -0
- package/dist/knob-contracts/chat-message-knobs.d.ts +1 -1
- package/dist/knob-contracts/chat-message-knobs.js +8 -1
- package/dist/knob-contracts/code-diff-knobs.d.ts +1 -1
- package/dist/knob-contracts/code-diff-knobs.js +2 -0
- package/dist/knob-contracts/code-knobs.d.ts +1 -1
- package/dist/knob-contracts/code-knobs.js +2 -1
- package/dist/knob-contracts/dynamic-notification-knobs.d.ts +1 -1
- package/dist/knob-contracts/dynamic-notification-knobs.js +2 -0
- package/dist/knob-contracts/emoji-picker-knobs.d.ts +4 -0
- package/dist/knob-contracts/emoji-picker-knobs.js +10 -0
- package/dist/knob-contracts/field-knobs.d.ts +1 -1
- package/dist/knob-contracts/field-knobs.js +5 -1
- package/dist/knob-contracts/filter-bar-knobs.d.ts +1 -1
- package/dist/knob-contracts/filter-bar-knobs.js +1 -2
- package/dist/knob-contracts/markdown-knobs.d.ts +1 -1
- package/dist/knob-contracts/markdown-knobs.js +3 -1
- package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/page-layout-knobs.js +2 -1
- package/dist/knob-contracts/popup-knobs.d.ts +1 -1
- package/dist/knob-contracts/popup-knobs.js +27 -0
- package/dist/knob-contracts/range-knobs.d.ts +1 -1
- package/dist/knob-contracts/range-knobs.js +1 -0
- package/dist/knob-contracts/rich-tooltip-knobs.d.ts +1 -1
- package/dist/knob-contracts/rich-tooltip-knobs.js +2 -1
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +27 -2
- package/dist/knob-contracts/spinner-knobs.d.ts +1 -1
- package/dist/knob-contracts/spinner-knobs.js +1 -1
- package/dist/knob-contracts/stepper-knobs.d.ts +1 -1
- package/dist/knob-contracts/stepper-knobs.js +4 -1
- package/dist/knob-contracts/switch-knobs.d.ts +1 -1
- package/dist/knob-contracts/switch-knobs.js +5 -0
- package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
- package/dist/knob-contracts/table-of-contents-knobs.js +2 -1
- package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
- package/dist/knob-contracts/tabs-knobs.js +1 -0
- package/dist/knob-contracts/tree-knobs.d.ts +1 -1
- package/dist/knob-contracts/tree-knobs.js +2 -1
- package/dist/lib/cn.js +0 -4
- package/dist/lib/contrast.d.ts +1 -0
- package/dist/lib/contrast.js +17 -5
- package/dist/lib/dropzone-validation.js +41 -28
- package/dist/lib/env-file.d.ts +1 -1
- package/dist/lib/env-file.js +5 -5
- package/dist/lib/motion.d.ts +4 -0
- package/dist/lib/motion.js +15 -0
- package/dist/lib/phone-input-format.js +1 -1
- package/dist/lib/trigger-detect.js +6 -8
- package/dist/markdown-block.js +2 -1
- package/dist/popup-parts.d.ts +8 -0
- package/dist/popup-parts.js +43 -0
- package/dist/source-badge.js +3 -1
- package/dist/styles/code.css +0 -2
- package/dist/styles/effects.css +6 -32
- package/dist/styles/index.css +10 -5
- package/dist/styles/recipes/accordion.css +9 -6
- package/dist/styles/recipes/action-bar.css +0 -15
- package/dist/styles/recipes/activity.css +5 -11
- package/dist/styles/recipes/alert.css +4 -4
- package/dist/styles/recipes/audio-recorder.css +15 -3
- package/dist/styles/recipes/audio-visualizer.css +13 -2
- package/dist/styles/recipes/avatar.css +78 -1
- package/dist/styles/recipes/badge.css +14 -4
- package/dist/styles/recipes/breadcrumb.css +77 -0
- package/dist/styles/recipes/button-group.css +5 -7
- package/dist/styles/recipes/button-states.css +66 -0
- package/dist/styles/recipes/button.css +24 -83
- package/dist/styles/recipes/calendar.css +17 -23
- package/dist/styles/recipes/card.css +2 -2
- package/dist/styles/recipes/chat-composer-attachment.css +9 -3
- package/dist/styles/recipes/chat-composer.css +7 -10
- package/dist/styles/recipes/chat-layout.css +35 -0
- package/dist/styles/recipes/chat-message-social.css +123 -0
- package/dist/styles/recipes/chat-message.css +157 -37
- package/dist/styles/recipes/choice.css +18 -21
- package/dist/styles/recipes/code-diff.css +46 -33
- package/dist/styles/recipes/code.css +36 -16
- package/dist/styles/recipes/collapsible.css +7 -2
- package/dist/styles/recipes/color-picker-details.css +3 -4
- package/dist/styles/recipes/color-picker-values.css +9 -8
- package/dist/styles/recipes/color-picker.css +11 -2
- package/dist/styles/recipes/context.css +3 -3
- package/dist/styles/recipes/dockable-panel.css +7 -4
- package/dist/styles/recipes/dropzone.css +7 -8
- package/dist/styles/recipes/dynamic-notification-input.css +8 -5
- package/dist/styles/recipes/dynamic-notification-motion.css +12 -21
- package/dist/styles/recipes/dynamic-notification.css +40 -26
- package/dist/styles/recipes/emoji-picker.css +132 -0
- package/dist/styles/recipes/empty.css +5 -4
- package/dist/styles/recipes/environment-variables.css +4 -15
- package/dist/styles/recipes/field-parts.css +30 -24
- package/dist/styles/recipes/field.css +61 -26
- package/dist/styles/recipes/filter-bar.css +18 -31
- package/dist/styles/recipes/gradient-editor.css +18 -7
- package/dist/styles/recipes/infinite-canvas.css +0 -1
- package/dist/styles/recipes/inline-attachment.css +3 -3
- package/dist/styles/recipes/inline-citation.css +10 -4
- package/dist/styles/recipes/item.css +23 -9
- package/dist/styles/recipes/markdown-block.css +5 -4
- package/dist/styles/recipes/markdown.css +68 -26
- package/dist/styles/recipes/morphing-panel.css +8 -8
- package/dist/styles/recipes/page-layout.css +20 -12
- package/dist/styles/recipes/pagination.css +4 -5
- package/dist/styles/recipes/phone-input.css +12 -8
- package/dist/styles/recipes/popup-controls.css +166 -33
- package/dist/styles/recipes/popup-drawer.css +3 -14
- package/dist/styles/recipes/popup-lists.css +128 -27
- package/dist/styles/recipes/popup-motion.css +4 -45
- package/dist/styles/recipes/popup-toast.css +55 -26
- package/dist/styles/recipes/popup.css +139 -141
- package/dist/styles/recipes/range.css +54 -18
- package/dist/styles/recipes/resizable.css +2 -7
- package/dist/styles/recipes/rich-tooltip.css +24 -34
- package/dist/styles/recipes/scroll-area.css +8 -1
- package/dist/styles/recipes/sidebar-menu.css +149 -34
- package/dist/styles/recipes/sidebar-parts.css +154 -0
- package/dist/styles/recipes/sidebar.css +187 -128
- package/dist/styles/recipes/source-badge.css +1 -1
- package/dist/styles/recipes/spinner.css +8 -1
- package/dist/styles/recipes/stepper.css +31 -13
- package/dist/styles/recipes/switch.css +68 -23
- package/dist/styles/recipes/table-of-contents.css +9 -1
- package/dist/styles/recipes/table.css +14 -10
- package/dist/styles/recipes/tabs.css +17 -12
- package/dist/styles/recipes/task-list.css +7 -14
- package/dist/styles/recipes/thread-rail.css +42 -19
- package/dist/styles/recipes/timeline.css +2 -0
- package/dist/styles/recipes/toolbar.css +27 -25
- package/dist/styles/recipes/track-highlight.css +10 -7
- package/dist/styles/recipes/tree.css +31 -4
- package/dist/styles/recipes/user-ask-details.css +0 -1
- package/dist/styles/recipes/user-ask.css +4 -4
- package/dist/styles/theme.css +37 -16
- package/dist/task-list.d.ts +4 -1
- package/dist/task-list.js +24 -8
- package/dist/thread-rail.d.ts +1 -1
- package/dist/thread-rail.js +61 -19
- package/dist/transcript-divider.js +2 -1
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/alert.d.ts +3 -1
- package/dist/ui/alert.js +14 -8
- package/dist/ui/autocomplete.js +4 -2
- package/dist/ui/avatar.d.ts +8 -0
- package/dist/ui/avatar.js +23 -3
- package/dist/ui/badge.js +1 -1
- package/dist/ui/breadcrumb.d.ts +27 -0
- package/dist/ui/breadcrumb.js +88 -0
- package/dist/ui/button.d.ts +2 -1
- package/dist/ui/button.js +3 -3
- package/dist/ui/calendar.js +2 -2
- package/dist/ui/card.d.ts +3 -1
- package/dist/ui/card.js +12 -7
- package/dist/ui/checkbox.d.ts +2 -0
- package/dist/ui/code-diff.d.ts +1 -1
- package/dist/ui/code-diff.js +72 -28
- package/dist/ui/code.d.ts +5 -3
- package/dist/ui/code.js +28 -29
- package/dist/ui/collapsible.js +1 -1
- package/dist/ui/color-picker.d.ts +5 -2
- package/dist/ui/color-picker.js +85 -37
- package/dist/ui/combobox-disabled-selection.d.ts +1 -2
- package/dist/ui/combobox-disabled-selection.js +7 -9
- package/dist/ui/combobox.js +14 -6
- package/dist/ui/command.d.ts +8 -2
- package/dist/ui/command.js +30 -14
- package/dist/ui/context-menu.js +4 -1
- package/dist/ui/dialog.d.ts +2 -1
- package/dist/ui/dialog.js +4 -23
- package/dist/ui/dockable-panel-geometry.d.ts +1 -0
- package/dist/ui/dockable-panel-geometry.js +7 -1
- package/dist/ui/dockable-panel.d.ts +9 -6
- package/dist/ui/dockable-panel.js +63 -23
- package/dist/ui/drawer.js +1 -1
- package/dist/ui/dropdown-menu.js +5 -4
- package/dist/ui/dropzone.d.ts +2 -2
- package/dist/ui/dropzone.js +75 -16
- package/dist/ui/emoji-picker.d.ts +18 -0
- package/dist/ui/emoji-picker.js +136 -0
- package/dist/ui/empty.d.ts +3 -1
- package/dist/ui/empty.js +12 -7
- package/dist/ui/gradient-editor.d.ts +1 -1
- package/dist/ui/gradient-editor.js +37 -21
- package/dist/ui/hover-card.js +1 -1
- package/dist/ui/infinite-canvas.d.ts +3 -2
- package/dist/ui/infinite-canvas.js +63 -19
- package/dist/ui/input-group.d.ts +0 -3
- package/dist/ui/input-group.js +4 -14
- package/dist/ui/input-otp.d.ts +1 -1
- package/dist/ui/input-otp.js +32 -15
- package/dist/ui/input.js +4 -4
- package/dist/ui/item.d.ts +2 -1
- package/dist/ui/item.js +12 -8
- package/dist/ui/live-status.d.ts +7 -0
- package/dist/ui/live-status.js +17 -0
- package/dist/ui/markdown-elements.d.ts +6 -0
- package/dist/ui/markdown-elements.js +31 -1
- package/dist/ui/menubar.js +3 -3
- package/dist/ui/morphing-panel.js +3 -2
- package/dist/ui/native-select.d.ts +1 -1
- package/dist/ui/native-select.js +24 -11
- package/dist/ui/navigation-menu.js +1 -1
- package/dist/ui/page-layout.d.ts +2 -2
- package/dist/ui/page-layout.js +2 -4
- package/dist/ui/pagination.d.ts +7 -5
- package/dist/ui/pagination.js +19 -13
- package/dist/ui/phone-input.d.ts +1 -0
- package/dist/ui/phone-input.js +58 -60
- package/dist/ui/popover.js +1 -1
- package/dist/ui/radio-group.d.ts +2 -0
- package/dist/ui/resizable.d.ts +3 -2
- package/dist/ui/resizable.js +5 -3
- package/dist/ui/responsive-dialog.d.ts +1 -1
- package/dist/ui/responsive-dialog.js +4 -21
- package/dist/ui/rich-tooltip.d.ts +10 -4
- package/dist/ui/rich-tooltip.js +82 -34
- package/dist/ui/scroll-area.d.ts +1 -1
- package/dist/ui/scroll-area.js +43 -28
- package/dist/ui/select.js +1 -1
- package/dist/ui/sheet.js +1 -1
- package/dist/ui/sidebar-menu.d.ts +5 -1
- package/dist/ui/sidebar-menu.js +32 -34
- package/dist/ui/sidebar-provider.d.ts +10 -1
- package/dist/ui/sidebar-provider.js +39 -14
- package/dist/ui/sidebar-resize-rail.js +8 -4
- package/dist/ui/sidebar.d.ts +11 -6
- package/dist/ui/sidebar.js +47 -24
- package/dist/ui/slider.js +31 -22
- package/dist/ui/spinner.d.ts +3 -2
- package/dist/ui/spinner.js +3 -2
- package/dist/ui/stepper.d.ts +8 -1
- package/dist/ui/stepper.js +74 -25
- package/dist/ui/switch.d.ts +1 -0
- package/dist/ui/table-of-contents.d.ts +2 -2
- package/dist/ui/table-of-contents.js +20 -8
- package/dist/ui/table.js +4 -2
- package/dist/ui/textarea.d.ts +1 -1
- package/dist/ui/textarea.js +20 -9
- package/dist/ui/timeline.d.ts +3 -1
- package/dist/ui/timeline.js +17 -9
- package/dist/ui/toast.d.ts +11 -5
- package/dist/ui/toast.js +101 -55
- package/dist/ui/toolbar.d.ts +3 -2
- package/dist/ui/toolbar.js +4 -2
- package/dist/ui/tooltip.js +4 -21
- package/dist/ui/tree.js +121 -81
- package/dist/ui/trigger-menu.js +2 -1
- package/dist/user-ask.d.ts +10 -5
- package/dist/user-ask.js +32 -12
- package/package.json +5 -1
- package/dist/hooks/use-keyboard-navigation.d.ts +0 -3
- package/dist/hooks/use-keyboard-navigation.js +0 -22
package/dist/ui/toast.js
CHANGED
|
@@ -1,38 +1,106 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { controlEffectsAttribute } from "../skin.js";
|
|
3
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { controlEffectsAttribute } from "../skin.js";
|
|
4
4
|
import { useSkin } from "../skin-provider.js";
|
|
5
5
|
import { Button } from "./button.js";
|
|
6
|
+
import { PopupCloseButton } from "../popup-parts.js";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { CircleCheckIcon, CircleXIcon, InfoIcon, TriangleAlertIcon } from "lucide-react";
|
|
7
9
|
import { Toast } from "@base-ui/react/toast";
|
|
8
10
|
//#region src/ui/toast.tsx
|
|
9
11
|
const toastManager = Toast.createToastManager();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
const errorDefaults = {
|
|
13
|
+
timeout: 0,
|
|
14
|
+
priority: "high"
|
|
15
|
+
};
|
|
16
|
+
function persistenceDefaults(options) {
|
|
17
|
+
if (options.type === "error") return errorDefaults;
|
|
18
|
+
return options.actionProps ? { timeout: 0 } : void 0;
|
|
19
|
+
}
|
|
20
|
+
function show(title, options = {}) {
|
|
21
|
+
return toastManager.add({
|
|
12
22
|
title,
|
|
23
|
+
...persistenceDefaults(options),
|
|
24
|
+
...options
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function withType(type) {
|
|
28
|
+
return (title, options) => show(title, {
|
|
13
29
|
type,
|
|
14
30
|
...options
|
|
15
31
|
});
|
|
16
32
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
function persistentError(update) {
|
|
34
|
+
return typeof update === "string" ? {
|
|
35
|
+
...errorDefaults,
|
|
36
|
+
description: update
|
|
37
|
+
} : {
|
|
38
|
+
...errorDefaults,
|
|
39
|
+
...update
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const toast = Object.assign(show, {
|
|
21
43
|
success: withType("success"),
|
|
22
44
|
error: withType("error"),
|
|
23
45
|
warning: withType("warning"),
|
|
24
46
|
info: withType("info"),
|
|
25
|
-
message: (title, options) =>
|
|
26
|
-
|
|
27
|
-
...options
|
|
47
|
+
message: (title, options) => show(title, options),
|
|
48
|
+
promise: (promise, options) => toastManager.promise(promise, {
|
|
49
|
+
...options,
|
|
50
|
+
error: (reason) => persistentError(typeof options.error === "function" ? options.error(reason) : options.error)
|
|
28
51
|
}),
|
|
29
|
-
promise: (...args) => toastManager.promise(...args),
|
|
30
52
|
dismiss: (id) => toastManager.close(id)
|
|
31
53
|
});
|
|
54
|
+
const statusIcons = {
|
|
55
|
+
success: CircleCheckIcon,
|
|
56
|
+
error: CircleXIcon,
|
|
57
|
+
warning: TriangleAlertIcon,
|
|
58
|
+
info: InfoIcon
|
|
59
|
+
};
|
|
60
|
+
function isToastStatus(type) {
|
|
61
|
+
return type !== void 0 && Object.hasOwn(statusIcons, type);
|
|
62
|
+
}
|
|
32
63
|
const useToast = Toast.useToastManager;
|
|
33
|
-
function
|
|
64
|
+
function ToastIndicator({ status, style }) {
|
|
65
|
+
if (!status) return null;
|
|
66
|
+
const StatusIcon = statusIcons[status];
|
|
67
|
+
return /* @__PURE__ */ jsx("span", {
|
|
68
|
+
"aria-hidden": "true",
|
|
69
|
+
"data-control-ui": "toast",
|
|
70
|
+
"data-control-family": "popup",
|
|
71
|
+
"data-popup-kind": "toast",
|
|
72
|
+
"data-slot": "indicator",
|
|
73
|
+
style,
|
|
74
|
+
className: "shrink-0",
|
|
75
|
+
children: /* @__PURE__ */ jsx(StatusIcon, { className: "size-4" })
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function ToastText({ entry, statusPrefix }) {
|
|
79
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
80
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
81
|
+
children: [entry.title ? /* @__PURE__ */ jsxs(Toast.Title, {
|
|
82
|
+
"data-control-ui": "toast",
|
|
83
|
+
"data-control-family": "popup",
|
|
84
|
+
"data-popup-kind": "toast",
|
|
85
|
+
"data-slot": "title",
|
|
86
|
+
children: [statusPrefix, entry.title]
|
|
87
|
+
}) : null, entry.description ? /* @__PURE__ */ jsxs(Toast.Description, {
|
|
88
|
+
"data-control-ui": "toast",
|
|
89
|
+
"data-control-family": "popup",
|
|
90
|
+
"data-popup-kind": "toast",
|
|
91
|
+
"data-slot": "description",
|
|
92
|
+
children: [entry.title ? null : statusPrefix, entry.description]
|
|
93
|
+
}) : null]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function ToastList({ rootStyle, indicatorStyle, actionStyle, closeStyle, closeLabel, statusLabels }) {
|
|
34
97
|
const { toasts } = Toast.useToastManager();
|
|
35
98
|
return toasts.map((entry) => {
|
|
99
|
+
const status = isToastStatus(entry.type) ? entry.type : void 0;
|
|
100
|
+
const statusPrefix = status ? /* @__PURE__ */ jsx("span", {
|
|
101
|
+
className: "sr-only",
|
|
102
|
+
children: `${statusLabels[status]}: `
|
|
103
|
+
}) : null;
|
|
36
104
|
return /* @__PURE__ */ jsx(Toast.Root, {
|
|
37
105
|
toast: entry,
|
|
38
106
|
"data-control-ui": "toast",
|
|
@@ -43,7 +111,7 @@ function ToastList({ rootStyle, indicatorStyle, actionStyle, closeStyle }) {
|
|
|
43
111
|
style: rootStyle,
|
|
44
112
|
"data-slot": "root",
|
|
45
113
|
"data-surface": "floating",
|
|
46
|
-
className: cn("[--gap:0.75rem] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))]", "absolute
|
|
114
|
+
className: cn("[--gap:0.75rem] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))]", "absolute end-0 bottom-0 z-[calc(var(--z-toast)-var(--toast-index))] h-[var(--height)] w-full select-none data-[expanded]:h-[var(--toast-height)]", "after:absolute after:top-full after:start-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']"),
|
|
47
115
|
children: /* @__PURE__ */ jsxs(Toast.Content, {
|
|
48
116
|
"data-control-ui": "toast",
|
|
49
117
|
"data-control-family": "popup",
|
|
@@ -51,28 +119,13 @@ function ToastList({ rootStyle, indicatorStyle, actionStyle, closeStyle }) {
|
|
|
51
119
|
"data-slot": "content",
|
|
52
120
|
className: "flex items-start",
|
|
53
121
|
children: [
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
className: "shrink-0"
|
|
62
|
-
}) : null,
|
|
63
|
-
/* @__PURE__ */ jsxs("div", {
|
|
64
|
-
className: "flex min-w-0 flex-1 flex-col",
|
|
65
|
-
children: [entry.title ? /* @__PURE__ */ jsx(Toast.Title, {
|
|
66
|
-
"data-control-ui": "toast",
|
|
67
|
-
"data-control-family": "popup",
|
|
68
|
-
"data-popup-kind": "toast",
|
|
69
|
-
"data-slot": "title"
|
|
70
|
-
}) : null, entry.description ? /* @__PURE__ */ jsx(Toast.Description, {
|
|
71
|
-
"data-control-ui": "toast",
|
|
72
|
-
"data-control-family": "popup",
|
|
73
|
-
"data-popup-kind": "toast",
|
|
74
|
-
"data-slot": "description"
|
|
75
|
-
}) : null]
|
|
122
|
+
/* @__PURE__ */ jsx(ToastIndicator, {
|
|
123
|
+
status,
|
|
124
|
+
style: indicatorStyle
|
|
125
|
+
}),
|
|
126
|
+
/* @__PURE__ */ jsx(ToastText, {
|
|
127
|
+
entry,
|
|
128
|
+
statusPrefix
|
|
76
129
|
}),
|
|
77
130
|
entry.actionProps ? /* @__PURE__ */ jsx(Toast.Action, {
|
|
78
131
|
style: actionStyle,
|
|
@@ -86,25 +139,11 @@ function ToastList({ rootStyle, indicatorStyle, actionStyle, closeStyle }) {
|
|
|
86
139
|
}) : null,
|
|
87
140
|
/* @__PURE__ */ jsx(Toast.Close, {
|
|
88
141
|
style: closeStyle,
|
|
89
|
-
|
|
90
|
-
render: (renderProps) => /* @__PURE__ */ jsx(Button, {
|
|
142
|
+
render: (renderProps) => /* @__PURE__ */ jsx(PopupCloseButton, {
|
|
91
143
|
...renderProps,
|
|
92
144
|
"data-popup-kind": "toast",
|
|
93
|
-
|
|
94
|
-
variant: "quiet"
|
|
95
|
-
size: "xs",
|
|
96
|
-
iconOnly: true
|
|
97
|
-
}),
|
|
98
|
-
children: /* @__PURE__ */ jsx("svg", {
|
|
99
|
-
viewBox: "0 0 16 16",
|
|
100
|
-
"aria-hidden": "true",
|
|
101
|
-
fill: "none",
|
|
102
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
103
|
-
d: "M4 4 12 12M12 4 4 12",
|
|
104
|
-
stroke: "currentColor",
|
|
105
|
-
strokeWidth: "1.4",
|
|
106
|
-
strokeLinecap: "round"
|
|
107
|
-
})
|
|
145
|
+
label: closeLabel,
|
|
146
|
+
variant: "quiet"
|
|
108
147
|
})
|
|
109
148
|
})
|
|
110
149
|
]
|
|
@@ -112,7 +151,7 @@ function ToastList({ rootStyle, indicatorStyle, actionStyle, closeStyle }) {
|
|
|
112
151
|
}, entry.id);
|
|
113
152
|
});
|
|
114
153
|
}
|
|
115
|
-
function Toaster({ className, timeout, limit, rootStyle, indicatorStyle, actionStyle, closeStyle }) {
|
|
154
|
+
function Toaster({ className, timeout, limit, rootStyle, indicatorStyle, actionStyle, closeStyle, closeLabel = "Dismiss notification", successLabel = "Success", errorLabel = "Error", warningLabel = "Warning", infoLabel = "Info" }) {
|
|
116
155
|
const skin = useSkin();
|
|
117
156
|
return /* @__PURE__ */ jsx(Toast.Provider, {
|
|
118
157
|
toastManager,
|
|
@@ -125,12 +164,19 @@ function Toaster({ className, timeout, limit, rootStyle, indicatorStyle, actionS
|
|
|
125
164
|
"data-slot": "viewport",
|
|
126
165
|
"data-skin": skin.id,
|
|
127
166
|
"data-effects": controlEffectsAttribute(skin.effects),
|
|
128
|
-
className: cn("fixed
|
|
167
|
+
className: cn("fixed end-4 bottom-4 z-(--z-toast) mx-auto w-[calc(100vw-2rem)] sm:end-6 sm:bottom-6 sm:w-[22.5rem]", className),
|
|
129
168
|
children: /* @__PURE__ */ jsx(ToastList, {
|
|
130
169
|
rootStyle,
|
|
131
170
|
indicatorStyle,
|
|
132
171
|
actionStyle,
|
|
133
|
-
closeStyle
|
|
172
|
+
closeStyle,
|
|
173
|
+
closeLabel,
|
|
174
|
+
statusLabels: {
|
|
175
|
+
success: successLabel,
|
|
176
|
+
error: errorLabel,
|
|
177
|
+
warning: warningLabel,
|
|
178
|
+
info: infoLabel
|
|
179
|
+
}
|
|
134
180
|
})
|
|
135
181
|
}) })
|
|
136
182
|
});
|
package/dist/ui/toolbar.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolbarKnobStyle } from "../knob-contracts/toolbar-knobs.js";
|
|
2
|
-
import { CSSProperties, ComponentProps } from "react";
|
|
3
2
|
import { Toolbar as Toolbar$1 } from "@base-ui/react/toolbar";
|
|
3
|
+
import { CSSProperties, ComponentProps } from "react";
|
|
4
4
|
//#region src/ui/toolbar.d.ts
|
|
5
5
|
export type ToolbarVariant = "default" | "inverse" | "floating";
|
|
6
6
|
export type ToolbarLinkVariant = "default" | "track";
|
|
@@ -15,6 +15,7 @@ export type ToolbarButtonProps = Omit<ComponentProps<"button">, "style"> & {
|
|
|
15
15
|
};
|
|
16
16
|
export type ToolbarLinkProps = Omit<ComponentProps<"a">, "style"> & {
|
|
17
17
|
variant?: ToolbarLinkVariant;
|
|
18
|
+
active?: boolean;
|
|
18
19
|
style?: CSSProperties & ToolbarKnobStyle;
|
|
19
20
|
};
|
|
20
21
|
export type ToolbarGroupProps = ComponentProps<"div"> & {
|
|
@@ -31,7 +32,7 @@ export declare function Toolbar({ orientation, variant, className, children, ...
|
|
|
31
32
|
type RefinedToolbarButtonProps = ToolbarButtonProps & Pick<ComponentProps<typeof Toolbar$1.Button>, "render">;
|
|
32
33
|
export declare function ToolbarButton({ iconOnly, className, ...props }: RefinedToolbarButtonProps): import("react").JSX.Element;
|
|
33
34
|
type RefinedToolbarLinkProps = ToolbarLinkProps & Pick<ComponentProps<typeof Toolbar$1.Link>, "render">;
|
|
34
|
-
export declare function ToolbarLink({ variant, className, ...props }: RefinedToolbarLinkProps): import("react").JSX.Element;
|
|
35
|
+
export declare function ToolbarLink({ variant, active, className, ...props }: RefinedToolbarLinkProps): import("react").JSX.Element;
|
|
35
36
|
export declare function ToolbarGroup({ className, ...props }: ToolbarGroupProps): import("react").JSX.Element;
|
|
36
37
|
export declare function ToolbarSeparator({ orientation, className, ...props }: ToolbarSeparatorProps): import("react").JSX.Element;
|
|
37
38
|
type RefinedToolbarInputProps = ToolbarInputProps & Pick<ComponentProps<typeof Toolbar$1.Input>, "render">;
|
package/dist/ui/toolbar.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
3
|
import { Toolbar as Toolbar$1 } from "@base-ui/react/toolbar";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/ui/toolbar.tsx
|
|
6
6
|
function Toolbar({ orientation = "horizontal", variant = "default", className, children, ...props }) {
|
|
7
7
|
return /* @__PURE__ */ jsxs(Toolbar$1.Root, {
|
|
@@ -37,7 +37,7 @@ function ToolbarButton({ iconOnly = false, className, ...props }) {
|
|
|
37
37
|
...props
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
function ToolbarLink({ variant = "default", className, ...props }) {
|
|
40
|
+
function ToolbarLink({ variant = "default", active = false, className, ...props }) {
|
|
41
41
|
return /* @__PURE__ */ jsx(Toolbar$1.Link, {
|
|
42
42
|
"data-control-ui": "toolbar",
|
|
43
43
|
"data-control-family": "toolbar",
|
|
@@ -45,6 +45,8 @@ function ToolbarLink({ variant = "default", className, ...props }) {
|
|
|
45
45
|
"data-control": "true",
|
|
46
46
|
"data-size": "sm",
|
|
47
47
|
"data-variant": variant,
|
|
48
|
+
"data-active": active || void 0,
|
|
49
|
+
"aria-current": active ? "page" : void 0,
|
|
48
50
|
className: cn("inline-flex shrink-0 items-center justify-center [&_svg]:block [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", variant === "track" && "relative z-[2]", className),
|
|
49
51
|
...props
|
|
50
52
|
});
|
package/dist/ui/tooltip.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { controlEffectsAttribute } from "../skin.js";
|
|
3
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { controlEffectsAttribute } from "../skin.js";
|
|
4
4
|
import { useSkin } from "../skin-provider.js";
|
|
5
|
+
import { PopupArrowShape } from "../popup-parts.js";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { Tooltip as Tooltip$1 } from "@base-ui/react/tooltip";
|
|
7
8
|
//#region src/ui/tooltip.tsx
|
|
@@ -64,29 +65,11 @@ function TooltipContent({ className, children, side = "top", sideOffset = 8, ali
|
|
|
64
65
|
"data-control-family": "popup",
|
|
65
66
|
"data-popup-kind": "tooltip",
|
|
66
67
|
"data-slot": "arrow",
|
|
67
|
-
className:
|
|
68
|
-
children: /* @__PURE__ */ jsx(
|
|
68
|
+
className: "flex",
|
|
69
|
+
children: /* @__PURE__ */ jsx(PopupArrowShape, {})
|
|
69
70
|
}) : null]
|
|
70
71
|
})
|
|
71
72
|
}) });
|
|
72
73
|
}
|
|
73
|
-
function TooltipArrowSvg() {
|
|
74
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
75
|
-
"aria-hidden": "true",
|
|
76
|
-
focusable: "false",
|
|
77
|
-
width: "12",
|
|
78
|
-
height: "8",
|
|
79
|
-
viewBox: "0 0 12 8",
|
|
80
|
-
fill: "none",
|
|
81
|
-
overflow: "visible",
|
|
82
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
83
|
-
"data-control-ui": "tooltip",
|
|
84
|
-
"data-popup-kind": "tooltip",
|
|
85
|
-
"data-control-family": "popup",
|
|
86
|
-
"data-slot": "arrow-shape",
|
|
87
|
-
d: "M0 7L4 2Q6 0 8 2L12 7L12 8L0 8Z"
|
|
88
|
-
})
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
74
|
//#endregion
|
|
92
75
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
package/dist/ui/tree.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { useSkin } from "../skin-provider.js";
|
|
4
4
|
import { TrackHighlight } from "../extensions/track-highlight.js";
|
|
5
|
-
import { Children, createContext, isValidElement, useContext, useRef, useState } from "react";
|
|
5
|
+
import { Children, createContext, isValidElement, useContext, useEffect, useId, useRef, useState } from "react";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import { ChevronRightIcon } from "lucide-react";
|
|
8
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
9
9
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
10
10
|
//#region src/ui/tree.tsx
|
|
11
11
|
const TYPEAHEAD_TIMEOUT = 500;
|
|
@@ -34,8 +34,18 @@ function compareTreeItems(a, b) {
|
|
|
34
34
|
if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
|
35
35
|
return 0;
|
|
36
36
|
}
|
|
37
|
-
function
|
|
38
|
-
|
|
37
|
+
function isUnderExpandedAncestors(item, items, expanded) {
|
|
38
|
+
for (let parentValue = item.parentValue; parentValue !== void 0; parentValue = items.get(parentValue)?.parentValue) if (!expanded.has(parentValue)) return false;
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
function reachableItems(items, expanded) {
|
|
42
|
+
return [...items.values()].filter((item) => isUnderExpandedAncestors(item, items, expanded)).sort(compareTreeItems);
|
|
43
|
+
}
|
|
44
|
+
function resolveTabStop(items, expanded, selected, focusedValue) {
|
|
45
|
+
const reachable = reachableItems(items, expanded);
|
|
46
|
+
if (reachable.some((item) => item.value === focusedValue)) return focusedValue;
|
|
47
|
+
const enabled = reachable.filter((item) => !item.disabled);
|
|
48
|
+
return (enabled.find((item) => selected.has(item.value)) ?? enabled[0])?.value ?? null;
|
|
39
49
|
}
|
|
40
50
|
function focusItem(item, ctx) {
|
|
41
51
|
if (!item) return;
|
|
@@ -55,40 +65,56 @@ function handleTypeahead(event, items, index, ctx, typeahead) {
|
|
|
55
65
|
const now = Date.now();
|
|
56
66
|
typeahead.current.query = now - typeahead.current.at > TYPEAHEAD_TIMEOUT ? event.key : typeahead.current.query + event.key;
|
|
57
67
|
typeahead.current.at = now;
|
|
58
|
-
const
|
|
59
|
-
const
|
|
68
|
+
const typed = typeahead.current.query.toLowerCase();
|
|
69
|
+
const query = [...typed].every((character) => character === typed[0]) ? typed.charAt(0) : typed;
|
|
70
|
+
const searchStart = query.length === 1 ? index + 1 : index;
|
|
71
|
+
const match = [...items.slice(searchStart), ...items.slice(0, searchStart)].find((item) => labelOf(item, ctx).toLowerCase().startsWith(query));
|
|
60
72
|
if (match) focusItem(match, ctx);
|
|
61
73
|
}
|
|
62
|
-
function registeredItemFromTarget(target, root, itemsByNode) {
|
|
63
|
-
let node = target;
|
|
64
|
-
while (node && root.contains(node)) {
|
|
65
|
-
const item = itemsByNode.get(node);
|
|
66
|
-
if (item) return item;
|
|
67
|
-
if (node === root) return;
|
|
68
|
-
node = node.parentElement;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
74
|
function getTreeKeyboardState(event, ctx) {
|
|
72
75
|
if (event.defaultPrevented || !(event.target instanceof HTMLElement)) return null;
|
|
73
|
-
const
|
|
74
|
-
if (!
|
|
75
|
-
const items = ctx.
|
|
76
|
-
const index = items.indexOf(
|
|
76
|
+
const item = ctx.getItemFromTarget(event.target, event.currentTarget);
|
|
77
|
+
if (!item) return null;
|
|
78
|
+
const items = ctx.getNavigableItems();
|
|
79
|
+
const index = items.indexOf(item);
|
|
77
80
|
if (index === -1) return null;
|
|
78
81
|
return {
|
|
79
|
-
|
|
82
|
+
item,
|
|
80
83
|
items,
|
|
81
84
|
index,
|
|
82
|
-
|
|
83
|
-
isExpanded: ctx.expanded.has(current.value),
|
|
84
|
-
level: current.level
|
|
85
|
+
isExpanded: ctx.expanded.has(item.value)
|
|
85
86
|
};
|
|
86
87
|
}
|
|
88
|
+
const RTL_ARROW_KEYS = {
|
|
89
|
+
ArrowLeft: "ArrowRight",
|
|
90
|
+
ArrowRight: "ArrowLeft"
|
|
91
|
+
};
|
|
92
|
+
function handleInlineArrow(key, { item, items, index, isExpanded }, ctx) {
|
|
93
|
+
const isBranch = item.expandable && !item.disabled;
|
|
94
|
+
if (key === "ArrowRight") {
|
|
95
|
+
if (!isBranch) return;
|
|
96
|
+
if (isExpanded) focusItem(items[index + 1], ctx);
|
|
97
|
+
else ctx.toggleExpanded(item.value, true, "keyboard");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (isBranch && isExpanded) ctx.toggleExpanded(item.value, false, "keyboard");
|
|
101
|
+
else focusParentItem(items, index, item.level, ctx);
|
|
102
|
+
}
|
|
103
|
+
function activateItem(key, item, ctx) {
|
|
104
|
+
if (item.disabled) return;
|
|
105
|
+
if (key === " ") {
|
|
106
|
+
ctx.select(item.value, "keyboard", ctx.selectionMode === "multiple");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
ctx.select(item.value, "keyboard", false);
|
|
110
|
+
if (item.expandable) ctx.toggleExpanded(item.value, void 0, "keyboard");
|
|
111
|
+
}
|
|
87
112
|
function handleTreeKeyDown(event, ctx, typeahead) {
|
|
88
113
|
const state = getTreeKeyboardState(event, ctx);
|
|
89
114
|
if (!state) return;
|
|
90
|
-
const {
|
|
91
|
-
|
|
115
|
+
const { item, items, index } = state;
|
|
116
|
+
const key = getComputedStyle(event.currentTarget).direction === "rtl" && RTL_ARROW_KEYS[event.key] || event.key;
|
|
117
|
+
switch (key) {
|
|
92
118
|
case "ArrowDown":
|
|
93
119
|
event.preventDefault();
|
|
94
120
|
focusItem(items[index + 1], ctx);
|
|
@@ -98,14 +124,9 @@ function handleTreeKeyDown(event, ctx, typeahead) {
|
|
|
98
124
|
focusItem(items[index - 1], ctx);
|
|
99
125
|
break;
|
|
100
126
|
case "ArrowRight":
|
|
101
|
-
event.preventDefault();
|
|
102
|
-
if (isBranch && !isExpanded) ctx.toggleExpanded(value, true, "keyboard");
|
|
103
|
-
else if (isBranch && isExpanded) focusItem(items[index + 1], ctx);
|
|
104
|
-
break;
|
|
105
127
|
case "ArrowLeft":
|
|
106
128
|
event.preventDefault();
|
|
107
|
-
|
|
108
|
-
else focusParentItem(items, index, level, ctx);
|
|
129
|
+
handleInlineArrow(key, state, ctx);
|
|
109
130
|
break;
|
|
110
131
|
case "Home":
|
|
111
132
|
event.preventDefault();
|
|
@@ -116,13 +137,9 @@ function handleTreeKeyDown(event, ctx, typeahead) {
|
|
|
116
137
|
focusItem(items[items.length - 1], ctx);
|
|
117
138
|
break;
|
|
118
139
|
case "Enter":
|
|
119
|
-
event.preventDefault();
|
|
120
|
-
ctx.select(value, "keyboard", false);
|
|
121
|
-
if (isBranch) ctx.toggleExpanded(value, void 0, "keyboard");
|
|
122
|
-
break;
|
|
123
140
|
case " ":
|
|
124
141
|
event.preventDefault();
|
|
125
|
-
|
|
142
|
+
activateItem(key, item, ctx);
|
|
126
143
|
break;
|
|
127
144
|
default: handleTypeahead(event, items, index, ctx, typeahead);
|
|
128
145
|
}
|
|
@@ -132,31 +149,23 @@ function Tree({ selectionMode = "single", indicator, value, defaultValue, onValu
|
|
|
132
149
|
const [selectedState, setSelectedState] = useState(() => new Set(defaultValue));
|
|
133
150
|
const [expandedState, setExpandedState] = useState(() => new Set(defaultExpandedValue));
|
|
134
151
|
const [focusedValue, setFocusedValue] = useState(null);
|
|
152
|
+
const [items, setItems] = useState(() => /* @__PURE__ */ new Map());
|
|
153
|
+
const [registerItem] = useState(() => (item) => {
|
|
154
|
+
setItems((current) => new Map(current).set(item.value, item));
|
|
155
|
+
return () => setItems((current) => {
|
|
156
|
+
if (current.get(item.value) !== item) return current;
|
|
157
|
+
const next = new Map(current);
|
|
158
|
+
next.delete(item.value);
|
|
159
|
+
return next;
|
|
160
|
+
});
|
|
161
|
+
});
|
|
135
162
|
const selected = value ? new Set(value) : selectedState;
|
|
136
163
|
const expanded = expandedValue ? new Set(expandedValue) : expandedState;
|
|
137
164
|
const typeahead = useRef({
|
|
138
165
|
query: "",
|
|
139
166
|
at: 0
|
|
140
167
|
});
|
|
141
|
-
const itemsRef = useRef(/* @__PURE__ */ new Map());
|
|
142
|
-
const itemsByNodeRef = useRef(/* @__PURE__ */ new WeakMap());
|
|
143
168
|
const labelsRef = useRef(/* @__PURE__ */ new Map());
|
|
144
|
-
const seededFocusRef = useRef(false);
|
|
145
|
-
const registerItem = (item) => {
|
|
146
|
-
const previous = itemsRef.current.get(item.value);
|
|
147
|
-
if (previous) itemsByNodeRef.current.delete(previous.node);
|
|
148
|
-
itemsRef.current.set(item.value, item);
|
|
149
|
-
itemsByNodeRef.current.set(item.node, item);
|
|
150
|
-
if (!seededFocusRef.current && !item.disabled) {
|
|
151
|
-
seededFocusRef.current = true;
|
|
152
|
-
setFocusedValue(item.value);
|
|
153
|
-
}
|
|
154
|
-
return () => {
|
|
155
|
-
if (itemsRef.current.get(item.value) !== item) return;
|
|
156
|
-
itemsRef.current.delete(item.value);
|
|
157
|
-
itemsByNodeRef.current.delete(item.node);
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
169
|
const registerLabel = (itemValue, node) => {
|
|
161
170
|
if (!node) return;
|
|
162
171
|
labelsRef.current.set(itemValue, node);
|
|
@@ -164,10 +173,15 @@ function Tree({ selectionMode = "single", indicator, value, defaultValue, onValu
|
|
|
164
173
|
if (labelsRef.current.get(itemValue) === node) labelsRef.current.delete(itemValue);
|
|
165
174
|
};
|
|
166
175
|
};
|
|
167
|
-
const
|
|
168
|
-
const getItemFromTarget = (target, root) =>
|
|
176
|
+
const getNavigableItems = () => reachableItems(items, expanded).filter((item) => item.node.checkVisibility());
|
|
177
|
+
const getItemFromTarget = (target, root) => {
|
|
178
|
+
const node = target.closest("[data-control-family=\"tree\"][data-slot=\"item\"]");
|
|
179
|
+
if (!(node instanceof HTMLLIElement) || !root.contains(node)) return;
|
|
180
|
+
const item = items.get(node.dataset.value ?? "");
|
|
181
|
+
return item?.node === node ? item : void 0;
|
|
182
|
+
};
|
|
169
183
|
const getLabel = (itemValue) => labelsRef.current.get(itemValue)?.textContent ?? "";
|
|
170
|
-
const getItem = (itemValue) =>
|
|
184
|
+
const getItem = (itemValue) => items.get(itemValue);
|
|
171
185
|
const select = (itemValue, reason, toggle) => {
|
|
172
186
|
if (selectionMode === "none") return;
|
|
173
187
|
let next;
|
|
@@ -201,10 +215,10 @@ function Tree({ selectionMode = "single", indicator, value, defaultValue, onValu
|
|
|
201
215
|
indicator: resolvedIndicator,
|
|
202
216
|
selected,
|
|
203
217
|
expanded,
|
|
204
|
-
focusedValue,
|
|
218
|
+
tabStopValue: resolveTabStop(items, expanded, selected, focusedValue),
|
|
205
219
|
registerItem,
|
|
206
220
|
registerLabel,
|
|
207
|
-
|
|
221
|
+
getNavigableItems,
|
|
208
222
|
getItemFromTarget,
|
|
209
223
|
getLabel,
|
|
210
224
|
getItem,
|
|
@@ -252,33 +266,48 @@ function Tree({ selectionMode = "single", indicator, value, defaultValue, onValu
|
|
|
252
266
|
}
|
|
253
267
|
function TreeItem({ value, disabled = false, label, className, style, children, ref, ...props }) {
|
|
254
268
|
const tree = useTree();
|
|
255
|
-
const
|
|
269
|
+
const parent = useContext(TreeItemContext);
|
|
270
|
+
const parentValue = parent?.value;
|
|
271
|
+
const level = (parent?.level ?? 0) + 1;
|
|
256
272
|
const expandable = Children.toArray(children).some((child) => isValidElement(child) && child.type === TreeItemContent);
|
|
273
|
+
const labelId = useId();
|
|
274
|
+
const [labelled, setLabelled] = useState(false);
|
|
275
|
+
const nodeRef = useRef(null);
|
|
276
|
+
const { registerItem } = tree;
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
const node = nodeRef.current;
|
|
279
|
+
if (!node) return;
|
|
280
|
+
return registerItem({
|
|
281
|
+
value,
|
|
282
|
+
parentValue,
|
|
283
|
+
node,
|
|
284
|
+
level,
|
|
285
|
+
disabled,
|
|
286
|
+
expandable,
|
|
287
|
+
label
|
|
288
|
+
});
|
|
289
|
+
}, [
|
|
290
|
+
registerItem,
|
|
291
|
+
value,
|
|
292
|
+
parentValue,
|
|
293
|
+
level,
|
|
294
|
+
disabled,
|
|
295
|
+
expandable,
|
|
296
|
+
label
|
|
297
|
+
]);
|
|
257
298
|
const expanded = expandable && tree.expanded.has(value);
|
|
258
299
|
const selected = tree.selected.has(value);
|
|
259
300
|
const itemContext = {
|
|
260
301
|
value,
|
|
261
302
|
level,
|
|
262
303
|
disabled,
|
|
263
|
-
expandable
|
|
304
|
+
expandable,
|
|
305
|
+
labelId,
|
|
306
|
+
setLabelled
|
|
264
307
|
};
|
|
265
308
|
const itemRef = (node) => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (!itemNode) return;
|
|
269
|
-
const unregister = tree.registerItem({
|
|
270
|
-
value,
|
|
271
|
-
node: itemNode,
|
|
272
|
-
level,
|
|
273
|
-
disabled,
|
|
274
|
-
expandable,
|
|
275
|
-
label
|
|
276
|
-
});
|
|
277
|
-
return () => {
|
|
278
|
-
unregister();
|
|
279
|
-
if (typeof refCleanup === "function") refCleanup();
|
|
280
|
-
else setRef(ref, null);
|
|
281
|
-
};
|
|
309
|
+
nodeRef.current = node instanceof HTMLLIElement ? node : null;
|
|
310
|
+
return setRef(ref, nodeRef.current);
|
|
282
311
|
};
|
|
283
312
|
const baseClass = cn("list-none", className);
|
|
284
313
|
const itemStyle = {
|
|
@@ -286,6 +315,7 @@ function TreeItem({ value, disabled = false, label, className, style, children,
|
|
|
286
315
|
...style
|
|
287
316
|
};
|
|
288
317
|
const shared = {
|
|
318
|
+
"aria-labelledby": labelled ? labelId : void 0,
|
|
289
319
|
...props,
|
|
290
320
|
"data-control-ui": "tree",
|
|
291
321
|
"data-control-family": "tree",
|
|
@@ -298,7 +328,7 @@ function TreeItem({ value, disabled = false, label, className, style, children,
|
|
|
298
328
|
"aria-level": level,
|
|
299
329
|
"aria-selected": tree.selectionMode === "none" ? void 0 : selected,
|
|
300
330
|
"aria-disabled": disabled || void 0,
|
|
301
|
-
tabIndex: tree.
|
|
331
|
+
tabIndex: tree.tabStopValue === value ? 0 : -1,
|
|
302
332
|
style: itemStyle
|
|
303
333
|
};
|
|
304
334
|
if (!expandable) return /* @__PURE__ */ jsx(TreeItemContext.Provider, {
|
|
@@ -321,7 +351,7 @@ function TreeItem({ value, disabled = false, label, className, style, children,
|
|
|
321
351
|
...shared,
|
|
322
352
|
role: "treeitem",
|
|
323
353
|
"aria-expanded": expanded,
|
|
324
|
-
tabIndex:
|
|
354
|
+
tabIndex: shared.tabIndex,
|
|
325
355
|
"data-state": expanded ? "open" : "closed",
|
|
326
356
|
className: cn(renderProps.className, baseClass)
|
|
327
357
|
}),
|
|
@@ -353,7 +383,7 @@ function TreeItemTrigger({ className, children, onClick, render, ...props }) {
|
|
|
353
383
|
if (item.expandable) tree.toggleExpanded(item.value);
|
|
354
384
|
focusItem(tree.getItem(item.value), tree);
|
|
355
385
|
},
|
|
356
|
-
className: cn("flex cursor-pointer select-none items-center", "
|
|
386
|
+
className: cn("flex cursor-pointer select-none items-center", "aria-disabled:pointer-events-none", className),
|
|
357
387
|
children
|
|
358
388
|
}
|
|
359
389
|
});
|
|
@@ -378,12 +408,20 @@ function TreeItemIndicator({ className, children, ...props }) {
|
|
|
378
408
|
"aria-hidden": true,
|
|
379
409
|
className: cn("inline-flex shrink-0 items-center justify-center", className),
|
|
380
410
|
...props,
|
|
381
|
-
children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {
|
|
411
|
+
children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {
|
|
412
|
+
"data-icon-dir": "inline",
|
|
413
|
+
className: "size-4"
|
|
414
|
+
})
|
|
382
415
|
});
|
|
383
416
|
}
|
|
384
417
|
function TreeItemLabel({ className, children, render, ref, ...props }) {
|
|
385
418
|
const tree = useTree();
|
|
386
419
|
const item = useTreeItem();
|
|
420
|
+
const { setLabelled } = item;
|
|
421
|
+
useEffect(() => {
|
|
422
|
+
setLabelled(true);
|
|
423
|
+
return () => setLabelled(false);
|
|
424
|
+
}, [setLabelled]);
|
|
387
425
|
const labelRef = (node) => {
|
|
388
426
|
const unregister = tree.registerLabel(item.value, node);
|
|
389
427
|
const cleanup = setRef(ref, node);
|
|
@@ -398,8 +436,10 @@ function TreeItemLabel({ className, children, render, ref, ...props }) {
|
|
|
398
436
|
defaultTagName: "span",
|
|
399
437
|
render,
|
|
400
438
|
props: {
|
|
439
|
+
title: typeof children === "string" ? children : void 0,
|
|
401
440
|
...props,
|
|
402
441
|
ref: labelRef,
|
|
442
|
+
id: item.labelId,
|
|
403
443
|
"data-control-ui": "tree",
|
|
404
444
|
"data-control-family": "tree",
|
|
405
445
|
"data-slot": "item-label",
|