@kjaniec-dev/ui 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +528 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -21
- package/dist/index.d.ts +97 -21
- package/dist/index.js +517 -56
- package/dist/index.js.map +1 -1
- package/package.json +59 -20
package/dist/index.cjs
CHANGED
|
@@ -540,6 +540,7 @@ function useTabs() {
|
|
|
540
540
|
}
|
|
541
541
|
function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
|
|
542
542
|
const [internal, setInternal] = React18__namespace.useState(defaultValue ?? "");
|
|
543
|
+
const uid = React18__namespace.useId();
|
|
543
544
|
const current = value ?? internal;
|
|
544
545
|
const setValue = React18__namespace.useCallback(
|
|
545
546
|
(v) => {
|
|
@@ -548,7 +549,7 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
|
|
|
548
549
|
},
|
|
549
550
|
[value, onValueChange]
|
|
550
551
|
);
|
|
551
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props, children }) });
|
|
552
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue, uid }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props, children }) });
|
|
552
553
|
}
|
|
553
554
|
var TabsList = React18__namespace.forwardRef(
|
|
554
555
|
({ className, onKeyDown, ...props }, ref) => {
|
|
@@ -599,7 +600,7 @@ var TabsList = React18__namespace.forwardRef(
|
|
|
599
600
|
TabsList.displayName = "TabsList";
|
|
600
601
|
var TabsTrigger = React18__namespace.forwardRef(
|
|
601
602
|
({ className, value, children, ...props }, ref) => {
|
|
602
|
-
const { value: current, setValue } = useTabs();
|
|
603
|
+
const { value: current, setValue, uid } = useTabs();
|
|
603
604
|
const active = current === value;
|
|
604
605
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
605
606
|
"button",
|
|
@@ -607,8 +608,8 @@ var TabsTrigger = React18__namespace.forwardRef(
|
|
|
607
608
|
ref,
|
|
608
609
|
type: "button",
|
|
609
610
|
role: "tab",
|
|
610
|
-
id: `tabs-trigger-${value}`,
|
|
611
|
-
"aria-controls": `tabs-panel-${value}`,
|
|
611
|
+
id: `tabs-trigger-${uid}-${value}`,
|
|
612
|
+
"aria-controls": `tabs-panel-${uid}-${value}`,
|
|
612
613
|
"aria-selected": active,
|
|
613
614
|
tabIndex: active ? 0 : -1,
|
|
614
615
|
onClick: () => setValue(value),
|
|
@@ -628,7 +629,7 @@ var TabsTrigger = React18__namespace.forwardRef(
|
|
|
628
629
|
TabsTrigger.displayName = "TabsTrigger";
|
|
629
630
|
var TabsContent = React18__namespace.forwardRef(
|
|
630
631
|
({ className, value, ...props }, ref) => {
|
|
631
|
-
const { value: current } = useTabs();
|
|
632
|
+
const { value: current, uid } = useTabs();
|
|
632
633
|
const active = current === value;
|
|
633
634
|
if (!active) return null;
|
|
634
635
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -636,8 +637,8 @@ var TabsContent = React18__namespace.forwardRef(
|
|
|
636
637
|
{
|
|
637
638
|
ref,
|
|
638
639
|
role: "tabpanel",
|
|
639
|
-
id: `tabs-panel-${value}`,
|
|
640
|
-
"aria-labelledby": `tabs-trigger-${value}`,
|
|
640
|
+
id: `tabs-panel-${uid}-${value}`,
|
|
641
|
+
"aria-labelledby": `tabs-trigger-${uid}-${value}`,
|
|
641
642
|
tabIndex: 0,
|
|
642
643
|
className: cn("pt-5 text-[0.9rem] text-muted-foreground outline-none", className),
|
|
643
644
|
...props
|
|
@@ -1366,23 +1367,39 @@ function DataTable({
|
|
|
1366
1367
|
}[col.align || "left"];
|
|
1367
1368
|
const isSortable = col.sortable && onSort && col.sortKey;
|
|
1368
1369
|
const isSortedActive = sortBy && col.sortKey === sortBy;
|
|
1370
|
+
const ariaSort = isSortable ? isSortedActive ? sortDirection === "asc" ? "ascending" : "descending" : "none" : void 0;
|
|
1369
1371
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1370
1372
|
TableHead,
|
|
1371
1373
|
{
|
|
1372
1374
|
className: cn(
|
|
1373
1375
|
alignClass,
|
|
1374
|
-
isSortable && "
|
|
1376
|
+
isSortable && "p-0 hover:bg-muted/30 transition-colors",
|
|
1375
1377
|
col.className
|
|
1376
1378
|
),
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1379
|
+
"aria-sort": ariaSort,
|
|
1380
|
+
children: isSortable ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1381
|
+
"button",
|
|
1382
|
+
{
|
|
1383
|
+
type: "button",
|
|
1384
|
+
onClick: () => {
|
|
1385
|
+
if (!col.sortKey) return;
|
|
1386
|
+
const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
|
|
1387
|
+
onSort(col.sortKey, nextDirection);
|
|
1388
|
+
},
|
|
1389
|
+
className: cn(
|
|
1390
|
+
"w-full px-4 py-3 flex items-center gap-1.5 font-semibold text-[0.72rem] uppercase tracking-[0.05em] text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 transition-colors cursor-pointer",
|
|
1391
|
+
{
|
|
1392
|
+
"justify-start text-left": col.align === "left" || !col.align,
|
|
1393
|
+
"justify-center text-center": col.align === "center",
|
|
1394
|
+
"justify-end text-right": col.align === "right"
|
|
1395
|
+
}
|
|
1396
|
+
),
|
|
1397
|
+
children: [
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: col.header }),
|
|
1399
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
|
|
1400
|
+
]
|
|
1401
|
+
}
|
|
1402
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: col.header })
|
|
1386
1403
|
},
|
|
1387
1404
|
idx
|
|
1388
1405
|
);
|
|
@@ -1895,7 +1912,7 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1895
1912
|
}, [open, filteredItems, activeIndex, onClose]);
|
|
1896
1913
|
React18__namespace.useEffect(() => {
|
|
1897
1914
|
if (listRef.current) {
|
|
1898
|
-
const activeEl = listRef.current.
|
|
1915
|
+
const activeEl = listRef.current.querySelector('[aria-selected="true"]');
|
|
1899
1916
|
if (activeEl) {
|
|
1900
1917
|
activeEl.scrollIntoView({ block: "nearest" });
|
|
1901
1918
|
}
|
|
@@ -1918,6 +1935,9 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1918
1935
|
"div",
|
|
1919
1936
|
{
|
|
1920
1937
|
ref: containerRef,
|
|
1938
|
+
role: "dialog",
|
|
1939
|
+
"aria-modal": "true",
|
|
1940
|
+
"aria-label": "Command palette",
|
|
1921
1941
|
className: "w-[95vw] max-w-lg bg-surface border border-border rounded-kj-xl shadow-kj-lg flex flex-col overflow-hidden max-h-[500px]",
|
|
1922
1942
|
children: [
|
|
1923
1943
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border flex items-center gap-2", children: [
|
|
@@ -1926,6 +1946,11 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1926
1946
|
"input",
|
|
1927
1947
|
{
|
|
1928
1948
|
type: "text",
|
|
1949
|
+
role: "combobox",
|
|
1950
|
+
"aria-expanded": open,
|
|
1951
|
+
"aria-autocomplete": "list",
|
|
1952
|
+
"aria-controls": "command-palette-listbox",
|
|
1953
|
+
"aria-activedescendant": filteredItems.length > 0 ? `cmd-item-${activeIndex}` : void 0,
|
|
1929
1954
|
placeholder,
|
|
1930
1955
|
value: search,
|
|
1931
1956
|
onChange: (e) => setSearch(e.target.value),
|
|
@@ -1938,44 +1963,64 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1938
1963
|
'No results found for "',
|
|
1939
1964
|
search,
|
|
1940
1965
|
'"'
|
|
1941
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
"
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
"
|
|
1967
|
-
{
|
|
1968
|
-
|
|
1969
|
-
|
|
1966
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1967
|
+
"div",
|
|
1968
|
+
{
|
|
1969
|
+
ref: listRef,
|
|
1970
|
+
id: "command-palette-listbox",
|
|
1971
|
+
role: "listbox",
|
|
1972
|
+
"aria-label": "Commands",
|
|
1973
|
+
className: "space-y-4",
|
|
1974
|
+
children: Object.entries(groups).map(([cat, itemsInCat]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "group", "aria-labelledby": `cmd-cat-${cat}`, className: "space-y-1", children: [
|
|
1975
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1976
|
+
"div",
|
|
1977
|
+
{
|
|
1978
|
+
id: `cmd-cat-${cat}`,
|
|
1979
|
+
className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground",
|
|
1980
|
+
children: cat
|
|
1981
|
+
}
|
|
1982
|
+
),
|
|
1983
|
+
itemsInCat.map((item) => {
|
|
1984
|
+
const currentIdx = absoluteItemIndex++;
|
|
1985
|
+
const isActive = currentIdx === activeIndex;
|
|
1986
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1987
|
+
"div",
|
|
1988
|
+
{
|
|
1989
|
+
id: `cmd-item-${currentIdx}`,
|
|
1990
|
+
role: "option",
|
|
1991
|
+
"aria-selected": isActive,
|
|
1992
|
+
onClick: () => {
|
|
1993
|
+
item.action();
|
|
1994
|
+
onClose();
|
|
1970
1995
|
},
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1996
|
+
className: cn(
|
|
1997
|
+
"flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
|
|
1998
|
+
isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
1999
|
+
),
|
|
2000
|
+
children: [
|
|
2001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
2002
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
|
|
2003
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col", children: [
|
|
2004
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
|
|
2005
|
+
item.subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
|
|
2006
|
+
] })
|
|
2007
|
+
] }),
|
|
2008
|
+
item.shortcut && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2009
|
+
"kbd",
|
|
2010
|
+
{
|
|
2011
|
+
className: "px-1.5 py-0.5 rounded border border-border bg-subtle text-[10px] font-mono leading-none shadow-kj-xs text-muted-foreground",
|
|
2012
|
+
children: sc
|
|
2013
|
+
},
|
|
2014
|
+
scIdx
|
|
2015
|
+
)) })
|
|
2016
|
+
]
|
|
2017
|
+
},
|
|
2018
|
+
item.id
|
|
2019
|
+
);
|
|
2020
|
+
})
|
|
2021
|
+
] }, cat))
|
|
2022
|
+
}
|
|
2023
|
+
) }),
|
|
1979
2024
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2.5 border-t border-border bg-subtle flex items-center justify-between text-[11px] text-muted-foreground font-medium", children: [
|
|
1980
2025
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1981
2026
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
|
|
@@ -2035,6 +2080,422 @@ function SidebarNav({ className, groups, currentHref, ...props }) {
|
|
|
2035
2080
|
] }, groupIdx)) });
|
|
2036
2081
|
}
|
|
2037
2082
|
SidebarNav.displayName = "SidebarNav";
|
|
2083
|
+
var fabVariants = classVarianceAuthority.cva(
|
|
2084
|
+
[
|
|
2085
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap select-none",
|
|
2086
|
+
"font-sans font-semibold leading-none",
|
|
2087
|
+
"border border-transparent rounded-full cursor-pointer shadow-lg",
|
|
2088
|
+
"transition-[background-color,color,border-color,box-shadow,transform] duration-150",
|
|
2089
|
+
"active:translate-y-px active:shadow-md",
|
|
2090
|
+
"focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/45",
|
|
2091
|
+
"disabled:opacity-50 disabled:pointer-events-none"
|
|
2092
|
+
],
|
|
2093
|
+
{
|
|
2094
|
+
variants: {
|
|
2095
|
+
variant: {
|
|
2096
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
2097
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover",
|
|
2098
|
+
outline: "bg-transparent text-foreground border-border hover:bg-muted hover:border-muted-foreground",
|
|
2099
|
+
danger: "bg-danger text-white hover:brightness-95"
|
|
2100
|
+
},
|
|
2101
|
+
size: {
|
|
2102
|
+
sm: "h-10 w-10 p-0 text-sm",
|
|
2103
|
+
md: "h-14 w-14 p-0 text-base",
|
|
2104
|
+
lg: "h-16 w-16 p-0 text-lg"
|
|
2105
|
+
},
|
|
2106
|
+
position: {
|
|
2107
|
+
"bottom-right": "fixed bottom-6 right-6 z-50",
|
|
2108
|
+
"bottom-left": "fixed bottom-6 left-6 z-50",
|
|
2109
|
+
"bottom-center": "fixed bottom-6 left-1/2 -translate-x-1/2 z-50",
|
|
2110
|
+
none: "relative"
|
|
2111
|
+
}
|
|
2112
|
+
},
|
|
2113
|
+
defaultVariants: { variant: "primary", size: "md", position: "bottom-right" }
|
|
2114
|
+
}
|
|
2115
|
+
);
|
|
2116
|
+
var Fab = React18__namespace.forwardRef(
|
|
2117
|
+
({ className, variant, size, position, mobileOnly, icon, label, loading, disabled, ...props }, ref) => {
|
|
2118
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2119
|
+
"button",
|
|
2120
|
+
{
|
|
2121
|
+
ref,
|
|
2122
|
+
className: cn(
|
|
2123
|
+
fabVariants({ variant, size, position }),
|
|
2124
|
+
mobileOnly && "md:hidden",
|
|
2125
|
+
className
|
|
2126
|
+
),
|
|
2127
|
+
...props,
|
|
2128
|
+
disabled: disabled || loading,
|
|
2129
|
+
"aria-label": label,
|
|
2130
|
+
"aria-busy": loading || void 0,
|
|
2131
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2132
|
+
"span",
|
|
2133
|
+
{
|
|
2134
|
+
"aria-hidden": true,
|
|
2135
|
+
className: "h-[1.2em] w-[1.2em] rounded-full border-2 border-current border-t-transparent animate-spin"
|
|
2136
|
+
}
|
|
2137
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "[&_svg]:h-[1.35em] [&_svg]:w-[1.35em] flex items-center justify-center", children: icon })
|
|
2138
|
+
}
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
);
|
|
2142
|
+
Fab.displayName = "Fab";
|
|
2143
|
+
var BottomSheetContext = React18__namespace.createContext(null);
|
|
2144
|
+
function BottomSheet({
|
|
2145
|
+
open,
|
|
2146
|
+
onClose,
|
|
2147
|
+
children,
|
|
2148
|
+
maxWidth = "max-w-lg",
|
|
2149
|
+
className,
|
|
2150
|
+
showClose = true
|
|
2151
|
+
}) {
|
|
2152
|
+
const titleId = React18__namespace.useId();
|
|
2153
|
+
const descId = React18__namespace.useId();
|
|
2154
|
+
const containerRef = React18__namespace.useRef(null);
|
|
2155
|
+
const lastActiveElement = React18__namespace.useRef(null);
|
|
2156
|
+
const [mounted, setMounted] = React18__namespace.useState(open);
|
|
2157
|
+
React18__namespace.useEffect(() => {
|
|
2158
|
+
if (open) {
|
|
2159
|
+
setMounted(true);
|
|
2160
|
+
} else {
|
|
2161
|
+
const timer = setTimeout(() => setMounted(false), 200);
|
|
2162
|
+
return () => clearTimeout(timer);
|
|
2163
|
+
}
|
|
2164
|
+
}, [open]);
|
|
2165
|
+
React18__namespace.useEffect(() => {
|
|
2166
|
+
if (!open) return;
|
|
2167
|
+
lastActiveElement.current = document.activeElement;
|
|
2168
|
+
const container = containerRef.current;
|
|
2169
|
+
if (container) {
|
|
2170
|
+
const focusables = container.querySelectorAll(
|
|
2171
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
2172
|
+
);
|
|
2173
|
+
if (focusables.length > 0) {
|
|
2174
|
+
focusables[0].focus();
|
|
2175
|
+
setTimeout(() => {
|
|
2176
|
+
if (container.contains(document.activeElement)) return;
|
|
2177
|
+
focusables[0].focus();
|
|
2178
|
+
}, 50);
|
|
2179
|
+
} else {
|
|
2180
|
+
container.focus();
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
const handleKeyDown = (e) => {
|
|
2184
|
+
if (e.key === "Escape") {
|
|
2185
|
+
onClose();
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
if (e.key === "Tab") {
|
|
2189
|
+
const container2 = containerRef.current;
|
|
2190
|
+
if (!container2) return;
|
|
2191
|
+
const focusables = Array.from(
|
|
2192
|
+
container2.querySelectorAll(
|
|
2193
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
2194
|
+
)
|
|
2195
|
+
);
|
|
2196
|
+
if (focusables.length === 0) {
|
|
2197
|
+
e.preventDefault();
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
const first = focusables[0];
|
|
2201
|
+
const last = focusables[focusables.length - 1];
|
|
2202
|
+
if (!container2.contains(document.activeElement)) {
|
|
2203
|
+
e.preventDefault();
|
|
2204
|
+
if (e.shiftKey) {
|
|
2205
|
+
last.focus();
|
|
2206
|
+
} else {
|
|
2207
|
+
first.focus();
|
|
2208
|
+
}
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
if (e.shiftKey) {
|
|
2212
|
+
if (document.activeElement === first || document.activeElement === container2) {
|
|
2213
|
+
last.focus();
|
|
2214
|
+
e.preventDefault();
|
|
2215
|
+
}
|
|
2216
|
+
} else {
|
|
2217
|
+
if (document.activeElement === last) {
|
|
2218
|
+
first.focus();
|
|
2219
|
+
e.preventDefault();
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
};
|
|
2224
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
2225
|
+
document.body.style.overflow = "hidden";
|
|
2226
|
+
return () => {
|
|
2227
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
2228
|
+
document.body.style.overflow = "";
|
|
2229
|
+
if (lastActiveElement.current) {
|
|
2230
|
+
lastActiveElement.current.focus();
|
|
2231
|
+
lastActiveElement.current = null;
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
2234
|
+
}, [open, onClose]);
|
|
2235
|
+
if (!open && !mounted) return null;
|
|
2236
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BottomSheetContext.Provider, { value: { titleId, descId }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2237
|
+
"div",
|
|
2238
|
+
{
|
|
2239
|
+
role: "presentation",
|
|
2240
|
+
onClick: (e) => e.target === e.currentTarget && onClose(),
|
|
2241
|
+
className: cn(
|
|
2242
|
+
"fixed inset-0 z-[100] grid items-end sm:place-items-center p-0 sm:p-6 backdrop-blur-[3px] transition-all duration-200",
|
|
2243
|
+
"bg-[color-mix(in_oklch,#09090b_55%,transparent)]",
|
|
2244
|
+
open ? "opacity-100 pointer-events-auto visible" : "opacity-0 pointer-events-none invisible"
|
|
2245
|
+
),
|
|
2246
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2247
|
+
"div",
|
|
2248
|
+
{
|
|
2249
|
+
ref: containerRef,
|
|
2250
|
+
role: "dialog",
|
|
2251
|
+
"aria-modal": "true",
|
|
2252
|
+
"aria-labelledby": titleId,
|
|
2253
|
+
"aria-describedby": descId,
|
|
2254
|
+
tabIndex: -1,
|
|
2255
|
+
className: cn(
|
|
2256
|
+
"relative w-full bg-surface border-t sm:border border-border shadow-kj-lg transition-all duration-200 outline-none",
|
|
2257
|
+
"rounded-t-kj-2xl sm:rounded-kj-2xl flex flex-col max-h-[85vh] sm:max-h-[90vh]",
|
|
2258
|
+
// Mobile sliding & Desktop scale/opacity transitions
|
|
2259
|
+
open ? "translate-y-0 sm:scale-100 sm:opacity-100" : "translate-y-full sm:scale-95 sm:opacity-0",
|
|
2260
|
+
// Mobile styling vs Desktop styling
|
|
2261
|
+
"bottom-0 sm:bottom-auto",
|
|
2262
|
+
maxWidth,
|
|
2263
|
+
className
|
|
2264
|
+
),
|
|
2265
|
+
children: [
|
|
2266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2 sm:hidden cursor-grab", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-1.5 rounded-full bg-muted-foreground/20" }) }),
|
|
2267
|
+
showClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2268
|
+
"button",
|
|
2269
|
+
{
|
|
2270
|
+
type: "button",
|
|
2271
|
+
onClick: onClose,
|
|
2272
|
+
"aria-label": "Close",
|
|
2273
|
+
className: "absolute top-4 right-4 p-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer z-10",
|
|
2274
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
2275
|
+
}
|
|
2276
|
+
),
|
|
2277
|
+
children
|
|
2278
|
+
]
|
|
2279
|
+
}
|
|
2280
|
+
)
|
|
2281
|
+
}
|
|
2282
|
+
) });
|
|
2283
|
+
}
|
|
2284
|
+
function BottomSheetHeader({ className, ...props }) {
|
|
2285
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 flex flex-col gap-1.5 border-b border-border", className), ...props });
|
|
2286
|
+
}
|
|
2287
|
+
function BottomSheetTitle({ className, id, ...props }) {
|
|
2288
|
+
const ctx = React18__namespace.useContext(BottomSheetContext);
|
|
2289
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h2", { id: id ?? ctx?.titleId, className: cn("m-0 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
|
|
2290
|
+
}
|
|
2291
|
+
function BottomSheetDescription({ className, id, ...props }) {
|
|
2292
|
+
const ctx = React18__namespace.useContext(BottomSheetContext);
|
|
2293
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
2294
|
+
}
|
|
2295
|
+
function BottomSheetContent({ className, ...props }) {
|
|
2296
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 overflow-y-auto flex-1", className), ...props });
|
|
2297
|
+
}
|
|
2298
|
+
function BottomSheetFooter({ className, ...props }) {
|
|
2299
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 border-t border-border flex gap-2.5 justify-end mt-auto", className), ...props });
|
|
2300
|
+
}
|
|
2301
|
+
var kbdVariants = classVarianceAuthority.cva(
|
|
2302
|
+
"inline-flex items-center justify-center font-mono font-medium text-muted-foreground bg-muted border border-border border-b-2 rounded-kj-sm select-none",
|
|
2303
|
+
{
|
|
2304
|
+
variants: {
|
|
2305
|
+
size: {
|
|
2306
|
+
sm: "h-5 min-w-5 px-1 text-[0.68rem]",
|
|
2307
|
+
md: "h-6 min-w-6 px-1.5 text-[0.78rem]"
|
|
2308
|
+
}
|
|
2309
|
+
},
|
|
2310
|
+
defaultVariants: { size: "sm" }
|
|
2311
|
+
}
|
|
2312
|
+
);
|
|
2313
|
+
var Kbd = React18__namespace.forwardRef(
|
|
2314
|
+
({ className, size, keys, children, ...props }, ref) => {
|
|
2315
|
+
if (keys && keys.length > 0) {
|
|
2316
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2317
|
+
"span",
|
|
2318
|
+
{
|
|
2319
|
+
ref,
|
|
2320
|
+
className: cn("inline-flex items-center gap-1", className),
|
|
2321
|
+
...props,
|
|
2322
|
+
children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: kbdVariants({ size }), children: k }, i))
|
|
2323
|
+
}
|
|
2324
|
+
);
|
|
2325
|
+
}
|
|
2326
|
+
return /* @__PURE__ */ jsxRuntime.jsx("kbd", { ref, className: cn(kbdVariants({ size }), className), ...props, children });
|
|
2327
|
+
}
|
|
2328
|
+
);
|
|
2329
|
+
Kbd.displayName = "Kbd";
|
|
2330
|
+
var CodeBlock = React18__namespace.forwardRef(
|
|
2331
|
+
({ className, code, language, filename, copyable = true, maxHeight, ...props }, ref) => {
|
|
2332
|
+
const [copied, setCopied] = React18__namespace.useState(false);
|
|
2333
|
+
const canCopy = copyable && typeof navigator !== "undefined" && !!navigator.clipboard;
|
|
2334
|
+
const onCopy = () => {
|
|
2335
|
+
navigator.clipboard.writeText(code).then(
|
|
2336
|
+
() => {
|
|
2337
|
+
setCopied(true);
|
|
2338
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
2339
|
+
},
|
|
2340
|
+
() => {
|
|
2341
|
+
}
|
|
2342
|
+
);
|
|
2343
|
+
};
|
|
2344
|
+
const label = filename ?? language;
|
|
2345
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2346
|
+
"div",
|
|
2347
|
+
{
|
|
2348
|
+
ref,
|
|
2349
|
+
className: cn("rounded-kj-md border border-border bg-muted/50 overflow-hidden", className),
|
|
2350
|
+
...props,
|
|
2351
|
+
children: [
|
|
2352
|
+
(label || canCopy) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 px-3.5 py-2 border-b border-border", children: [
|
|
2353
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.72rem] font-mono text-muted-foreground", children: label }),
|
|
2354
|
+
canCopy && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2355
|
+
"button",
|
|
2356
|
+
{
|
|
2357
|
+
type: "button",
|
|
2358
|
+
onClick: onCopy,
|
|
2359
|
+
className: "text-[0.72rem] font-medium text-muted-foreground hover:text-foreground transition-colors cursor-pointer bg-transparent border-0 p-0",
|
|
2360
|
+
children: copied ? "Copied" : "Copy"
|
|
2361
|
+
}
|
|
2362
|
+
)
|
|
2363
|
+
] }),
|
|
2364
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2365
|
+
"pre",
|
|
2366
|
+
{
|
|
2367
|
+
className: "m-0 px-3.5 py-3 overflow-x-auto text-[0.8rem] leading-relaxed font-mono text-foreground",
|
|
2368
|
+
style: maxHeight ? { maxHeight, overflowY: "auto" } : void 0,
|
|
2369
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: code })
|
|
2370
|
+
}
|
|
2371
|
+
)
|
|
2372
|
+
]
|
|
2373
|
+
}
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
);
|
|
2377
|
+
CodeBlock.displayName = "CodeBlock";
|
|
2378
|
+
var PopoverContext = React18__namespace.createContext(null);
|
|
2379
|
+
function usePopoverContext(part) {
|
|
2380
|
+
const ctx = React18__namespace.useContext(PopoverContext);
|
|
2381
|
+
if (!ctx) throw new Error(`${part} must be used inside <Popover>`);
|
|
2382
|
+
return ctx;
|
|
2383
|
+
}
|
|
2384
|
+
function Popover({ children, className, open: openProp, onOpenChange }) {
|
|
2385
|
+
const [openState, setOpenState] = React18__namespace.useState(false);
|
|
2386
|
+
const controlled = openProp !== void 0;
|
|
2387
|
+
const open = controlled ? openProp : openState;
|
|
2388
|
+
const triggerRef = React18__namespace.useRef(null);
|
|
2389
|
+
const ref = React18__namespace.useRef(null);
|
|
2390
|
+
const setOpen = React18__namespace.useCallback(
|
|
2391
|
+
(v) => {
|
|
2392
|
+
if (!controlled) setOpenState(v);
|
|
2393
|
+
onOpenChange?.(v);
|
|
2394
|
+
},
|
|
2395
|
+
[controlled, onOpenChange]
|
|
2396
|
+
);
|
|
2397
|
+
React18__namespace.useEffect(() => {
|
|
2398
|
+
if (!open) return;
|
|
2399
|
+
const onDoc = (e) => {
|
|
2400
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
2401
|
+
};
|
|
2402
|
+
const onEsc = (e) => {
|
|
2403
|
+
if (e.key === "Escape") {
|
|
2404
|
+
setOpen(false);
|
|
2405
|
+
triggerRef.current?.focus();
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
document.addEventListener("mousedown", onDoc);
|
|
2409
|
+
document.addEventListener("keydown", onEsc);
|
|
2410
|
+
return () => {
|
|
2411
|
+
document.removeEventListener("mousedown", onDoc);
|
|
2412
|
+
document.removeEventListener("keydown", onEsc);
|
|
2413
|
+
};
|
|
2414
|
+
}, [open, setOpen]);
|
|
2415
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value: { open, setOpen, triggerRef }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
2416
|
+
}
|
|
2417
|
+
var PopoverTrigger = React18__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
|
|
2418
|
+
const ctx = usePopoverContext("PopoverTrigger");
|
|
2419
|
+
const setRefs = (node) => {
|
|
2420
|
+
ctx.triggerRef.current = node;
|
|
2421
|
+
if (typeof ref === "function") ref(node);
|
|
2422
|
+
else if (ref) ref.current = node;
|
|
2423
|
+
};
|
|
2424
|
+
if (asChild) {
|
|
2425
|
+
const child = React18__namespace.Children.only(props.children);
|
|
2426
|
+
return React18__namespace.cloneElement(child, {
|
|
2427
|
+
ref: setRefs,
|
|
2428
|
+
...props,
|
|
2429
|
+
...child.props,
|
|
2430
|
+
onClick: (e) => {
|
|
2431
|
+
ctx.setOpen(!ctx.open);
|
|
2432
|
+
onClick?.(e);
|
|
2433
|
+
child.props.onClick?.(e);
|
|
2434
|
+
},
|
|
2435
|
+
"aria-haspopup": "dialog",
|
|
2436
|
+
"aria-expanded": ctx.open
|
|
2437
|
+
});
|
|
2438
|
+
}
|
|
2439
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2440
|
+
"button",
|
|
2441
|
+
{
|
|
2442
|
+
ref: setRefs,
|
|
2443
|
+
...props,
|
|
2444
|
+
type: "button",
|
|
2445
|
+
"aria-haspopup": "dialog",
|
|
2446
|
+
"aria-expanded": ctx.open,
|
|
2447
|
+
onClick: (e) => {
|
|
2448
|
+
ctx.setOpen(!ctx.open);
|
|
2449
|
+
onClick?.(e);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
);
|
|
2453
|
+
});
|
|
2454
|
+
PopoverTrigger.displayName = "PopoverTrigger";
|
|
2455
|
+
var sideAlignClasses = {
|
|
2456
|
+
"bottom-start": "top-[calc(100%+6px)] left-0",
|
|
2457
|
+
"bottom-center": "top-[calc(100%+6px)] left-1/2 -translate-x-1/2",
|
|
2458
|
+
"bottom-end": "top-[calc(100%+6px)] right-0",
|
|
2459
|
+
"top-start": "bottom-[calc(100%+6px)] left-0",
|
|
2460
|
+
"top-center": "bottom-[calc(100%+6px)] left-1/2 -translate-x-1/2",
|
|
2461
|
+
"top-end": "bottom-[calc(100%+6px)] right-0",
|
|
2462
|
+
"left-start": "right-[calc(100%+6px)] top-0",
|
|
2463
|
+
"left-center": "right-[calc(100%+6px)] top-1/2 -translate-y-1/2",
|
|
2464
|
+
"left-end": "right-[calc(100%+6px)] bottom-0",
|
|
2465
|
+
"right-start": "left-[calc(100%+6px)] top-0",
|
|
2466
|
+
"right-center": "left-[calc(100%+6px)] top-1/2 -translate-y-1/2",
|
|
2467
|
+
"right-end": "left-[calc(100%+6px)] bottom-0"
|
|
2468
|
+
};
|
|
2469
|
+
function PopoverContent({
|
|
2470
|
+
className,
|
|
2471
|
+
side = "bottom",
|
|
2472
|
+
align = "center",
|
|
2473
|
+
children,
|
|
2474
|
+
...props
|
|
2475
|
+
}) {
|
|
2476
|
+
const ctx = usePopoverContext("PopoverContent");
|
|
2477
|
+
const ref = React18__namespace.useRef(null);
|
|
2478
|
+
React18__namespace.useEffect(() => {
|
|
2479
|
+
if (ctx.open) ref.current?.focus();
|
|
2480
|
+
}, [ctx.open]);
|
|
2481
|
+
if (!ctx.open) return null;
|
|
2482
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2483
|
+
"div",
|
|
2484
|
+
{
|
|
2485
|
+
ref,
|
|
2486
|
+
role: "dialog",
|
|
2487
|
+
tabIndex: -1,
|
|
2488
|
+
className: cn(
|
|
2489
|
+
"absolute z-40 min-w-[200px] p-4 rounded-kj-md bg-surface border border-border shadow-kj-lg outline-none",
|
|
2490
|
+
"animate-[kjpop_.12s_ease]",
|
|
2491
|
+
sideAlignClasses[`${side}-${align}`],
|
|
2492
|
+
className
|
|
2493
|
+
),
|
|
2494
|
+
...props,
|
|
2495
|
+
children
|
|
2496
|
+
}
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2038
2499
|
|
|
2039
2500
|
exports.Accordion = Accordion;
|
|
2040
2501
|
exports.AccordionContent = AccordionContent;
|
|
@@ -2045,6 +2506,12 @@ exports.Avatar = Avatar;
|
|
|
2045
2506
|
exports.AvatarGroup = AvatarGroup;
|
|
2046
2507
|
exports.Badge = Badge;
|
|
2047
2508
|
exports.BottomNavigation = BottomNavigation;
|
|
2509
|
+
exports.BottomSheet = BottomSheet;
|
|
2510
|
+
exports.BottomSheetContent = BottomSheetContent;
|
|
2511
|
+
exports.BottomSheetDescription = BottomSheetDescription;
|
|
2512
|
+
exports.BottomSheetFooter = BottomSheetFooter;
|
|
2513
|
+
exports.BottomSheetHeader = BottomSheetHeader;
|
|
2514
|
+
exports.BottomSheetTitle = BottomSheetTitle;
|
|
2048
2515
|
exports.Breadcrumb = Breadcrumb;
|
|
2049
2516
|
exports.BreadcrumbItem = BreadcrumbItem;
|
|
2050
2517
|
exports.BreadcrumbSeparator = BreadcrumbSeparator;
|
|
@@ -2057,6 +2524,7 @@ exports.CardHeader = CardHeader;
|
|
|
2057
2524
|
exports.CardTitle = CardTitle;
|
|
2058
2525
|
exports.Checkbox = Checkbox;
|
|
2059
2526
|
exports.CheckboxField = CheckboxField;
|
|
2527
|
+
exports.CodeBlock = CodeBlock;
|
|
2060
2528
|
exports.CommandPalette = CommandPalette;
|
|
2061
2529
|
exports.ConfirmDialog = ConfirmDialog;
|
|
2062
2530
|
exports.DashboardShell = DashboardShell;
|
|
@@ -2070,10 +2538,12 @@ exports.DropdownMenuSeparator = DropdownMenuSeparator;
|
|
|
2070
2538
|
exports.DropdownMenuTrigger = DropdownMenuTrigger;
|
|
2071
2539
|
exports.EmptyState = EmptyState;
|
|
2072
2540
|
exports.ErrorState = ErrorState;
|
|
2541
|
+
exports.Fab = Fab;
|
|
2073
2542
|
exports.Field = Field;
|
|
2074
2543
|
exports.FormField = FormField;
|
|
2075
2544
|
exports.Hint = Hint;
|
|
2076
2545
|
exports.Input = Input;
|
|
2546
|
+
exports.Kbd = Kbd;
|
|
2077
2547
|
exports.Label = Label;
|
|
2078
2548
|
exports.MetricCard = MetricCard;
|
|
2079
2549
|
exports.Modal = Modal;
|
|
@@ -2082,6 +2552,9 @@ exports.ModalDescription = ModalDescription;
|
|
|
2082
2552
|
exports.ModalTitle = ModalTitle;
|
|
2083
2553
|
exports.PageHeader = PageHeader;
|
|
2084
2554
|
exports.Pagination = Pagination;
|
|
2555
|
+
exports.Popover = Popover;
|
|
2556
|
+
exports.PopoverContent = PopoverContent;
|
|
2557
|
+
exports.PopoverTrigger = PopoverTrigger;
|
|
2085
2558
|
exports.Progress = Progress;
|
|
2086
2559
|
exports.Radio = Radio;
|
|
2087
2560
|
exports.Segmented = Segmented;
|