@ctrl-ui/react 0.8.7 → 0.8.9
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 +39 -19
- package/dist/activity.js +7 -15
- 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.d.ts +5 -1
- package/dist/blocks/design-canvas.js +198 -92
- 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 +101 -79
- 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 +59 -28
- 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 +52 -12
- 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 +38 -23
- 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 +85 -22
- 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 +19 -8
- package/dist/filter-bar/types.d.ts +1 -0
- package/dist/filter-bar.js +19 -13
- 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 +25 -16
- 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/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 +166 -34
- package/dist/styles/recipes/sidebar-parts.css +192 -0
- package/dist/styles/recipes/sidebar.css +188 -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.d.ts +3 -1
- package/dist/ui/alert.js +14 -8
- package/dist/ui/autocomplete.js +3 -1
- 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 +1 -1
- 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 +71 -27
- package/dist/ui/code.d.ts +5 -3
- package/dist/ui/code.js +26 -27
- package/dist/ui/color-picker.d.ts +5 -2
- package/dist/ui/color-picker.js +84 -36
- package/dist/ui/combobox-disabled-selection.d.ts +1 -2
- package/dist/ui/combobox-disabled-selection.js +7 -9
- package/dist/ui/combobox.js +13 -5
- package/dist/ui/command.d.ts +8 -2
- package/dist/ui/command.js +30 -14
- package/dist/ui/context-menu.js +3 -0
- package/dist/ui/dialog.d.ts +2 -1
- package/dist/ui/dialog.js +3 -22
- 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/dropdown-menu.js +4 -3
- 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/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 +3 -13
- 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 +11 -7
- 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 +2 -2
- package/dist/ui/morphing-panel.js +2 -1
- package/dist/ui/native-select.d.ts +1 -1
- package/dist/ui/native-select.js +24 -11
- 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 +56 -58
- 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 +81 -33
- package/dist/ui/scroll-area.d.ts +1 -1
- package/dist/ui/scroll-area.js +43 -28
- package/dist/ui/sidebar-menu.d.ts +5 -1
- package/dist/ui/sidebar-menu.js +34 -34
- package/dist/ui/sidebar-provider.d.ts +10 -1
- package/dist/ui/sidebar-provider.js +38 -13
- package/dist/ui/sidebar-resize-rail.js +7 -3
- package/dist/ui/sidebar.d.ts +11 -6
- package/dist/ui/sidebar.js +48 -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 +100 -54
- package/dist/ui/toolbar.d.ts +2 -1
- package/dist/ui/toolbar.js +3 -1
- package/dist/ui/tooltip.js +3 -20
- package/dist/ui/tree.js +120 -80
- package/dist/ui/trigger-menu.js +1 -0
- package/dist/user-ask.d.ts +10 -5
- package/dist/user-ask.js +31 -11
- package/package.json +5 -1
- package/dist/hooks/use-keyboard-navigation.d.ts +0 -3
- package/dist/hooks/use-keyboard-navigation.js +0 -22
|
@@ -9,9 +9,10 @@ export type SettingsBlockProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
9
9
|
onActivePageChange?: (pageId: string) => void;
|
|
10
10
|
backAction?: ReactNode;
|
|
11
11
|
searchPlaceholder?: string;
|
|
12
|
+
searchLabel?: string;
|
|
12
13
|
layout?: "viewport" | "contained";
|
|
13
14
|
};
|
|
14
|
-
export declare function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageChange, backAction, searchPlaceholder, layout, className, style, ...props }: SettingsBlockProps): import("react").JSX.Element;
|
|
15
|
+
export declare function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageChange, backAction, searchPlaceholder, searchLabel, layout, className, style, ...props }: SettingsBlockProps): import("react").JSX.Element;
|
|
15
16
|
export declare function SettingsBackAction({ children, ...props }: Omit<ComponentProps<typeof Button>, "children"> & {
|
|
16
17
|
children?: ReactNode;
|
|
17
18
|
}): import("react").JSX.Element;
|
package/dist/blocks/settings.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { Button } from "../ui/button.js";
|
|
4
|
+
import { LiveStatus } from "../ui/live-status.js";
|
|
5
|
+
import { prefersReducedMotion } from "../lib/motion.js";
|
|
4
6
|
import { ScrollArea } from "../ui/scroll-area.js";
|
|
5
|
-
import { InputGroup, InputGroupAddon
|
|
6
|
-
import {
|
|
7
|
+
import { InputGroup, InputGroupAddon } from "../ui/input-group.js";
|
|
8
|
+
import { Input } from "../ui/input.js";
|
|
9
|
+
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "../ui/empty.js";
|
|
7
10
|
import { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet } from "../ui/field.js";
|
|
8
11
|
import { SidebarProvider, useSidebar } from "../ui/sidebar-provider.js";
|
|
9
12
|
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar-menu.js";
|
|
@@ -13,7 +16,7 @@ import { useEffect, useId, useState } from "react";
|
|
|
13
16
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
14
17
|
import { ArrowLeftIcon, SearchIcon, XIcon } from "lucide-react";
|
|
15
18
|
//#region src/blocks/settings.tsx
|
|
16
|
-
function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageChange, backAction, searchPlaceholder = "Search settings", layout = "viewport", className, style, ...props }) {
|
|
19
|
+
function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageChange, backAction, searchPlaceholder = "Search settings", searchLabel = "Search settings", layout = "viewport", className, style, ...props }) {
|
|
17
20
|
const [internalPageId, setInternalPageId] = useState(defaultActivePageId ?? pages[0]?.id);
|
|
18
21
|
const [query, setQuery] = useState("");
|
|
19
22
|
const [pendingTarget, setPendingTarget] = useState(null);
|
|
@@ -30,8 +33,8 @@ function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageC
|
|
|
30
33
|
...style
|
|
31
34
|
};
|
|
32
35
|
return /* @__PURE__ */ jsx(SidebarProvider, {
|
|
33
|
-
|
|
34
|
-
className: cn("
|
|
36
|
+
layout,
|
|
37
|
+
className: cn("bg-background text-foreground", layout === "viewport" && "h-svh overflow-hidden", className),
|
|
35
38
|
style: providerStyle,
|
|
36
39
|
...props,
|
|
37
40
|
children: /* @__PURE__ */ jsx(SettingsShell, {
|
|
@@ -41,7 +44,7 @@ function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageC
|
|
|
41
44
|
results,
|
|
42
45
|
backAction,
|
|
43
46
|
searchPlaceholder,
|
|
44
|
-
|
|
47
|
+
searchLabel,
|
|
45
48
|
instanceId,
|
|
46
49
|
pendingTarget,
|
|
47
50
|
onPendingTargetChange: setPendingTarget,
|
|
@@ -50,7 +53,7 @@ function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageC
|
|
|
50
53
|
})
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
|
-
function SettingsShell({ pages, currentPage, query, results, backAction, searchPlaceholder,
|
|
56
|
+
function SettingsShell({ pages, currentPage, query, results, backAction, searchPlaceholder, searchLabel, instanceId, pendingTarget, onPendingTargetChange, onPageChange, onQueryChange }) {
|
|
54
57
|
const { setOpenMobile } = useSidebar();
|
|
55
58
|
useEffect(() => {
|
|
56
59
|
if (!pendingTarget || currentPage?.id !== pendingTarget.pageId) return;
|
|
@@ -59,7 +62,7 @@ function SettingsShell({ pages, currentPage, query, results, backAction, searchP
|
|
|
59
62
|
const control = document.getElementById(pendingTarget.controlId);
|
|
60
63
|
row?.scrollIntoView({
|
|
61
64
|
block: "center",
|
|
62
|
-
behavior:
|
|
65
|
+
behavior: prefersReducedMotion(row) ? "auto" : "smooth"
|
|
63
66
|
});
|
|
64
67
|
(control instanceof HTMLElement ? control : row)?.focus({ preventScroll: true });
|
|
65
68
|
onPendingTargetChange(null);
|
|
@@ -83,62 +86,71 @@ function SettingsShell({ pages, currentPage, query, results, backAction, searchP
|
|
|
83
86
|
});
|
|
84
87
|
navigate(result.page.id);
|
|
85
88
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
89
|
+
const trimmedQuery = query.trim();
|
|
90
|
+
const resultCount = `${results.length} ${results.length === 1 ? "setting" : "settings"} found`;
|
|
91
|
+
const searchStatus = results.length > 0 ? resultCount : "No matching settings";
|
|
92
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
93
|
+
/* @__PURE__ */ jsx(LiveStatus, { message: trimmedQuery ? searchStatus : "" }),
|
|
94
|
+
/* @__PURE__ */ jsxs(Sidebar, {
|
|
95
|
+
collapsible: "offcanvas",
|
|
96
|
+
children: [/* @__PURE__ */ jsxs(SidebarHeader, {
|
|
97
|
+
className: "gap-3 border-b border-sidebar-border p-3",
|
|
98
|
+
children: [backAction ? /* @__PURE__ */ jsx("div", {
|
|
99
|
+
className: "min-w-0",
|
|
100
|
+
children: backAction
|
|
101
|
+
}) : null, /* @__PURE__ */ jsx(SettingsSearch, {
|
|
102
|
+
value: query,
|
|
103
|
+
label: searchLabel,
|
|
104
|
+
placeholder: searchPlaceholder,
|
|
105
|
+
onValueChange: onQueryChange
|
|
106
|
+
})]
|
|
107
|
+
}), /* @__PURE__ */ jsx(SidebarContent, { children: trimmedQuery ? /* @__PURE__ */ jsx(SettingsSearchNavigation, {
|
|
108
|
+
results,
|
|
109
|
+
onSelect: openResult,
|
|
110
|
+
onClear: () => onQueryChange("")
|
|
111
|
+
}) : /* @__PURE__ */ jsx(SettingsPageNavigation, {
|
|
112
|
+
pages,
|
|
113
|
+
activePageId: currentPage?.id,
|
|
114
|
+
onSelect: navigate
|
|
115
|
+
}) })]
|
|
116
|
+
}),
|
|
117
|
+
/* @__PURE__ */ jsxs(SidebarInset, {
|
|
118
|
+
className: "h-full min-h-0 min-w-0",
|
|
119
|
+
children: [/* @__PURE__ */ jsxs("header", {
|
|
120
|
+
className: "flex h-12 shrink-0 items-center gap-2 border-b px-3 lg:hidden",
|
|
121
|
+
children: [/* @__PURE__ */ jsx(SidebarTrigger, {}), /* @__PURE__ */ jsx("span", {
|
|
122
|
+
className: "truncate text-label font-medium",
|
|
123
|
+
title: currentPage?.title,
|
|
124
|
+
children: currentPage?.title ?? "Settings"
|
|
125
|
+
})]
|
|
126
|
+
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
127
|
+
className: "min-h-0 flex-1",
|
|
128
|
+
lockAxis: "x",
|
|
129
|
+
children: currentPage ? /* @__PURE__ */ jsx(SettingsPage, {
|
|
130
|
+
page: currentPage,
|
|
131
|
+
instanceId
|
|
132
|
+
}) : /* @__PURE__ */ jsx(SettingsEmpty, {
|
|
133
|
+
title: "No settings",
|
|
134
|
+
description: "Add a settings page to populate this space."
|
|
135
|
+
})
|
|
114
136
|
})]
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
lockAxis: "x",
|
|
118
|
-
children: currentPage ? /* @__PURE__ */ jsx(SettingsPage, {
|
|
119
|
-
page: currentPage,
|
|
120
|
-
instanceId
|
|
121
|
-
}) : /* @__PURE__ */ jsx(SettingsEmpty, {
|
|
122
|
-
title: "No settings",
|
|
123
|
-
description: "Add a settings page to populate this space."
|
|
124
|
-
})
|
|
125
|
-
})]
|
|
126
|
-
})] });
|
|
137
|
+
})
|
|
138
|
+
] });
|
|
127
139
|
}
|
|
128
|
-
function SettingsSearch({ value, placeholder, onValueChange }) {
|
|
140
|
+
function SettingsSearch({ value, label, placeholder, onValueChange }) {
|
|
129
141
|
return /* @__PURE__ */ jsxs(InputGroup, {
|
|
130
142
|
size: "sm",
|
|
131
143
|
children: [
|
|
132
144
|
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
133
|
-
className: "
|
|
145
|
+
className: "ps-2.5",
|
|
134
146
|
children: /* @__PURE__ */ jsx(SearchIcon, {
|
|
135
147
|
className: "size-3.5",
|
|
136
148
|
"aria-hidden": "true"
|
|
137
149
|
})
|
|
138
150
|
}),
|
|
139
|
-
/* @__PURE__ */ jsx(
|
|
151
|
+
/* @__PURE__ */ jsx(Input, {
|
|
140
152
|
type: "search",
|
|
141
|
-
"aria-label":
|
|
153
|
+
"aria-label": label,
|
|
142
154
|
placeholder,
|
|
143
155
|
value,
|
|
144
156
|
onChange: (event) => onValueChange(event.currentTarget.value)
|
|
@@ -148,9 +160,12 @@ function SettingsSearch({ value, placeholder, onValueChange }) {
|
|
|
148
160
|
size: "xs",
|
|
149
161
|
iconOnly: true,
|
|
150
162
|
"aria-label": "Clear settings search",
|
|
151
|
-
className: "
|
|
163
|
+
className: "me-1",
|
|
152
164
|
onClick: () => onValueChange(""),
|
|
153
|
-
children: /* @__PURE__ */ jsx(XIcon, {
|
|
165
|
+
children: /* @__PURE__ */ jsx(XIcon, {
|
|
166
|
+
className: "size-3.5",
|
|
167
|
+
"aria-hidden": "true"
|
|
168
|
+
})
|
|
154
169
|
}) : null
|
|
155
170
|
]
|
|
156
171
|
});
|
|
@@ -163,10 +178,16 @@ function SettingsPageNavigation({ pages, activePageId, onSelect }) {
|
|
|
163
178
|
children: [page.icon, /* @__PURE__ */ jsx("span", { children: page.title })]
|
|
164
179
|
}) }, page.id)) })] });
|
|
165
180
|
}
|
|
166
|
-
function SettingsSearchNavigation({ results, onSelect }) {
|
|
181
|
+
function SettingsSearchNavigation({ results, onSelect, onClear }) {
|
|
167
182
|
if (results.length === 0) return /* @__PURE__ */ jsx(SettingsEmpty, {
|
|
168
183
|
title: "No matching settings",
|
|
169
|
-
description: "Try another name or keyword."
|
|
184
|
+
description: "Try another name or keyword.",
|
|
185
|
+
action: /* @__PURE__ */ jsx(Button, {
|
|
186
|
+
variant: "surface",
|
|
187
|
+
size: "sm",
|
|
188
|
+
onClick: onClear,
|
|
189
|
+
children: "Clear search"
|
|
190
|
+
})
|
|
170
191
|
});
|
|
171
192
|
const groups = /* @__PURE__ */ new Map();
|
|
172
193
|
for (const result of results) {
|
|
@@ -177,28 +198,22 @@ function SettingsSearchNavigation({ results, onSelect }) {
|
|
|
177
198
|
group.results.push(result);
|
|
178
199
|
groups.set(result.page.id, group);
|
|
179
200
|
}
|
|
180
|
-
return /* @__PURE__ */
|
|
181
|
-
className: "sr-only",
|
|
182
|
-
role: "status",
|
|
183
|
-
"aria-live": "polite",
|
|
184
|
-
children: [
|
|
185
|
-
results.length,
|
|
186
|
-
" ",
|
|
187
|
-
results.length === 1 ? "setting" : "settings",
|
|
188
|
-
" found"
|
|
189
|
-
]
|
|
190
|
-
}), [...groups.values()].map((group) => /* @__PURE__ */ jsxs(SidebarGroup, { children: [/* @__PURE__ */ jsxs(SidebarGroupLabel, { children: [group.page.icon, /* @__PURE__ */ jsx("span", { children: group.page.title })] }), /* @__PURE__ */ jsx(SidebarMenu, { children: group.results.map((result) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, {
|
|
201
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: [...groups.values()].map((group) => /* @__PURE__ */ jsxs(SidebarGroup, { children: [/* @__PURE__ */ jsxs(SidebarGroupLabel, { children: [group.page.icon, /* @__PURE__ */ jsx("span", { children: group.page.title })] }), /* @__PURE__ */ jsx(SidebarMenu, { children: group.results.map((result) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, {
|
|
191
202
|
size: "sm",
|
|
192
|
-
className: "h-auto min-h-
|
|
203
|
+
className: "h-auto min-h-(--control-h-sm) py-1.5",
|
|
193
204
|
onClick: () => onSelect(result),
|
|
194
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
195
|
-
|
|
205
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
206
|
+
title: result.setting.title,
|
|
207
|
+
children: result.setting.title
|
|
208
|
+
})
|
|
209
|
+
}) }, `${result.section.id}/${result.setting.id}`)) })] }, group.page.id)) });
|
|
196
210
|
}
|
|
197
211
|
function SettingsPage({ page, instanceId }) {
|
|
212
|
+
const { layout } = useSidebar();
|
|
198
213
|
return /* @__PURE__ */ jsxs("div", {
|
|
199
214
|
className: "mx-auto flex w-full max-w-4xl flex-col gap-10 px-5 py-8 md:px-10 md:py-12",
|
|
200
|
-
children: [/* @__PURE__ */ jsx("h1", {
|
|
201
|
-
className: "text-heading
|
|
215
|
+
children: [/* @__PURE__ */ jsx(layout === "contained" ? "h2" : "h1", {
|
|
216
|
+
className: "text-heading-2 text-foreground text-balance",
|
|
202
217
|
children: page.title
|
|
203
218
|
}), page.sections.map((section) => /* @__PURE__ */ jsxs(FieldSet, {
|
|
204
219
|
className: "gap-3",
|
|
@@ -244,17 +259,20 @@ function SettingsRow({ pageId, sectionId, setting, instanceId, separated }) {
|
|
|
244
259
|
})]
|
|
245
260
|
})] });
|
|
246
261
|
}
|
|
247
|
-
function SettingsEmpty({ title, description }) {
|
|
248
|
-
return /* @__PURE__ */
|
|
262
|
+
function SettingsEmpty({ title, description, action }) {
|
|
263
|
+
return /* @__PURE__ */ jsxs(Empty, {
|
|
249
264
|
className: "min-h-40 gap-3 p-4",
|
|
250
|
-
children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [
|
|
265
|
+
children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
|
|
251
266
|
/* @__PURE__ */ jsx(EmptyMedia, {
|
|
252
267
|
className: "mb-0 size-8",
|
|
253
|
-
children: /* @__PURE__ */ jsx(SearchIcon, {
|
|
268
|
+
children: /* @__PURE__ */ jsx(SearchIcon, {
|
|
269
|
+
className: "size-4",
|
|
270
|
+
"aria-hidden": "true"
|
|
271
|
+
})
|
|
254
272
|
}),
|
|
255
273
|
/* @__PURE__ */ jsx(EmptyTitle, { children: title }),
|
|
256
274
|
/* @__PURE__ */ jsx(EmptyDescription, { children: description })
|
|
257
|
-
] })
|
|
275
|
+
] }), action ? /* @__PURE__ */ jsx(EmptyContent, { children: action }) : null]
|
|
258
276
|
});
|
|
259
277
|
}
|
|
260
278
|
function settingDomIds(instanceId, pageId, sectionId, settingId) {
|
|
@@ -275,9 +293,13 @@ function SettingsBackAction({ children = "Back to app", ...props }) {
|
|
|
275
293
|
return /* @__PURE__ */ jsxs(Button, {
|
|
276
294
|
variant: "quiet",
|
|
277
295
|
size: "sm",
|
|
278
|
-
className: "-
|
|
296
|
+
className: "-ms-1 justify-start gap-2",
|
|
279
297
|
...props,
|
|
280
|
-
children: [/* @__PURE__ */ jsx(ArrowLeftIcon, {
|
|
298
|
+
children: [/* @__PURE__ */ jsx(ArrowLeftIcon, {
|
|
299
|
+
className: "size-4",
|
|
300
|
+
"data-icon-dir": "inline",
|
|
301
|
+
"aria-hidden": "true"
|
|
302
|
+
}), children]
|
|
281
303
|
});
|
|
282
304
|
}
|
|
283
305
|
//#endregion
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SidebarProvider } from "../ui/sidebar-provider.js";
|
|
2
|
+
import "../ui/sidebar.js";
|
|
3
|
+
import { ComponentProps, ReactNode } from "react";
|
|
4
|
+
//#region src/blocks/team-chat.d.ts
|
|
5
|
+
export type TeamChatBlockProps = Omit<ComponentProps<typeof SidebarProvider>, "children"> & {
|
|
6
|
+
sidebar: ReactNode;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
thread?: ReactNode;
|
|
9
|
+
threadLabel?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function TeamChatBlock({ sidebar, children, thread, threadLabel, className, ...props }: TeamChatBlockProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { SidebarProvider } from "../ui/sidebar-provider.js";
|
|
4
|
+
import { SidebarInset } from "../ui/sidebar.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/blocks/team-chat.tsx
|
|
7
|
+
function TeamChatBlock({ sidebar, children, thread, threadLabel = "Thread", className, ...props }) {
|
|
8
|
+
const threadIsOpen = thread !== void 0 && thread !== null;
|
|
9
|
+
return /* @__PURE__ */ jsxs(SidebarProvider, {
|
|
10
|
+
className: cn("bg-background text-foreground", className),
|
|
11
|
+
...props,
|
|
12
|
+
children: [sidebar, /* @__PURE__ */ jsxs(SidebarInset, {
|
|
13
|
+
className: "@container/team-chat flex h-full min-h-0 min-w-0 flex-row",
|
|
14
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
15
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", threadIsOpen && "@max-3xl/team-chat:hidden"),
|
|
16
|
+
children
|
|
17
|
+
}), threadIsOpen ? /* @__PURE__ */ jsx("aside", {
|
|
18
|
+
"aria-label": threadLabel,
|
|
19
|
+
className: "flex min-h-0 w-full min-w-0 flex-col border-border @3xl/team-chat:w-[min(26rem,45%)] @3xl/team-chat:shrink-0 @3xl/team-chat:border-s",
|
|
20
|
+
children: thread
|
|
21
|
+
}) : null]
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { TeamChatBlock };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Button } from "../ui/button.js";
|
|
3
|
-
import { DropdownMenu, DropdownMenuContent,
|
|
3
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
|
|
4
4
|
import { Switch } from "../ui/switch.js";
|
|
5
5
|
import { useId } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import {
|
|
7
|
+
import { ChevronDownIcon, MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
|
8
8
|
//#region src/blocks/theme-toggle.tsx
|
|
9
9
|
const systemThemeOption = {
|
|
10
10
|
value: "system",
|
|
@@ -53,7 +53,7 @@ function ThemeSwitch({ value, onValueChange, onValue = "dark", offValue = "light
|
|
|
53
53
|
checkedIcon: checkedIcon ?? defaultSwitchCheckedIcon,
|
|
54
54
|
uncheckedIcon: uncheckedIcon ?? defaultSwitchUncheckedIcon,
|
|
55
55
|
onCheckedChange: (checked) => onValueChange(checked ? onValue : offValue),
|
|
56
|
-
"aria-label": ariaLabel ??
|
|
56
|
+
"aria-label": ariaLabel ?? `${currentThemeOption(onValue, defaultThemeOptions).label} mode`,
|
|
57
57
|
...props
|
|
58
58
|
});
|
|
59
59
|
}
|
|
@@ -61,10 +61,9 @@ function ThemeSegmentedSwitch({ value, onValueChange, options = defaultThemeOpti
|
|
|
61
61
|
const generatedName = useId();
|
|
62
62
|
const choices = controlOptions(options);
|
|
63
63
|
const currentValue = effectiveThemeValue(value, choices);
|
|
64
|
-
const activeIndex = Math.max(0, choices.findIndex((option) => option.value === currentValue));
|
|
65
64
|
const indicatorStyle = {
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
"--_theme-switch-index": Math.max(0, choices.findIndex((option) => option.value === currentValue)),
|
|
66
|
+
width: `calc((100% - var(--_theme-switch-padding) * 2) / ${choices.length})`
|
|
68
67
|
};
|
|
69
68
|
return /* @__PURE__ */ jsxs("div", {
|
|
70
69
|
role: "radiogroup",
|
|
@@ -80,7 +79,7 @@ function ThemeSegmentedSwitch({ value, onValueChange, options = defaultThemeOpti
|
|
|
80
79
|
"data-control-ui": "theme-toggle",
|
|
81
80
|
"data-control-family": "theme-toggle",
|
|
82
81
|
"data-slot": "indicator",
|
|
83
|
-
className: "pointer-events-none absolute inset-y-(--_theme-switch-padding)
|
|
82
|
+
className: "pointer-events-none absolute inset-y-(--_theme-switch-padding) start-(--_theme-switch-padding) translate-x-[calc(var(--_theme-switch-index)*100%)] rounded-(--_theme-switch-radius) bg-background shadow-(--shadow-sm) transition-transform duration-(--duration-base) ease-(--ease-standard) rtl:translate-x-[calc(var(--_theme-switch-index)*-100%)]",
|
|
84
83
|
style: indicatorStyle
|
|
85
84
|
}), choices.map((option) => {
|
|
86
85
|
const selected = option.value === currentValue;
|
|
@@ -92,7 +91,7 @@ function ThemeSegmentedSwitch({ value, onValueChange, options = defaultThemeOpti
|
|
|
92
91
|
"data-control": "true",
|
|
93
92
|
"data-selected": selected ? "true" : void 0,
|
|
94
93
|
"data-disabled": option.disabled ? "true" : void 0,
|
|
95
|
-
className: classes("relative z-[1] inline-flex h-(--control-h-xs) cursor-pointer items-center justify-center gap-1.5 rounded-(--_theme-switch-radius) px-1.5 text-label font-medium transition-colors duration-(--duration-fast) ease-(--ease-standard) hover:text-foreground data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-
|
|
94
|
+
className: classes("relative z-[1] inline-flex h-(--control-h-xs) cursor-pointer items-center justify-center gap-1.5 rounded-(--_theme-switch-radius) px-1.5 text-label font-medium transition-colors duration-(--duration-fast) ease-(--ease-standard) not-data-[disabled=true]:hover:text-foreground data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-(--disabled-opacity) data-[selected=true]:text-foreground", showLabels ? "min-w-20" : "w-(--control-h-xs)"),
|
|
96
95
|
children: [
|
|
97
96
|
/* @__PURE__ */ jsx("input", {
|
|
98
97
|
type: "radio",
|
|
@@ -140,7 +139,7 @@ function ThemeDropdown({ value, onValueChange, options = defaultThemeOptions, la
|
|
|
140
139
|
const current = currentThemeOption(value, options);
|
|
141
140
|
const CurrentIcon = current.icon;
|
|
142
141
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
|
|
143
|
-
"aria-label": ariaLabel ?? label
|
|
142
|
+
"aria-label": ariaLabel ?? `${label}: ${current.label}`,
|
|
144
143
|
className: classes("min-w-36 gap-2", className),
|
|
145
144
|
...props,
|
|
146
145
|
children: [
|
|
@@ -157,33 +156,26 @@ function ThemeDropdown({ value, onValueChange, options = defaultThemeOptions, la
|
|
|
157
156
|
"aria-hidden": true
|
|
158
157
|
})
|
|
159
158
|
]
|
|
160
|
-
}), /* @__PURE__ */
|
|
159
|
+
}), /* @__PURE__ */ jsx(DropdownMenuContent, {
|
|
161
160
|
className: "min-w-40",
|
|
162
|
-
children:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
children: /* @__PURE__ */ jsxs(DropdownMenuRadioGroup, {
|
|
162
|
+
value,
|
|
163
|
+
onValueChange,
|
|
164
|
+
children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: label }), options.map((option) => {
|
|
165
|
+
const Icon = option.icon;
|
|
166
|
+
return /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
|
|
167
|
+
value: option.value,
|
|
168
|
+
disabled: option.disabled,
|
|
169
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
170
170
|
className: "size-3.5",
|
|
171
171
|
"aria-hidden": true
|
|
172
|
-
}),
|
|
173
|
-
/* @__PURE__ */ jsx("span", {
|
|
172
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
174
173
|
className: "min-w-0 flex-1 truncate",
|
|
175
174
|
children: option.label
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
181
|
-
className: "size-3.5",
|
|
182
|
-
"aria-hidden": true
|
|
183
|
-
})
|
|
184
|
-
]
|
|
185
|
-
}, option.value);
|
|
186
|
-
})]
|
|
175
|
+
})]
|
|
176
|
+
}, option.value);
|
|
177
|
+
})]
|
|
178
|
+
})
|
|
187
179
|
})] });
|
|
188
180
|
}
|
|
189
181
|
//#endregion
|
|
@@ -30,9 +30,12 @@ export type ChatComposerAttachmentProps = Omit<ComponentProps<"li">, "style"> &
|
|
|
30
30
|
variant?: ChatComposerAttachmentVariant;
|
|
31
31
|
onRemove?: () => void;
|
|
32
32
|
removeLabel?: string;
|
|
33
|
+
errorLabel?: string;
|
|
34
|
+
uploadedLabel?: (name: string) => string;
|
|
35
|
+
uploadFailedLabel?: (name: string) => string;
|
|
33
36
|
style?: CSSProperties & ChatComposerAttachmentKnobStyle;
|
|
34
37
|
};
|
|
35
|
-
export declare function ChatComposerAttachment({ file, name: nameInput, type: typeInput, description, status, progress: progressInput, previewUrl: previewUrlInput, kind, variant, onRemove, removeLabel, className, children, "aria-label": ariaLabel, ...props }: ChatComposerAttachmentProps): import("react").JSX.Element;
|
|
38
|
+
export declare function ChatComposerAttachment({ file, name: nameInput, type: typeInput, description, status, progress: progressInput, previewUrl: previewUrlInput, kind, variant, onRemove, removeLabel, errorLabel, uploadedLabel, uploadFailedLabel, className, children, "aria-label": ariaLabel, ...props }: ChatComposerAttachmentProps): import("react").JSX.Element;
|
|
36
39
|
export type ChatComposerAttachmentPreviewProps = Omit<ComponentProps<"div">, "style"> & {
|
|
37
40
|
style?: CSSProperties & ChatComposerAttachmentKnobStyle;
|
|
38
41
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "./lib/cn.js";
|
|
3
3
|
import { Button } from "./ui/button.js";
|
|
4
|
+
import { LiveStatus } from "./ui/live-status.js";
|
|
4
5
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
5
6
|
import { Spinner } from "./ui/spinner.js";
|
|
6
7
|
import { createContext, useContext, useLayoutEffect, useState } from "react";
|
|
@@ -106,9 +107,27 @@ function defaultDescription(context) {
|
|
|
106
107
|
const { progress } = context;
|
|
107
108
|
if (context.description) return context.description;
|
|
108
109
|
if (context.status === "uploading") return progress === void 0 ? "Uploading…" : `Uploading ${Math.round(progress)}%`;
|
|
109
|
-
if (context.status === "error") return
|
|
110
|
+
if (context.status === "error") return context.errorLabel;
|
|
110
111
|
return fallbackLabel(context.kind, context.extension);
|
|
111
112
|
}
|
|
113
|
+
function defaultUploadedLabel(name) {
|
|
114
|
+
return `${name} uploaded`;
|
|
115
|
+
}
|
|
116
|
+
function defaultUploadFailedLabel(name) {
|
|
117
|
+
return `${name} couldn't upload`;
|
|
118
|
+
}
|
|
119
|
+
function useUploadAnnouncement(status, name, uploadedLabel, uploadFailedLabel) {
|
|
120
|
+
const [previousStatus, setPreviousStatus] = useState(status);
|
|
121
|
+
const [announcement, setAnnouncement] = useState("");
|
|
122
|
+
if (status !== previousStatus) {
|
|
123
|
+
setPreviousStatus(status);
|
|
124
|
+
setAnnouncement({
|
|
125
|
+
uploaded: uploadedLabel,
|
|
126
|
+
error: uploadFailedLabel
|
|
127
|
+
}[status]?.(name) ?? "");
|
|
128
|
+
}
|
|
129
|
+
return announcement;
|
|
130
|
+
}
|
|
112
131
|
function ChatComposerAttachments({ label = "Attachments", className, viewportClassName, children, ...props }) {
|
|
113
132
|
return /* @__PURE__ */ jsx("div", {
|
|
114
133
|
"data-control-ui": "chat-composer-attachments",
|
|
@@ -119,12 +138,12 @@ function ChatComposerAttachments({ label = "Attachments", className, viewportCla
|
|
|
119
138
|
children: /* @__PURE__ */ jsx(ScrollArea, {
|
|
120
139
|
"data-control-ui": "chat-composer-attachments",
|
|
121
140
|
"data-slot": "scroll",
|
|
122
|
-
"aria-label": label,
|
|
123
141
|
lockAxis: "y",
|
|
124
142
|
mask: true,
|
|
125
143
|
className: "w-full",
|
|
126
144
|
viewportClassName,
|
|
127
145
|
children: /* @__PURE__ */ jsx("ul", {
|
|
146
|
+
"aria-label": label,
|
|
128
147
|
"data-control-ui": "chat-composer-attachments",
|
|
129
148
|
"data-control-family": "chat-composer-attachment",
|
|
130
149
|
"data-slot": "list",
|
|
@@ -134,7 +153,7 @@ function ChatComposerAttachments({ label = "Attachments", className, viewportCla
|
|
|
134
153
|
})
|
|
135
154
|
});
|
|
136
155
|
}
|
|
137
|
-
function ChatComposerAttachment({ file, name: nameInput, type: typeInput, description, status = "idle", progress: progressInput, previewUrl: previewUrlInput, kind, variant = "auto", onRemove, removeLabel, className, children, "aria-label": ariaLabel, ...props }) {
|
|
156
|
+
function ChatComposerAttachment({ file, name: nameInput, type: typeInput, description, status = "idle", progress: progressInput, previewUrl: previewUrlInput, kind, variant = "auto", onRemove, removeLabel, errorLabel = "Couldn't upload. Remove and try again.", uploadedLabel = defaultUploadedLabel, uploadFailedLabel = defaultUploadFailedLabel, className, children, "aria-label": ariaLabel, ...props }) {
|
|
138
157
|
const name = nameInput ?? file?.name ?? "";
|
|
139
158
|
const type = typeInput ?? file?.type;
|
|
140
159
|
const resolvedKind = kind ?? kindFromAttachment(type, name);
|
|
@@ -143,6 +162,7 @@ function ChatComposerAttachment({ file, name: nameInput, type: typeInput, descri
|
|
|
143
162
|
const previewUrl = previewUrlInput ?? filePreviewUrl;
|
|
144
163
|
const extension = extensionFromName(name);
|
|
145
164
|
const progress = progressValue(progressInput);
|
|
165
|
+
const announcement = useUploadAnnouncement(status, name, uploadedLabel, uploadFailedLabel);
|
|
146
166
|
return /* @__PURE__ */ jsx(ChatComposerAttachmentContext.Provider, {
|
|
147
167
|
value: {
|
|
148
168
|
name,
|
|
@@ -155,9 +175,10 @@ function ChatComposerAttachment({ file, name: nameInput, type: typeInput, descri
|
|
|
155
175
|
variant: resolvedVariant,
|
|
156
176
|
extension,
|
|
157
177
|
onRemove,
|
|
158
|
-
removeLabel
|
|
178
|
+
removeLabel,
|
|
179
|
+
errorLabel
|
|
159
180
|
},
|
|
160
|
-
children: /* @__PURE__ */
|
|
181
|
+
children: /* @__PURE__ */ jsxs("li", {
|
|
161
182
|
"aria-label": ariaLabel ?? name,
|
|
162
183
|
"data-control-ui": "chat-composer-attachment",
|
|
163
184
|
"data-control-family": "chat-composer-attachment",
|
|
@@ -168,12 +189,12 @@ function ChatComposerAttachment({ file, name: nameInput, type: typeInput, descri
|
|
|
168
189
|
"data-variant": resolvedVariant,
|
|
169
190
|
className: cn("relative isolate flex shrink-0 items-center overflow-hidden", className),
|
|
170
191
|
...props,
|
|
171
|
-
children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
192
|
+
children: [children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
172
193
|
/* @__PURE__ */ jsx(ChatComposerAttachmentPreview, {}),
|
|
173
194
|
resolvedVariant === "file" && /* @__PURE__ */ jsxs(ChatComposerAttachmentContent, { children: [/* @__PURE__ */ jsx(ChatComposerAttachmentTitle, {}), /* @__PURE__ */ jsx(ChatComposerAttachmentDescription, {})] }),
|
|
174
195
|
/* @__PURE__ */ jsx(ChatComposerAttachmentRemove, {}),
|
|
175
196
|
/* @__PURE__ */ jsx(ChatComposerAttachmentProgress, {})
|
|
176
|
-
] })
|
|
197
|
+
] }), /* @__PURE__ */ jsx(LiveStatus, { message: announcement })]
|
|
177
198
|
})
|
|
178
199
|
});
|
|
179
200
|
}
|
|
@@ -212,25 +233,29 @@ function ChatComposerAttachmentContent({ className, ...props }) {
|
|
|
212
233
|
}
|
|
213
234
|
function ChatComposerAttachmentTitle({ className, children, ...props }) {
|
|
214
235
|
const { name } = useChatComposerAttachmentContext();
|
|
236
|
+
const content = children ?? name;
|
|
215
237
|
return /* @__PURE__ */ jsx("div", {
|
|
216
238
|
"data-control-ui": "chat-composer-attachment",
|
|
217
239
|
"data-control-family": "chat-composer-attachment",
|
|
218
240
|
"data-slot": "title",
|
|
241
|
+
title: typeof content === "string" ? content : void 0,
|
|
219
242
|
className: cn("truncate", className),
|
|
220
243
|
...props,
|
|
221
|
-
children:
|
|
244
|
+
children: content
|
|
222
245
|
});
|
|
223
246
|
}
|
|
224
247
|
function ChatComposerAttachmentDescription({ className, children, ...props }) {
|
|
225
248
|
const context = useChatComposerAttachmentContext();
|
|
249
|
+
const content = children ?? defaultDescription(context);
|
|
226
250
|
return /* @__PURE__ */ jsx("div", {
|
|
227
251
|
"data-control-ui": "chat-composer-attachment",
|
|
228
252
|
"data-control-family": "chat-composer-attachment",
|
|
229
253
|
"data-slot": "description",
|
|
254
|
+
title: typeof content === "string" ? content : void 0,
|
|
230
255
|
className: cn("truncate", className),
|
|
231
256
|
"data-state": context.status,
|
|
232
257
|
...props,
|
|
233
|
-
children:
|
|
258
|
+
children: content
|
|
234
259
|
});
|
|
235
260
|
}
|
|
236
261
|
function ChatComposerAttachmentRemove({ className, onClick, children, "aria-label": ariaLabel, ...props }) {
|
|
@@ -248,7 +273,7 @@ function ChatComposerAttachmentRemove({ className, onClick, children, "aria-labe
|
|
|
248
273
|
"aria-label": ariaLabel ?? removeLabel ?? `Remove ${name}`,
|
|
249
274
|
size: "xs",
|
|
250
275
|
variant: "solid",
|
|
251
|
-
className: cn("absolute
|
|
276
|
+
className: cn("absolute end-1 top-1 z-10", className),
|
|
252
277
|
onClick: handleClick,
|
|
253
278
|
...props,
|
|
254
279
|
children: children ?? /* @__PURE__ */ jsx(XIcon, {
|
|
@@ -8,6 +8,10 @@ export type MentionExtensionConfig<Item extends TriggerMenuItemData = TriggerMen
|
|
|
8
8
|
triggers: readonly TriggerConfig<Item>[];
|
|
9
9
|
side?: "top" | "bottom";
|
|
10
10
|
align?: "start" | "center" | "end";
|
|
11
|
+
/** Shown and announced when a trigger's query matches nothing. */
|
|
12
|
+
emptyLabel?: string;
|
|
13
|
+
/** Announced while the menu is open, so opening it and narrowing it are heard from the editor. */
|
|
14
|
+
resultsLabel?: (count: number) => string;
|
|
11
15
|
};
|
|
12
|
-
export declare function mentionExtension<Item extends TriggerMenuItemData = TriggerMenuItemData>({ triggers, side, align }: MentionExtensionConfig<Item>): ChatComposerEditorExtension;
|
|
16
|
+
export declare function mentionExtension<Item extends TriggerMenuItemData = TriggerMenuItemData>({ triggers, side, align, emptyLabel, resultsLabel }: MentionExtensionConfig<Item>): ChatComposerEditorExtension;
|
|
13
17
|
//#endregion
|