@adea-ai/ui 0.87.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 +22 -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/sidebar-nav/index.d.ts +1 -1
- package/dist/components/layout/sidebar-nav/index.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts +18 -2
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.js +42 -11
- package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
- 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/sidebar-nav/index.ts +2 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +71 -16
- 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/sidebar-nav/index.ts +2 -0
- package/src/components/layout/sidebar-nav/sidebar-nav.tsx +71 -16
- package/src/components/layout/top-bar/top-bar.tsx +9 -5
- package/src/components/ui/tabs/tabs.tsx +80 -10
|
@@ -20,7 +20,7 @@ function TopBar(props) {
|
|
|
20
20
|
return (() => {
|
|
21
21
|
var _el$ = _tmpl$();
|
|
22
22
|
spread(_el$, mergeProps({ get ["class"]() {
|
|
23
|
-
return cn("h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[
|
|
23
|
+
return cn("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)]", local.glass && "glass-panel", local.draggable && "window-drag", local.macosInset && "window-inset-macos", local.windowsInset && "window-inset-windows", local.class);
|
|
24
24
|
} }, rest), false, false);
|
|
25
25
|
return _el$;
|
|
26
26
|
})();
|
|
@@ -31,17 +31,17 @@ function TopBarSection(props) {
|
|
|
31
31
|
return (() => {
|
|
32
32
|
var _el$2 = _tmpl$2();
|
|
33
33
|
spread(_el$2, mergeProps({ get ["class"]() {
|
|
34
|
-
return cn("flex min-w-0 items-center gap-2 overflow-hidden", local.align === "end" && "justify-end", local.align !== "end" && "justify-start", local.class);
|
|
34
|
+
return cn("window-no-drag flex min-w-0 items-center gap-2 overflow-x-auto overflow-y-hidden", local.align === "end" && "justify-end", local.align !== "end" && "justify-start", local.class);
|
|
35
35
|
} }, rest), false, false);
|
|
36
36
|
return _el$2;
|
|
37
37
|
})();
|
|
38
38
|
}
|
|
39
39
|
function TopBarTitle(props) {
|
|
40
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
40
|
+
const [local, rest] = splitProps(props, ["class", "align"]);
|
|
41
41
|
return (() => {
|
|
42
42
|
var _el$3 = _tmpl$3();
|
|
43
43
|
spread(_el$3, mergeProps({ get ["class"]() {
|
|
44
|
-
return cn("truncate text-sm font-medium", local.class);
|
|
44
|
+
return cn("truncate text-sm font-medium", local.align === "center" && "text-center", local.class);
|
|
45
45
|
} }, rest), false, false);
|
|
46
46
|
return _el$3;
|
|
47
47
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-bar.js","names":["ComponentProps","Show","splitProps","cn","TopBarProps","draggable","macosInset","windowsInset","glass","TopBar","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","TopBarSection","align","_el$2","_tmpl$2","TopBarTitle","_el$3","_tmpl$3","TopBarBreadcrumb","_el$4","_tmpl$4","TopBarSearchProps","placeholder","shortcut","TopBarSearch","_el$5","_tmpl$6","_el$6","firstChild","_$insert","_$createComponent","when","children","_el$7","_tmpl$5","TopBarPill","label","_el$8","_tmpl$7","_el$9","_$mergeProps","_$createComponent"],"sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * TopBar.\n *\n * The window's title row and primary toolbar. Three tracks: a leading group, a\n * centred search, and a trailing group. The search is a fixed function of the\n * window width and the two side groups are equal remainders, which is what\n * makes the search *exactly* window-centred by construction — no measurement,\n * no observer, no absolutely-positioned overlay to keep clear of.\n *\n * On a frameless desktop window this row is also the drag region, so it carries\n * `window-drag` and the controls inside it opt back out. `macos-inset` and\n * `windows-inset` reserve the space the native window controls occupy, which is\n * why the row can look off-centre in a frameless window and be correct: it is\n * centred in the space the user can actually see.\n */\nexport type TopBarProps = ComponentProps<'header'> & {\n /** Make the row draggable, for a frameless window. */\n draggable?: boolean\n /** Reserve space for the macOS traffic lights. */\n macosInset?: boolean\n /** Reserve space for the Windows caption buttons. */\n windowsInset?: boolean\n /** Blur the content scrolling under the bar. */\n glass?: boolean\n}\n\nexport function TopBar(props: TopBarProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'draggable',\n 'macosInset',\n 'windowsInset',\n 'glass',\n ])\n\n return (\n <header\n data-slot=\"top-bar\"\n class={cn(\n 'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[
|
|
1
|
+
{"version":3,"file":"top-bar.js","names":["ComponentProps","Show","splitProps","cn","TopBarProps","draggable","macosInset","windowsInset","glass","TopBar","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","TopBarSection","align","_el$2","_tmpl$2","TopBarTitle","_el$3","_tmpl$3","TopBarBreadcrumb","_el$4","_tmpl$4","TopBarSearchProps","placeholder","shortcut","TopBarSearch","_el$5","_tmpl$6","_el$6","firstChild","_$insert","_$createComponent","when","children","_el$7","_tmpl$5","TopBarPill","label","_el$8","_tmpl$7","_el$9","_$mergeProps","_$createComponent"],"sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * TopBar.\n *\n * The window's title row and primary toolbar. Three tracks: a leading group, a\n * centred search, and a trailing group. The search is a fixed function of the\n * window width and the two side groups are equal remainders, which is what\n * makes the search *exactly* window-centred by construction — no measurement,\n * no observer, no absolutely-positioned overlay to keep clear of.\n *\n * On a frameless desktop window this row is also the drag region, so it carries\n * `window-drag` and the controls inside it opt back out. `macos-inset` and\n * `windows-inset` reserve the space the native window controls occupy, which is\n * why the row can look off-centre in a frameless window and be correct: it is\n * centred in the space the user can actually see.\n */\nexport type TopBarProps = ComponentProps<'header'> & {\n /** Make the row draggable, for a frameless window. */\n draggable?: boolean\n /** Reserve space for the macOS traffic lights. */\n macosInset?: boolean\n /** Reserve space for the Windows caption buttons. */\n windowsInset?: boolean\n /** Blur the content scrolling under the bar. */\n glass?: boolean\n}\n\nexport function TopBar(props: TopBarProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'draggable',\n 'macosInset',\n 'windowsInset',\n 'glass',\n ])\n\n return (\n <header\n data-slot=\"top-bar\"\n class={cn(\n '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)]',\n local.glass && 'glass-panel',\n local.draggable && 'window-drag',\n local.macosInset && 'window-inset-macos',\n local.windowsInset && 'window-inset-windows',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A side group. Both sides are equal remainders, which centres the search. */\nexport function TopBarSection(props: ComponentProps<'div'> & { align?: 'start' | 'end' }) {\n const [local, rest] = splitProps(props, ['class', 'align'])\n\n return (\n <div\n data-slot=\"top-bar-section\"\n class={cn(\n 'window-no-drag flex min-w-0 items-center gap-2 overflow-x-auto overflow-y-hidden',\n local.align === 'end' && 'justify-end',\n local.align !== 'end' && 'justify-start',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function TopBarTitle(props: ComponentProps<'div'> & { align?: 'start' | 'center' }) {\n const [local, rest] = splitProps(props, ['class', 'align'])\n return (\n <div\n data-slot=\"top-bar-title\"\n class={cn(\n 'truncate text-sm font-medium',\n local.align === 'center' && 'text-center',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A breadcrumb or path readout that yields to the actions when space runs out. */\nexport function TopBarBreadcrumb(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"top-bar-breadcrumb\"\n class={cn('flex min-w-0 items-center gap-1.5 text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport type TopBarSearchProps = ComponentProps<'button'> & {\n /** The hint shown inside the field, e.g. \"Search projects and files\". */\n placeholder?: string\n /** The shortcut chip drawn at the trailing edge, e.g. \"⌘K\". */\n shortcut?: string\n}\n\n/**\n * The search affordance in the middle track.\n *\n * It is a button, not an input, and that is deliberate: clicking it opens the\n * command palette, which already owns the input, the ranking and the keyboard\n * handling. A second live input here would be a second source of truth for the\n * same query. It is styled to read as a field because that is what it behaves\n * like from the user's side.\n */\nexport function TopBarSearch(props: TopBarSearchProps) {\n const [local, rest] = splitProps(props, ['class', 'placeholder', 'shortcut'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-search\"\n class={cn(\n 'text-muted-foreground flex h-control-md w-full items-center gap-2 rounded-md border border-input px-3 text-sm',\n 'transition-colors ease-out outline-none',\n 'hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag',\n local.class\n )}\n {...rest}\n >\n <span class=\"truncate\">{local.placeholder ?? 'Search'}</span>\n <Show when={local.shortcut}>\n <kbd class=\"bg-muted ms-auto hidden h-5 shrink-0 items-center rounded-sm border border-border px-1.5 font-mono text-2xs sm:flex\">\n {local.shortcut}\n </kbd>\n </Show>\n </button>\n )\n}\n\n/**\n * A labelled top-bar control — the readouts KiroCrew puts in the trailing\n * group. Container queries on the group decide which of these survive a narrow\n * window; a caller marks the cheap-to-drop ones and the group handles the rest.\n */\nexport function TopBarPill(props: ComponentProps<'button'> & { label: string }) {\n const [local, rest] = splitProps(props, ['class', 'label', 'children'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-pill\"\n class={cn(\n 'text-muted-foreground inline-flex h-control-sm shrink-0 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium',\n 'transition-colors ease-out outline-none',\n 'hover:border-input hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag [&_svg]:size-3.5 [&_svg]:shrink-0',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <span>{local.label}</span>\n </button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/tabs/tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/tabs/tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,UAAU,CAAA;AA2BxD;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,kCAiC7D;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG;IACpE,UAAU,CAAC,EAAE,WAAW,GAAG,WAAW,CAAA;CACvC,CAAA;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kCAgB5C;AAED,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG;IAC1E,UAAU,CAAC,EAAE,WAAW,GAAG,WAAW,CAAA;CACvC,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kCA+BlD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC,kCAc5E"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { createComponent, mergeProps } from "solid-js/web";
|
|
3
|
-
import { splitProps } from "solid-js";
|
|
3
|
+
import { createContext, createRenderEffect, createSignal, createUniqueId, onCleanup, splitProps, useContext } from "solid-js";
|
|
4
4
|
import { Tabs } from "@kobalte/core/tabs";
|
|
5
5
|
//#region src/components/ui/tabs/tabs.tsx
|
|
6
|
+
var TabsIdContext = createContext();
|
|
7
|
+
function useTabsId() {
|
|
8
|
+
const tabs = useContext(TabsIdContext);
|
|
9
|
+
if (!tabs) throw new Error("[adea-ui]: Tabs parts must be used within Tabs.");
|
|
10
|
+
return tabs;
|
|
11
|
+
}
|
|
6
12
|
/**
|
|
7
13
|
* Tabs.
|
|
8
14
|
*
|
|
@@ -14,10 +20,38 @@ import { Tabs } from "@kobalte/core/tabs";
|
|
|
14
20
|
* where a full-width underline would collide with the panel's own header rule.
|
|
15
21
|
*/
|
|
16
22
|
function Tabs$1(props) {
|
|
17
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
const [local, rest] = splitProps(props, ["class", "id"]);
|
|
24
|
+
const generatedId = `tabs-${createUniqueId()}`;
|
|
25
|
+
const id = () => local.id ?? generatedId;
|
|
26
|
+
const [triggerIds, setTriggerIds] = createSignal(/* @__PURE__ */ new Map());
|
|
27
|
+
const tabs = {
|
|
28
|
+
id,
|
|
29
|
+
triggerIds,
|
|
30
|
+
registerTriggerId: (value, triggerId) => {
|
|
31
|
+
setTriggerIds((current) => new Map(current).set(value, triggerId));
|
|
32
|
+
},
|
|
33
|
+
unregisterTriggerId: (value, triggerId) => {
|
|
34
|
+
setTriggerIds((current) => {
|
|
35
|
+
if (current.get(value) !== triggerId) return current;
|
|
36
|
+
const next = new Map(current);
|
|
37
|
+
next.delete(value);
|
|
38
|
+
return next;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return createComponent(TabsIdContext.Provider, {
|
|
43
|
+
value: tabs,
|
|
44
|
+
get children() {
|
|
45
|
+
return createComponent(Tabs, mergeProps({
|
|
46
|
+
get id() {
|
|
47
|
+
return id();
|
|
48
|
+
},
|
|
49
|
+
get ["class"]() {
|
|
50
|
+
return cn("flex min-h-0 min-w-0 flex-col gap-2 data-[orientation=vertical]:flex-row", local.class);
|
|
51
|
+
}
|
|
52
|
+
}, rest));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
21
55
|
}
|
|
22
56
|
function TabsList(props) {
|
|
23
57
|
const [local, rest] = splitProps(props, ["class", "appearance"]);
|
|
@@ -26,16 +60,39 @@ function TabsList(props) {
|
|
|
26
60
|
} }, rest));
|
|
27
61
|
}
|
|
28
62
|
function TabsTrigger(props) {
|
|
29
|
-
const [local, rest] = splitProps(props, [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
63
|
+
const [local, rest] = splitProps(props, [
|
|
64
|
+
"class",
|
|
65
|
+
"appearance",
|
|
66
|
+
"id"
|
|
67
|
+
]);
|
|
68
|
+
const tabs = useTabsId();
|
|
69
|
+
const triggerId = () => local.id ?? `${tabs.id()}-trigger-${rest.value}`;
|
|
70
|
+
createRenderEffect(() => {
|
|
71
|
+
const value = rest.value;
|
|
72
|
+
const id = triggerId();
|
|
73
|
+
tabs.registerTriggerId(value, id);
|
|
74
|
+
onCleanup(() => tabs.unregisterTriggerId(value, id));
|
|
75
|
+
});
|
|
76
|
+
return createComponent(Tabs.Trigger, mergeProps({
|
|
77
|
+
get id() {
|
|
78
|
+
return triggerId();
|
|
79
|
+
},
|
|
80
|
+
get ["class"]() {
|
|
81
|
+
return cn("inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap text-sm font-medium", "transition-colors ease-out outline-none select-none", "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle", "disabled:pointer-events-none disabled:opacity-50", "text-foreground", "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4", local.appearance === "segmented" ? "h-control-sm rounded-md px-control-sm data-[selected]:bg-card data-[selected]:shadow-xs" : "h-control-md -mb-px rounded-none border-b-2 border-transparent px-2 pb-2 data-[selected]:border-primary", local.class);
|
|
82
|
+
}
|
|
83
|
+
}, rest));
|
|
33
84
|
}
|
|
34
85
|
function TabsContent(props) {
|
|
35
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
86
|
+
const [local, rest] = splitProps(props, ["class", "aria-labelledby"]);
|
|
87
|
+
const tabs = useTabsId();
|
|
88
|
+
return createComponent(Tabs.Content, mergeProps({
|
|
89
|
+
get ["aria-labelledby"]() {
|
|
90
|
+
return local["aria-labelledby"] ?? tabs.triggerIds().get(rest.value) ?? `${tabs.id()}-trigger-${rest.value}`;
|
|
91
|
+
},
|
|
92
|
+
get ["class"]() {
|
|
93
|
+
return cn("min-h-0 min-w-0 flex-1 outline-none", local.class);
|
|
94
|
+
}
|
|
95
|
+
}, rest));
|
|
39
96
|
}
|
|
40
97
|
//#endregion
|
|
41
98
|
export { Tabs$1 as Tabs, TabsContent, TabsList, TabsTrigger };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":["Tabs","KobalteTabs","ComponentProps","splitProps","cn","props","local","rest","_$createComponent","_$mergeProps","class","TabsListProps","List","appearance","TabsList","TabsTriggerProps","Trigger","TabsTrigger","TabsContent","Content","Tabs","_$createComponent","KobalteTabs","_$mergeProps"],"sources":["../../../../src/components/ui/tabs/tabs.tsx"],"sourcesContent":["import { Tabs as KobalteTabs } from '@kobalte/core/tabs'\nimport type { ComponentProps } from 'solid-js'\nimport {
|
|
1
|
+
{"version":3,"file":"tabs.js","names":["Tabs","KobalteTabs","Accessor","ComponentProps","createContext","createRenderEffect","createSignal","createUniqueId","onCleanup","splitProps","useContext","cn","TabsIdContextValue","id","triggerIds","ReadonlyMap","registerTriggerId","value","unregisterTriggerId","TabsIdContext","useTabsId","tabs","Error","props","local","rest","generatedId","setTriggerIds","Map","triggerId","current","set","get","next","delete","_$createComponent","Provider","children","_$mergeProps","class","TabsListProps","List","appearance","TabsList","TabsTriggerProps","Trigger","TabsTrigger","TabsContent","Content","aria-labelledby","Tabs","_$createComponent","KobalteTabs","_$mergeProps"],"sources":["../../../../src/components/ui/tabs/tabs.tsx"],"sourcesContent":["import { Tabs as KobalteTabs } from '@kobalte/core/tabs'\nimport type { Accessor, ComponentProps } from 'solid-js'\nimport {\n createContext,\n createRenderEffect,\n createSignal,\n createUniqueId,\n onCleanup,\n splitProps,\n useContext,\n} from 'solid-js'\nimport { cn } from '#lib/utils'\n\ntype TabsIdContextValue = {\n id: Accessor<string>\n triggerIds: Accessor<ReadonlyMap<string, string>>\n registerTriggerId: (value: string, id: string) => void\n unregisterTriggerId: (value: string, id: string) => void\n}\n\nconst TabsIdContext = createContext<TabsIdContextValue>()\n\nfunction useTabsId() {\n const tabs = useContext(TabsIdContext)\n if (!tabs) throw new Error('[adea-ui]: Tabs parts must be used within Tabs.')\n return tabs\n}\n\n/**\n * Tabs.\n *\n * For switching between sibling views of the *same* subject — a file's code,\n * diff and history. Not for moving between pages: a tab is expected to keep\n * its panel and its scroll position, which a route does not.\n *\n * `appearance=\"segmented\"` gives the joined bar KiroCrew uses inside a pane\n * where a full-width underline would collide with the panel's own header rule.\n */\nexport function Tabs(props: ComponentProps<typeof KobalteTabs>) {\n const [local, rest] = splitProps(props, ['class', 'id'])\n const generatedId = `tabs-${createUniqueId()}`\n const id = () => local.id ?? generatedId\n const [triggerIds, setTriggerIds] = createSignal<ReadonlyMap<string, string>>(new Map())\n const tabs: TabsIdContextValue = {\n id,\n triggerIds,\n registerTriggerId: (value, triggerId) => {\n setTriggerIds((current) => new Map(current).set(value, triggerId))\n },\n unregisterTriggerId: (value, triggerId) => {\n setTriggerIds((current) => {\n if (current.get(value) !== triggerId) return current\n const next = new Map(current)\n next.delete(value)\n return next\n })\n },\n }\n\n return (\n <TabsIdContext.Provider value={tabs}>\n <KobalteTabs\n id={id()}\n class={cn(\n 'flex min-h-0 min-w-0 flex-col gap-2 data-[orientation=vertical]:flex-row',\n local.class\n )}\n {...rest}\n />\n </TabsIdContext.Provider>\n )\n}\n\nexport type TabsListProps = ComponentProps<typeof KobalteTabs.List> & {\n appearance?: 'underline' | 'segmented'\n}\n\nexport function TabsList(props: TabsListProps) {\n const [local, rest] = splitProps(props, ['class', 'appearance'])\n\n return (\n <KobalteTabs.List\n class={cn(\n 'inline-flex w-fit shrink-0 items-center justify-center',\n local.appearance === 'segmented'\n ? 'gap-0.5 rounded-lg bg-surface-hover p-0.5'\n : 'gap-1 rounded-none border-b border-border',\n 'data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type TabsTriggerProps = ComponentProps<typeof KobalteTabs.Trigger> & {\n appearance?: 'underline' | 'segmented'\n}\n\nexport function TabsTrigger(props: TabsTriggerProps) {\n const [local, rest] = splitProps(props, ['class', 'appearance', 'id'])\n const tabs = useTabsId()\n const triggerId = () => local.id ?? `${tabs.id()}-trigger-${rest.value}`\n\n // Register before panels render, including SSR where createEffect is skipped.\n createRenderEffect(() => {\n const value = rest.value\n const id = triggerId()\n tabs.registerTriggerId(value, id)\n onCleanup(() => tabs.unregisterTriggerId(value, id))\n })\n\n return (\n <KobalteTabs.Trigger\n id={triggerId()}\n class={cn(\n 'inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap text-sm font-medium',\n 'transition-colors ease-out outline-none select-none',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'text-foreground',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4',\n local.appearance === 'segmented'\n ? 'h-control-sm rounded-md px-control-sm data-[selected]:bg-card data-[selected]:shadow-xs'\n : 'h-control-md -mb-px rounded-none border-b-2 border-transparent px-2 pb-2 data-[selected]:border-primary',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function TabsContent(props: ComponentProps<typeof KobalteTabs.Content>) {\n const [local, rest] = splitProps(props, ['class', 'aria-labelledby'])\n const tabs = useTabsId()\n return (\n <KobalteTabs.Content\n aria-labelledby={\n local['aria-labelledby'] ??\n tabs.triggerIds().get(rest.value) ??\n `${tabs.id()}-trigger-${rest.value}`\n }\n class={cn('min-h-0 min-w-0 flex-1 outline-none', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
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
|
+
}
|