@adea-ai/ui 0.88.0 → 0.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/components/composites/settings/index.d.ts +2 -0
- package/dist/components/composites/settings/index.d.ts.map +1 -1
- package/dist/components/composites/settings/index.js +3 -1
- package/dist/components/composites/settings/settings-layout.d.ts +28 -0
- package/dist/components/composites/settings/settings-layout.d.ts.map +1 -0
- package/dist/components/composites/settings/settings-layout.js +62 -0
- package/dist/components/composites/settings/settings-layout.js.map +1 -0
- package/dist/components/composites/settings/settings-navigation.d.ts +41 -0
- package/dist/components/composites/settings/settings-navigation.d.ts.map +1 -0
- package/dist/components/composites/settings/settings-navigation.js +102 -0
- package/dist/components/composites/settings/settings-navigation.js.map +1 -0
- package/dist/components/layout/top-bar/top-bar.d.ts +3 -1
- package/dist/components/layout/top-bar/top-bar.d.ts.map +1 -1
- package/dist/components/layout/top-bar/top-bar.js +4 -4
- package/dist/components/layout/top-bar/top-bar.js.map +1 -1
- package/dist/components/ui/tabs/tabs.d.ts.map +1 -1
- package/dist/components/ui/tabs/tabs.js +70 -13
- package/dist/components/ui/tabs/tabs.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/r/registry.json +12 -0
- package/dist/r/settings.json +12 -0
- package/dist/r/src/components/composites/settings/index.ts +7 -0
- package/dist/r/src/components/composites/settings/settings-layout.tsx +65 -0
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +135 -0
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +9 -5
- package/dist/r/src/components/ui/tabs/tabs.tsx +80 -10
- package/package.json +2 -1
- package/registry.json +12 -0
- package/src/components/composites/settings/index.ts +7 -0
- package/src/components/composites/settings/settings-layout.tsx +65 -0
- package/src/components/composites/settings/settings-navigation.tsx +135 -0
- package/src/components/layout/top-bar/top-bar.tsx +9 -5
- package/src/components/ui/tabs/tabs.tsx +80 -10
package/dist/index.js
CHANGED
|
@@ -106,6 +106,8 @@ import { CatalogBrowser } from "./components/composites/catalog-browser/catalog-
|
|
|
106
106
|
import { CatalogDetail, CatalogDetailSection } from "./components/composites/catalog-browser/catalog-detail.js";
|
|
107
107
|
import { ListGroup, ListRow } from "./components/composites/list-row/list-row.js";
|
|
108
108
|
import { SettingsField, SettingsPage, SettingsRow, SettingsSection } from "./components/composites/settings/settings.js";
|
|
109
|
+
import { SettingsNavigation } from "./components/composites/settings/settings-navigation.js";
|
|
110
|
+
import { SettingsLayout } from "./components/composites/settings/settings-layout.js";
|
|
109
111
|
import { PropertyList, PropertyRow, PropertyTerm, PropertyValue, Stat, StatGroup } from "./components/composites/stat/stat.js";
|
|
110
112
|
import { PalettePreview, ThemeMiniature, ThemeMiniatureSplit } from "./components/composites/appearance-editor/theme-preview.js";
|
|
111
113
|
import { AppearanceEditor, AppearancePopover } from "./components/composites/appearance-editor/appearance-editor.js";
|
|
@@ -113,4 +115,4 @@ import { formatBytes, formatReleaseDate, plainTextFromMarkdown } from "./lib/ver
|
|
|
113
115
|
import { UpdateDialog } from "./components/composites/update-dialog/update-dialog.js";
|
|
114
116
|
import { WorkspaceMark } from "./components/composites/workspace-mark/workspace-mark.js";
|
|
115
117
|
import { writeClipboardText } from "./lib/clipboard.js";
|
|
116
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdGroup, Label, ListGroup, ListRow, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavResizeHandle, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, formatBytes, formatReleaseDate, formatToken, initialsFrom, inlineScriptLiteral, isPasteBlock, itemVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeLayout, parseDiff, plainTextFromMarkdown, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, themeById, themeCssVariables, themeFamilies, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, writeClipboardText, zIndexTokens };
|
|
118
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdGroup, Label, ListGroup, ListRow, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavResizeHandle, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, formatBytes, formatReleaseDate, formatToken, initialsFrom, inlineScriptLiteral, isPasteBlock, itemVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeLayout, parseDiff, plainTextFromMarkdown, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, themeById, themeCssVariables, themeFamilies, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, writeClipboardText, zIndexTokens };
|
package/dist/r/registry.json
CHANGED
|
@@ -1960,6 +1960,8 @@
|
|
|
1960
1960
|
"description": "",
|
|
1961
1961
|
"dependencies": [],
|
|
1962
1962
|
"registryDependencies": [
|
|
1963
|
+
"@adea-ai/ui/sidebar-nav",
|
|
1964
|
+
"@adea-ai/ui/tabs",
|
|
1963
1965
|
"lib"
|
|
1964
1966
|
],
|
|
1965
1967
|
"files": [
|
|
@@ -1968,6 +1970,16 @@
|
|
|
1968
1970
|
"type": "registry:ui",
|
|
1969
1971
|
"target": "components/composites/settings/index.ts"
|
|
1970
1972
|
},
|
|
1973
|
+
{
|
|
1974
|
+
"path": "src/components/composites/settings/settings-layout.tsx",
|
|
1975
|
+
"type": "registry:ui",
|
|
1976
|
+
"target": "components/composites/settings/settings-layout.tsx"
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
"path": "src/components/composites/settings/settings-navigation.tsx",
|
|
1980
|
+
"type": "registry:ui",
|
|
1981
|
+
"target": "components/composites/settings/settings-navigation.tsx"
|
|
1982
|
+
},
|
|
1971
1983
|
{
|
|
1972
1984
|
"path": "src/components/composites/settings/settings.tsx",
|
|
1973
1985
|
"type": "registry:ui",
|
package/dist/r/settings.json
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
"description": "",
|
|
6
6
|
"dependencies": [],
|
|
7
7
|
"registryDependencies": [
|
|
8
|
+
"@adea-ai/ui/sidebar-nav",
|
|
9
|
+
"@adea-ai/ui/tabs",
|
|
8
10
|
"lib"
|
|
9
11
|
],
|
|
10
12
|
"files": [
|
|
@@ -13,6 +15,16 @@
|
|
|
13
15
|
"type": "registry:ui",
|
|
14
16
|
"target": "components/composites/settings/index.ts"
|
|
15
17
|
},
|
|
18
|
+
{
|
|
19
|
+
"path": "src/components/composites/settings/settings-layout.tsx",
|
|
20
|
+
"type": "registry:ui",
|
|
21
|
+
"target": "components/composites/settings/settings-layout.tsx"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "src/components/composites/settings/settings-navigation.tsx",
|
|
25
|
+
"type": "registry:ui",
|
|
26
|
+
"target": "components/composites/settings/settings-navigation.tsx"
|
|
27
|
+
},
|
|
16
28
|
{
|
|
17
29
|
"path": "src/components/composites/settings/settings.tsx",
|
|
18
30
|
"type": "registry:ui",
|
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export { SettingsField, SettingsPage, SettingsRow, SettingsSection } from './settings'
|
|
2
|
+
export { SettingsLayout, type SettingsLayoutProps } from './settings-layout'
|
|
3
|
+
export {
|
|
4
|
+
SettingsNavigation,
|
|
5
|
+
type SettingsNavigationGroup,
|
|
6
|
+
type SettingsNavigationItem,
|
|
7
|
+
type SettingsNavigationProps,
|
|
8
|
+
} from './settings-navigation'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
import { Tabs } from '../../ui/tabs'
|
|
5
|
+
import { SettingsNavigation, type SettingsNavigationGroup } from './settings-navigation'
|
|
6
|
+
|
|
7
|
+
export type SettingsLayoutProps = Omit<
|
|
8
|
+
ComponentProps<typeof Tabs>,
|
|
9
|
+
'children' | 'orientation' | 'value' | 'defaultValue' | 'onChange'
|
|
10
|
+
> & {
|
|
11
|
+
/** Grouped navigation entries; the host owns their values and panel content. */
|
|
12
|
+
groups: readonly SettingsNavigationGroup[]
|
|
13
|
+
/** Accessible name for the vertical tab list. */
|
|
14
|
+
'aria-label': string
|
|
15
|
+
/** The host-controlled selected destination. */
|
|
16
|
+
value: string
|
|
17
|
+
/** Updates the host-controlled selected destination. */
|
|
18
|
+
onChange: (value: string) => void
|
|
19
|
+
/** Called when the already-selected destination is activated again. */
|
|
20
|
+
onReselect?: (value: string) => void
|
|
21
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scroll. */
|
|
22
|
+
revealSelected?: boolean | ((trigger: HTMLButtonElement | undefined) => void)
|
|
23
|
+
/** Panels must be rendered as `TabsContent` descendants. */
|
|
24
|
+
children?: JSX.Element
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* SettingsLayout.
|
|
29
|
+
*
|
|
30
|
+
* A controlled, vertical settings rail beside its scrollable panel viewport.
|
|
31
|
+
* The host keeps ownership of selection, URL/hash state and panel content.
|
|
32
|
+
* At narrow viewports the rail contracts while both columns remain shrinkable.
|
|
33
|
+
*/
|
|
34
|
+
export function SettingsLayout(props: SettingsLayoutProps) {
|
|
35
|
+
const [local, rest] = splitProps(props, [
|
|
36
|
+
'class',
|
|
37
|
+
'children',
|
|
38
|
+
'groups',
|
|
39
|
+
'aria-label',
|
|
40
|
+
'value',
|
|
41
|
+
'onReselect',
|
|
42
|
+
'revealSelected',
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Tabs
|
|
47
|
+
{...rest}
|
|
48
|
+
orientation="vertical"
|
|
49
|
+
value={local.value}
|
|
50
|
+
class={cn('min-h-0 min-w-0 flex-1 gap-0', local.class)}
|
|
51
|
+
>
|
|
52
|
+
<SettingsNavigation
|
|
53
|
+
aria-label={local['aria-label']}
|
|
54
|
+
groups={local.groups}
|
|
55
|
+
value={local.value}
|
|
56
|
+
onReselect={local.onReselect}
|
|
57
|
+
revealSelected={local.revealSelected}
|
|
58
|
+
class="w-24 md:w-sidebar"
|
|
59
|
+
/>
|
|
60
|
+
<div data-slot="settings-layout-panels" class="min-h-0 min-w-0 flex-1 overflow-y-auto p-4">
|
|
61
|
+
{local.children}
|
|
62
|
+
</div>
|
|
63
|
+
</Tabs>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js'
|
|
2
|
+
import { createEffect, createUniqueId, onCleanup, splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
import { sidebarNavItemClass, sidebarNavItemStateClass } from '../../layout/sidebar-nav/sidebar-nav'
|
|
5
|
+
import { TabsList, TabsTrigger, type TabsListProps } from '../../ui/tabs'
|
|
6
|
+
|
|
7
|
+
/** One host-owned destination in a settings tab list. Values must be unique. */
|
|
8
|
+
export type SettingsNavigationItem = {
|
|
9
|
+
value: string
|
|
10
|
+
label: string
|
|
11
|
+
icon?: JSX.Element
|
|
12
|
+
disabled?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A visible, accessibly named group of settings destinations. */
|
|
16
|
+
export type SettingsNavigationGroup = {
|
|
17
|
+
label: string
|
|
18
|
+
items: readonly SettingsNavigationItem[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type SettingsNavigationProps = Omit<
|
|
22
|
+
TabsListProps,
|
|
23
|
+
'appearance' | 'children' | 'orientation'
|
|
24
|
+
> & {
|
|
25
|
+
/** Groups are presentation only; the host owns the tab values and panels. */
|
|
26
|
+
groups: readonly SettingsNavigationGroup[]
|
|
27
|
+
/** The same controlled value supplied to the enclosing `Tabs`. */
|
|
28
|
+
value: string
|
|
29
|
+
/** Called when the already-selected destination is activated again. */
|
|
30
|
+
onReselect?: (value: string) => void
|
|
31
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scroll. */
|
|
32
|
+
revealSelected?: boolean | ((trigger: HTMLButtonElement | undefined) => void)
|
|
33
|
+
/** Every tab list needs a label independent of its visible group headings. */
|
|
34
|
+
'aria-label': string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* SettingsNavigation.
|
|
39
|
+
*
|
|
40
|
+
* A grouped vertical tab list for sibling settings panels. It composes the
|
|
41
|
+
* shared Tabs behaviour with the shared sidebar row recipe; the host supplies
|
|
42
|
+
* the controlled value, panel content, icons and any persistence or routing.
|
|
43
|
+
* Use ordinary tabs for a short, ungrouped row of view choices.
|
|
44
|
+
*
|
|
45
|
+
* Kobalte owns roving focus, arrow keys, selection and tab/panel ARIA. This
|
|
46
|
+
* component adds no URL, storage or host-specific state. Set
|
|
47
|
+
* `revealSelected={false}` when the surrounding layout does not use an internal
|
|
48
|
+
* scrolling viewport.
|
|
49
|
+
*/
|
|
50
|
+
export function SettingsNavigation(props: SettingsNavigationProps) {
|
|
51
|
+
const [local, rest] = splitProps(props, [
|
|
52
|
+
'class',
|
|
53
|
+
'aria-label',
|
|
54
|
+
'groups',
|
|
55
|
+
'value',
|
|
56
|
+
'onReselect',
|
|
57
|
+
'revealSelected',
|
|
58
|
+
])
|
|
59
|
+
const triggers = new Map<string, HTMLButtonElement>()
|
|
60
|
+
const groupIdPrefix = `settings-navigation-${createUniqueId()}`
|
|
61
|
+
|
|
62
|
+
createEffect(() => {
|
|
63
|
+
const value = local.value
|
|
64
|
+
const reveal = local.revealSelected
|
|
65
|
+
if (reveal === false) return
|
|
66
|
+
|
|
67
|
+
const revealCurrent = () => {
|
|
68
|
+
const trigger = triggers.get(value)
|
|
69
|
+
if (typeof reveal === 'function') reveal(trigger)
|
|
70
|
+
else trigger?.scrollIntoView({ block: 'nearest', inline: 'nearest' })
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
revealCurrent()
|
|
74
|
+
window.addEventListener('resize', revealCurrent)
|
|
75
|
+
onCleanup(() => window.removeEventListener('resize', revealCurrent))
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<TabsList
|
|
80
|
+
data-slot="settings-navigation"
|
|
81
|
+
aria-label={local['aria-label']}
|
|
82
|
+
orientation="vertical"
|
|
83
|
+
class={cn(
|
|
84
|
+
'flex max-h-full min-h-0 min-w-0 shrink-0 flex-col items-stretch justify-start gap-2 overflow-x-hidden overflow-y-auto px-2 py-2',
|
|
85
|
+
local.class
|
|
86
|
+
)}
|
|
87
|
+
{...rest}
|
|
88
|
+
>
|
|
89
|
+
{local.groups.map((group, groupIndex) => {
|
|
90
|
+
const groupId = `${groupIdPrefix}-group-${groupIndex}`
|
|
91
|
+
return (
|
|
92
|
+
<div
|
|
93
|
+
role="none"
|
|
94
|
+
data-slot="settings-navigation-group"
|
|
95
|
+
class="flex min-w-0 flex-col gap-0.5"
|
|
96
|
+
>
|
|
97
|
+
<span id={groupId} class="sr-only">
|
|
98
|
+
{group.label}
|
|
99
|
+
</span>
|
|
100
|
+
<span
|
|
101
|
+
aria-hidden="true"
|
|
102
|
+
class="px-2 py-1.5 text-2xs font-medium tracking-wide text-sidebar-muted-foreground uppercase"
|
|
103
|
+
>
|
|
104
|
+
{group.label}
|
|
105
|
+
</span>
|
|
106
|
+
{group.items.map((item) => (
|
|
107
|
+
<TabsTrigger
|
|
108
|
+
data-slot="settings-navigation-trigger"
|
|
109
|
+
orientation="vertical"
|
|
110
|
+
aria-describedby={groupId}
|
|
111
|
+
value={item.value}
|
|
112
|
+
disabled={item.disabled}
|
|
113
|
+
ref={(element: HTMLButtonElement | undefined) => {
|
|
114
|
+
if (element) triggers.set(item.value, element)
|
|
115
|
+
else triggers.delete(item.value)
|
|
116
|
+
}}
|
|
117
|
+
onClick={() => {
|
|
118
|
+
if (local.value === item.value) local.onReselect?.(item.value)
|
|
119
|
+
}}
|
|
120
|
+
class={cn(
|
|
121
|
+
sidebarNavItemClass,
|
|
122
|
+
sidebarNavItemStateClass.idle,
|
|
123
|
+
'h-row-lg w-full justify-start border-0 px-3 py-2 text-left data-[selected]:bg-primary-subtle data-[selected]:text-foreground'
|
|
124
|
+
)}
|
|
125
|
+
>
|
|
126
|
+
{item.icon}
|
|
127
|
+
<span class="min-w-0 truncate">{item.label}</span>
|
|
128
|
+
</TabsTrigger>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
)
|
|
132
|
+
})}
|
|
133
|
+
</TabsList>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
@@ -41,7 +41,7 @@ export function TopBar(props: TopBarProps) {
|
|
|
41
41
|
<header
|
|
42
42
|
data-slot="top-bar"
|
|
43
43
|
class={cn(
|
|
44
|
-
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[
|
|
44
|
+
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 border-b border-border bg-card text-card-foreground px-3 md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]',
|
|
45
45
|
local.glass && 'glass-panel',
|
|
46
46
|
local.draggable && 'window-drag',
|
|
47
47
|
local.macosInset && 'window-inset-macos',
|
|
@@ -61,7 +61,7 @@ export function TopBarSection(props: ComponentProps<'div'> & { align?: 'start' |
|
|
|
61
61
|
<div
|
|
62
62
|
data-slot="top-bar-section"
|
|
63
63
|
class={cn(
|
|
64
|
-
'flex min-w-0 items-center gap-2 overflow-hidden',
|
|
64
|
+
'window-no-drag flex min-w-0 items-center gap-2 overflow-x-auto overflow-y-hidden',
|
|
65
65
|
local.align === 'end' && 'justify-end',
|
|
66
66
|
local.align !== 'end' && 'justify-start',
|
|
67
67
|
local.class
|
|
@@ -71,12 +71,16 @@ export function TopBarSection(props: ComponentProps<'div'> & { align?: 'start' |
|
|
|
71
71
|
)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
export function TopBarTitle(props: ComponentProps<'div'>) {
|
|
75
|
-
const [local, rest] = splitProps(props, ['class'])
|
|
74
|
+
export function TopBarTitle(props: ComponentProps<'div'> & { align?: 'start' | 'center' }) {
|
|
75
|
+
const [local, rest] = splitProps(props, ['class', 'align'])
|
|
76
76
|
return (
|
|
77
77
|
<div
|
|
78
78
|
data-slot="top-bar-title"
|
|
79
|
-
class={cn(
|
|
79
|
+
class={cn(
|
|
80
|
+
'truncate text-sm font-medium',
|
|
81
|
+
local.align === 'center' && 'text-center',
|
|
82
|
+
local.class
|
|
83
|
+
)}
|
|
80
84
|
{...rest}
|
|
81
85
|
/>
|
|
82
86
|
)
|
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { Tabs as KobalteTabs } from '@kobalte/core/tabs'
|
|
2
|
-
import type { ComponentProps } from 'solid-js'
|
|
3
|
-
import {
|
|
2
|
+
import type { Accessor, ComponentProps } from 'solid-js'
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
createRenderEffect,
|
|
6
|
+
createSignal,
|
|
7
|
+
createUniqueId,
|
|
8
|
+
onCleanup,
|
|
9
|
+
splitProps,
|
|
10
|
+
useContext,
|
|
11
|
+
} from 'solid-js'
|
|
4
12
|
import { cn } from '../../../lib/utils'
|
|
5
13
|
|
|
14
|
+
type TabsIdContextValue = {
|
|
15
|
+
id: Accessor<string>
|
|
16
|
+
triggerIds: Accessor<ReadonlyMap<string, string>>
|
|
17
|
+
registerTriggerId: (value: string, id: string) => void
|
|
18
|
+
unregisterTriggerId: (value: string, id: string) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const TabsIdContext = createContext<TabsIdContextValue>()
|
|
22
|
+
|
|
23
|
+
function useTabsId() {
|
|
24
|
+
const tabs = useContext(TabsIdContext)
|
|
25
|
+
if (!tabs) throw new Error('[adea-ui]: Tabs parts must be used within Tabs.')
|
|
26
|
+
return tabs
|
|
27
|
+
}
|
|
28
|
+
|
|
6
29
|
/**
|
|
7
30
|
* Tabs.
|
|
8
31
|
*
|
|
@@ -14,12 +37,37 @@ import { cn } from '../../../lib/utils'
|
|
|
14
37
|
* where a full-width underline would collide with the panel's own header rule.
|
|
15
38
|
*/
|
|
16
39
|
export function Tabs(props: ComponentProps<typeof KobalteTabs>) {
|
|
17
|
-
const [local, rest] = splitProps(props, ['class'])
|
|
40
|
+
const [local, rest] = splitProps(props, ['class', 'id'])
|
|
41
|
+
const generatedId = `tabs-${createUniqueId()}`
|
|
42
|
+
const id = () => local.id ?? generatedId
|
|
43
|
+
const [triggerIds, setTriggerIds] = createSignal<ReadonlyMap<string, string>>(new Map())
|
|
44
|
+
const tabs: TabsIdContextValue = {
|
|
45
|
+
id,
|
|
46
|
+
triggerIds,
|
|
47
|
+
registerTriggerId: (value, triggerId) => {
|
|
48
|
+
setTriggerIds((current) => new Map(current).set(value, triggerId))
|
|
49
|
+
},
|
|
50
|
+
unregisterTriggerId: (value, triggerId) => {
|
|
51
|
+
setTriggerIds((current) => {
|
|
52
|
+
if (current.get(value) !== triggerId) return current
|
|
53
|
+
const next = new Map(current)
|
|
54
|
+
next.delete(value)
|
|
55
|
+
return next
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
18
60
|
return (
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
61
|
+
<TabsIdContext.Provider value={tabs}>
|
|
62
|
+
<KobalteTabs
|
|
63
|
+
id={id()}
|
|
64
|
+
class={cn(
|
|
65
|
+
'flex min-h-0 min-w-0 flex-col gap-2 data-[orientation=vertical]:flex-row',
|
|
66
|
+
local.class
|
|
67
|
+
)}
|
|
68
|
+
{...rest}
|
|
69
|
+
/>
|
|
70
|
+
</TabsIdContext.Provider>
|
|
23
71
|
)
|
|
24
72
|
}
|
|
25
73
|
|
|
@@ -50,10 +98,21 @@ export type TabsTriggerProps = ComponentProps<typeof KobalteTabs.Trigger> & {
|
|
|
50
98
|
}
|
|
51
99
|
|
|
52
100
|
export function TabsTrigger(props: TabsTriggerProps) {
|
|
53
|
-
const [local, rest] = splitProps(props, ['class', 'appearance'])
|
|
101
|
+
const [local, rest] = splitProps(props, ['class', 'appearance', 'id'])
|
|
102
|
+
const tabs = useTabsId()
|
|
103
|
+
const triggerId = () => local.id ?? `${tabs.id()}-trigger-${rest.value}`
|
|
104
|
+
|
|
105
|
+
// Register before panels render, including SSR where createEffect is skipped.
|
|
106
|
+
createRenderEffect(() => {
|
|
107
|
+
const value = rest.value
|
|
108
|
+
const id = triggerId()
|
|
109
|
+
tabs.registerTriggerId(value, id)
|
|
110
|
+
onCleanup(() => tabs.unregisterTriggerId(value, id))
|
|
111
|
+
})
|
|
54
112
|
|
|
55
113
|
return (
|
|
56
114
|
<KobalteTabs.Trigger
|
|
115
|
+
id={triggerId()}
|
|
57
116
|
class={cn(
|
|
58
117
|
'inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap text-sm font-medium',
|
|
59
118
|
'transition-colors ease-out outline-none select-none',
|
|
@@ -72,6 +131,17 @@ export function TabsTrigger(props: TabsTriggerProps) {
|
|
|
72
131
|
}
|
|
73
132
|
|
|
74
133
|
export function TabsContent(props: ComponentProps<typeof KobalteTabs.Content>) {
|
|
75
|
-
const [local, rest] = splitProps(props, ['class'])
|
|
76
|
-
|
|
134
|
+
const [local, rest] = splitProps(props, ['class', 'aria-labelledby'])
|
|
135
|
+
const tabs = useTabsId()
|
|
136
|
+
return (
|
|
137
|
+
<KobalteTabs.Content
|
|
138
|
+
aria-labelledby={
|
|
139
|
+
local['aria-labelledby'] ??
|
|
140
|
+
tabs.triggerIds().get(rest.value) ??
|
|
141
|
+
`${tabs.id()}-trigger-${rest.value}`
|
|
142
|
+
}
|
|
143
|
+
class={cn('min-h-0 min-w-0 flex-1 outline-none', local.class)}
|
|
144
|
+
{...rest}
|
|
145
|
+
/>
|
|
146
|
+
)
|
|
77
147
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.89.1",
|
|
4
4
|
"description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adea",
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"check:packed-layout-renderer": "bun scripts/check-packed-layout-renderer.ts",
|
|
108
108
|
"check:packed-appearance": "bun scripts/check-packed-appearance.ts",
|
|
109
109
|
"check:packed-native-select": "bun scripts/check-packed-native-select.ts",
|
|
110
|
+
"check:packed-settings-navigation": "bun scripts/check-packed-settings-navigation.ts",
|
|
110
111
|
"check:packed-paste-model": "node scripts/check-packed-paste-model.mjs"
|
|
111
112
|
},
|
|
112
113
|
"dependencies": {
|
package/registry.json
CHANGED
|
@@ -1960,6 +1960,8 @@
|
|
|
1960
1960
|
"description": "",
|
|
1961
1961
|
"dependencies": [],
|
|
1962
1962
|
"registryDependencies": [
|
|
1963
|
+
"@adea-ai/ui/sidebar-nav",
|
|
1964
|
+
"@adea-ai/ui/tabs",
|
|
1963
1965
|
"lib"
|
|
1964
1966
|
],
|
|
1965
1967
|
"files": [
|
|
@@ -1968,6 +1970,16 @@
|
|
|
1968
1970
|
"type": "registry:ui",
|
|
1969
1971
|
"target": "components/composites/settings/index.ts"
|
|
1970
1972
|
},
|
|
1973
|
+
{
|
|
1974
|
+
"path": "src/components/composites/settings/settings-layout.tsx",
|
|
1975
|
+
"type": "registry:ui",
|
|
1976
|
+
"target": "components/composites/settings/settings-layout.tsx"
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
"path": "src/components/composites/settings/settings-navigation.tsx",
|
|
1980
|
+
"type": "registry:ui",
|
|
1981
|
+
"target": "components/composites/settings/settings-navigation.tsx"
|
|
1982
|
+
},
|
|
1971
1983
|
{
|
|
1972
1984
|
"path": "src/components/composites/settings/settings.tsx",
|
|
1973
1985
|
"type": "registry:ui",
|
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export { SettingsField, SettingsPage, SettingsRow, SettingsSection } from './settings'
|
|
2
|
+
export { SettingsLayout, type SettingsLayoutProps } from './settings-layout'
|
|
3
|
+
export {
|
|
4
|
+
SettingsNavigation,
|
|
5
|
+
type SettingsNavigationGroup,
|
|
6
|
+
type SettingsNavigationItem,
|
|
7
|
+
type SettingsNavigationProps,
|
|
8
|
+
} from './settings-navigation'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '#lib/utils'
|
|
4
|
+
import { Tabs } from '../../ui/tabs'
|
|
5
|
+
import { SettingsNavigation, type SettingsNavigationGroup } from './settings-navigation'
|
|
6
|
+
|
|
7
|
+
export type SettingsLayoutProps = Omit<
|
|
8
|
+
ComponentProps<typeof Tabs>,
|
|
9
|
+
'children' | 'orientation' | 'value' | 'defaultValue' | 'onChange'
|
|
10
|
+
> & {
|
|
11
|
+
/** Grouped navigation entries; the host owns their values and panel content. */
|
|
12
|
+
groups: readonly SettingsNavigationGroup[]
|
|
13
|
+
/** Accessible name for the vertical tab list. */
|
|
14
|
+
'aria-label': string
|
|
15
|
+
/** The host-controlled selected destination. */
|
|
16
|
+
value: string
|
|
17
|
+
/** Updates the host-controlled selected destination. */
|
|
18
|
+
onChange: (value: string) => void
|
|
19
|
+
/** Called when the already-selected destination is activated again. */
|
|
20
|
+
onReselect?: (value: string) => void
|
|
21
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scroll. */
|
|
22
|
+
revealSelected?: boolean | ((trigger: HTMLButtonElement | undefined) => void)
|
|
23
|
+
/** Panels must be rendered as `TabsContent` descendants. */
|
|
24
|
+
children?: JSX.Element
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* SettingsLayout.
|
|
29
|
+
*
|
|
30
|
+
* A controlled, vertical settings rail beside its scrollable panel viewport.
|
|
31
|
+
* The host keeps ownership of selection, URL/hash state and panel content.
|
|
32
|
+
* At narrow viewports the rail contracts while both columns remain shrinkable.
|
|
33
|
+
*/
|
|
34
|
+
export function SettingsLayout(props: SettingsLayoutProps) {
|
|
35
|
+
const [local, rest] = splitProps(props, [
|
|
36
|
+
'class',
|
|
37
|
+
'children',
|
|
38
|
+
'groups',
|
|
39
|
+
'aria-label',
|
|
40
|
+
'value',
|
|
41
|
+
'onReselect',
|
|
42
|
+
'revealSelected',
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Tabs
|
|
47
|
+
{...rest}
|
|
48
|
+
orientation="vertical"
|
|
49
|
+
value={local.value}
|
|
50
|
+
class={cn('min-h-0 min-w-0 flex-1 gap-0', local.class)}
|
|
51
|
+
>
|
|
52
|
+
<SettingsNavigation
|
|
53
|
+
aria-label={local['aria-label']}
|
|
54
|
+
groups={local.groups}
|
|
55
|
+
value={local.value}
|
|
56
|
+
onReselect={local.onReselect}
|
|
57
|
+
revealSelected={local.revealSelected}
|
|
58
|
+
class="w-24 md:w-sidebar"
|
|
59
|
+
/>
|
|
60
|
+
<div data-slot="settings-layout-panels" class="min-h-0 min-w-0 flex-1 overflow-y-auto p-4">
|
|
61
|
+
{local.children}
|
|
62
|
+
</div>
|
|
63
|
+
</Tabs>
|
|
64
|
+
)
|
|
65
|
+
}
|