@sqlrooms/ui 0.27.0-rc.2 → 0.27.0-rc.3
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/components/editable-text.d.ts +4 -0
- package/dist/components/editable-text.d.ts.map +1 -1
- package/dist/components/editable-text.js +26 -4
- package/dist/components/editable-text.js.map +1 -1
- package/dist/components/scrollable-row.d.ts +14 -0
- package/dist/components/scrollable-row.d.ts.map +1 -0
- package/dist/components/scrollable-row.js +45 -0
- package/dist/components/scrollable-row.js.map +1 -0
- package/dist/components/tab-strip.d.ts +13 -3
- package/dist/components/tab-strip.d.ts.map +1 -1
- package/dist/components/tab-strip.js +116 -35
- package/dist/components/tab-strip.js.map +1 -1
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +12 -1
- package/dist/components/textarea.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/theme/theme-provider.d.ts.map +1 -1
- package/dist/theme/theme-provider.js +25 -4
- package/dist/theme/theme-provider.js.map +1 -1
- package/package.json +2 -2
|
@@ -35,6 +35,10 @@ export declare const EditableText: FC<{
|
|
|
35
35
|
value: string;
|
|
36
36
|
placeholder?: string;
|
|
37
37
|
onChange: (text: string) => void;
|
|
38
|
+
autoFocus?: boolean;
|
|
39
|
+
selectOnFocus?: boolean;
|
|
40
|
+
/** When false, the input is removed from tab order while not editing. */
|
|
41
|
+
allowTabFocusWhenNotEditing?: boolean;
|
|
38
42
|
/**
|
|
39
43
|
* The editing state when it is initially rendered. Use when you do not need to control its editing state
|
|
40
44
|
* in the parent component.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-text.d.ts","sourceRoot":"","sources":["../../src/components/editable-text.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,EAAE,EAA2C,MAAM,OAAO,CAAC;AAKhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"editable-text.d.ts","sourceRoot":"","sources":["../../src/components/editable-text.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,EAAE,EAA2C,MAAM,OAAO,CAAC;AAKhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC;;;QAGI;IACJ,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;QAEI;IACJ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAChD,CA6JA,CAAC"}
|
|
@@ -33,7 +33,7 @@ import { cn } from '../lib/utils';
|
|
|
33
33
|
* />
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export const EditableText = ({ className, isReadOnly = false, defaultEditing = false, isEditing, placeholder, value, onChange, onEditingChange, }) => {
|
|
36
|
+
export const EditableText = ({ className, isReadOnly = false, defaultEditing = false, isEditing, placeholder, value, onChange, onEditingChange, autoFocus, selectOnFocus = false, allowTabFocusWhenNotEditing = true, }) => {
|
|
37
37
|
const [isInternalEditing, setInternalIsEditing] = useState(defaultEditing);
|
|
38
38
|
const inputRef = useRef(null);
|
|
39
39
|
const [internalValue, setInternalValue] = useState(value);
|
|
@@ -55,10 +55,12 @@ export const EditableText = ({ className, isReadOnly = false, defaultEditing = f
|
|
|
55
55
|
setInternalIsEditing(Boolean(isEditing));
|
|
56
56
|
if (isEditing) {
|
|
57
57
|
// When enabling editing from a dropdown menu, there will be a blur event when the dropdown closes,
|
|
58
|
-
// so we need to wait a bit before making sure the input is focused and selected
|
|
58
|
+
// so we need to wait a bit before making sure the input is focused and selected.
|
|
59
59
|
const timeoutId = setTimeout(() => {
|
|
60
|
-
inputRef.current?.select();
|
|
61
60
|
inputRef.current?.focus();
|
|
61
|
+
if (selectOnFocus) {
|
|
62
|
+
inputRef.current?.select();
|
|
63
|
+
}
|
|
62
64
|
}, 200);
|
|
63
65
|
return () => clearTimeout(timeoutId);
|
|
64
66
|
}
|
|
@@ -88,6 +90,26 @@ export const EditableText = ({ className, isReadOnly = false, defaultEditing = f
|
|
|
88
90
|
handleSetEditing(true);
|
|
89
91
|
}
|
|
90
92
|
}, [isInternalEditing, handleSetEditing]);
|
|
93
|
+
const handleFocus = useCallback(() => {
|
|
94
|
+
if (selectOnFocus && isInternalEditing) {
|
|
95
|
+
inputRef.current?.select();
|
|
96
|
+
}
|
|
97
|
+
}, [isInternalEditing, selectOnFocus]);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!isInternalEditing)
|
|
100
|
+
return;
|
|
101
|
+
let rafId = requestAnimationFrame(() => {
|
|
102
|
+
rafId = requestAnimationFrame(() => {
|
|
103
|
+
inputRef.current?.focus();
|
|
104
|
+
if (selectOnFocus) {
|
|
105
|
+
inputRef.current?.select();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
return () => {
|
|
110
|
+
cancelAnimationFrame(rafId);
|
|
111
|
+
};
|
|
112
|
+
}, [isInternalEditing, selectOnFocus]);
|
|
91
113
|
// Add keydown event listener to handle enter key
|
|
92
114
|
useEffect(() => {
|
|
93
115
|
const handleKeyDown = (e) => {
|
|
@@ -118,6 +140,6 @@ export const EditableText = ({ className, isReadOnly = false, defaultEditing = f
|
|
|
118
140
|
truncate: !isInternalEditing,
|
|
119
141
|
}, className), style: {
|
|
120
142
|
caretColor: isInternalEditing ? undefined : 'transparent',
|
|
121
|
-
}, value: internalValue, onChange: handleSetValue, onBlur: handleBlur, disabled: isReadOnly, onClick: handleClick, placeholder: !isInternalEditing ? (placeholder ?? 'Click to edit') : undefined }));
|
|
143
|
+
}, value: internalValue, tabIndex: isInternalEditing || allowTabFocusWhenNotEditing ? 0 : -1, autoFocus: autoFocus, onChange: handleSetValue, onFocus: handleFocus, onBlur: handleBlur, disabled: isReadOnly, onClick: handleClick, placeholder: !isInternalEditing ? (placeholder ?? 'Click to edit') : undefined }));
|
|
122
144
|
};
|
|
123
145
|
//# sourceMappingURL=editable-text.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-text.js","sourceRoot":"","sources":["../../src/components/editable-text.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {ChangeEvent, FC, useCallback, useEffect, useRef, useState} from 'react';\n\nimport {Input} from './input';\nimport {cn} from '../lib/utils';\n\n/**\n * Component that allows the user to edit a string.\n *\n * The editing mode can be controlled (the mode is managed by the parent component)\n * or uncontrolled (managed by the component itself).\n *\n * Controlled mode example:\n * ```\n * const [text, setText] = useState('');\n * const [isEditing, setEditing] = useState(false);\n * ...\n * <EditableText\n * value={text}\n * onChange={setText}\n * isEditing={isEditing}\n * onEditingChange={setEditing}\n * />\n * ```\n *\n * Uncontrolled mode example:\n * ```\n * const [text, setText] = useState('');\n * ...\n * <EditableText\n * value={text}\n * onChange={setText}\n * defaultEditing={false}\n * />\n * ```\n */\n\nexport const EditableText: FC<{\n className?: string;\n isReadOnly?: boolean;\n value: string;\n placeholder?: string;\n onChange: (text: string) => void;\n\n /**\n * The editing state when it is initially rendered. Use when you do not need to control its editing state\n * in the parent component.\n **/\n defaultEditing?: boolean;\n\n /**\n * The controlled editing state of the component. Must be used in conjunction with onEditingChange.\n **/\n isEditing?: boolean;\n onEditingChange?: (isEditing: boolean) => void;\n}> = ({\n className,\n isReadOnly = false,\n defaultEditing = false,\n isEditing,\n placeholder,\n value,\n onChange,\n onEditingChange,\n}) => {\n const [isInternalEditing, setInternalIsEditing] = useState(defaultEditing);\n const inputRef = useRef<HTMLInputElement>(null);\n const [internalValue, setInternalValue] = useState(value);\n const internalValueRef = useRef(internalValue);\n\n useEffect(() => {\n internalValueRef.current = internalValue;\n }, [internalValue]);\n\n // Keep internalValue in sync with value prop\n /* eslint-disable react-hooks/set-state-in-effect */\n useEffect(() => {\n if (value !== internalValueRef.current) {\n setInternalValue(value);\n }\n }, [value]);\n\n // Keep internal editing state in sync with controlled isEditing prop\n // and focus the input when editing is enabled\n useEffect(() => {\n if (isEditing !== undefined && isEditing !== isInternalEditing) {\n setInternalIsEditing(Boolean(isEditing));\n if (isEditing) {\n // When enabling editing from a dropdown menu, there will be a blur event when the dropdown closes,\n // so we need to wait a bit before making sure the input is focused and selected\n const timeoutId = setTimeout(() => {\n inputRef.current?.select();\n inputRef.current?.focus();\n }, 200);\n return () => clearTimeout(timeoutId);\n }\n }\n return undefined;\n }, [isEditing, isInternalEditing]);\n /* eslint-enable react-hooks/set-state-in-effect */\n\n const handleSetValue = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n if (isReadOnly || !isInternalEditing) {\n return;\n }\n return setInternalValue(e.target.value);\n },\n [isInternalEditing, isReadOnly],\n );\n\n const handleSetEditing = useCallback(\n (nextIsEditing: boolean) => {\n if (isReadOnly) {\n return;\n }\n setInternalIsEditing(nextIsEditing);\n onEditingChange?.(nextIsEditing);\n },\n [isReadOnly, onEditingChange],\n );\n\n const handleBlur = useCallback(() => {\n handleSetEditing(false);\n onChange(internalValueRef.current?.trim());\n }, [handleSetEditing, onChange]);\n\n const handleClick = useCallback(() => {\n if (!isInternalEditing) {\n handleSetEditing(true);\n }\n }, [isInternalEditing, handleSetEditing]);\n\n // Add keydown event listener to handle enter key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'Escape':\n // Reset the internal value to the original value\n setInternalValue(value);\n internalValueRef.current = value;\n handleSetEditing(false);\n inputRef.current?.blur();\n break;\n case 'Enter':\n handleSetEditing(false);\n onChange(internalValueRef.current.trim());\n inputRef.current?.blur();\n break;\n }\n };\n if (isInternalEditing) {\n document.addEventListener('keydown', handleKeyDown);\n }\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isInternalEditing, onChange, handleSetEditing, value]);\n\n return (\n <Input\n ref={inputRef}\n className={cn(\n 'disabled:opacity-1 w-full rounded-sm border-transparent px-1 py-0 focus:border-blue-500 focus:outline-none focus:ring-blue-500 disabled:cursor-text',\n {\n 'select-none bg-transparent': !isInternalEditing,\n truncate: !isInternalEditing,\n },\n className,\n )}\n style={{\n caretColor: isInternalEditing ? undefined : 'transparent',\n }}\n value={internalValue}\n onChange={handleSetValue}\n onBlur={handleBlur}\n disabled={isReadOnly}\n onClick={handleClick}\n placeholder={\n !isInternalEditing ? (placeholder ?? 'Click to edit') : undefined\n }\n />\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"editable-text.js","sourceRoot":"","sources":["../../src/components/editable-text.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {ChangeEvent, FC, useCallback, useEffect, useRef, useState} from 'react';\n\nimport {Input} from './input';\nimport {cn} from '../lib/utils';\n\n/**\n * Component that allows the user to edit a string.\n *\n * The editing mode can be controlled (the mode is managed by the parent component)\n * or uncontrolled (managed by the component itself).\n *\n * Controlled mode example:\n * ```\n * const [text, setText] = useState('');\n * const [isEditing, setEditing] = useState(false);\n * ...\n * <EditableText\n * value={text}\n * onChange={setText}\n * isEditing={isEditing}\n * onEditingChange={setEditing}\n * />\n * ```\n *\n * Uncontrolled mode example:\n * ```\n * const [text, setText] = useState('');\n * ...\n * <EditableText\n * value={text}\n * onChange={setText}\n * defaultEditing={false}\n * />\n * ```\n */\n\nexport const EditableText: FC<{\n className?: string;\n isReadOnly?: boolean;\n value: string;\n placeholder?: string;\n onChange: (text: string) => void;\n autoFocus?: boolean;\n selectOnFocus?: boolean;\n /** When false, the input is removed from tab order while not editing. */\n allowTabFocusWhenNotEditing?: boolean;\n\n /**\n * The editing state when it is initially rendered. Use when you do not need to control its editing state\n * in the parent component.\n **/\n defaultEditing?: boolean;\n\n /**\n * The controlled editing state of the component. Must be used in conjunction with onEditingChange.\n **/\n isEditing?: boolean;\n onEditingChange?: (isEditing: boolean) => void;\n}> = ({\n className,\n isReadOnly = false,\n defaultEditing = false,\n isEditing,\n placeholder,\n value,\n onChange,\n onEditingChange,\n autoFocus,\n selectOnFocus = false,\n allowTabFocusWhenNotEditing = true,\n}) => {\n const [isInternalEditing, setInternalIsEditing] = useState(defaultEditing);\n const inputRef = useRef<HTMLInputElement>(null);\n const [internalValue, setInternalValue] = useState(value);\n const internalValueRef = useRef(internalValue);\n\n useEffect(() => {\n internalValueRef.current = internalValue;\n }, [internalValue]);\n\n // Keep internalValue in sync with value prop\n /* eslint-disable react-hooks/set-state-in-effect */\n useEffect(() => {\n if (value !== internalValueRef.current) {\n setInternalValue(value);\n }\n }, [value]);\n\n // Keep internal editing state in sync with controlled isEditing prop\n // and focus the input when editing is enabled\n useEffect(() => {\n if (isEditing !== undefined && isEditing !== isInternalEditing) {\n setInternalIsEditing(Boolean(isEditing));\n if (isEditing) {\n // When enabling editing from a dropdown menu, there will be a blur event when the dropdown closes,\n // so we need to wait a bit before making sure the input is focused and selected.\n const timeoutId = setTimeout(() => {\n inputRef.current?.focus();\n if (selectOnFocus) {\n inputRef.current?.select();\n }\n }, 200);\n return () => clearTimeout(timeoutId);\n }\n }\n return undefined;\n }, [isEditing, isInternalEditing]);\n /* eslint-enable react-hooks/set-state-in-effect */\n\n const handleSetValue = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n if (isReadOnly || !isInternalEditing) {\n return;\n }\n return setInternalValue(e.target.value);\n },\n [isInternalEditing, isReadOnly],\n );\n\n const handleSetEditing = useCallback(\n (nextIsEditing: boolean) => {\n if (isReadOnly) {\n return;\n }\n setInternalIsEditing(nextIsEditing);\n onEditingChange?.(nextIsEditing);\n },\n [isReadOnly, onEditingChange],\n );\n\n const handleBlur = useCallback(() => {\n handleSetEditing(false);\n onChange(internalValueRef.current?.trim());\n }, [handleSetEditing, onChange]);\n\n const handleClick = useCallback(() => {\n if (!isInternalEditing) {\n handleSetEditing(true);\n }\n }, [isInternalEditing, handleSetEditing]);\n\n const handleFocus = useCallback(() => {\n if (selectOnFocus && isInternalEditing) {\n inputRef.current?.select();\n }\n }, [isInternalEditing, selectOnFocus]);\n\n useEffect(() => {\n if (!isInternalEditing) return;\n let rafId = requestAnimationFrame(() => {\n rafId = requestAnimationFrame(() => {\n inputRef.current?.focus();\n if (selectOnFocus) {\n inputRef.current?.select();\n }\n });\n });\n return () => {\n cancelAnimationFrame(rafId);\n };\n }, [isInternalEditing, selectOnFocus]);\n\n // Add keydown event listener to handle enter key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'Escape':\n // Reset the internal value to the original value\n setInternalValue(value);\n internalValueRef.current = value;\n handleSetEditing(false);\n inputRef.current?.blur();\n break;\n case 'Enter':\n handleSetEditing(false);\n onChange(internalValueRef.current.trim());\n inputRef.current?.blur();\n break;\n }\n };\n if (isInternalEditing) {\n document.addEventListener('keydown', handleKeyDown);\n }\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isInternalEditing, onChange, handleSetEditing, value]);\n\n return (\n <Input\n ref={inputRef}\n className={cn(\n 'disabled:opacity-1 w-full rounded-sm border-transparent px-1 py-0 focus:border-blue-500 focus:outline-none focus:ring-blue-500 disabled:cursor-text',\n {\n 'select-none bg-transparent': !isInternalEditing,\n truncate: !isInternalEditing,\n },\n className,\n )}\n style={{\n caretColor: isInternalEditing ? undefined : 'transparent',\n }}\n value={internalValue}\n tabIndex={isInternalEditing || allowTabFocusWhenNotEditing ? 0 : -1}\n autoFocus={autoFocus}\n onChange={handleSetValue}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={isReadOnly}\n onClick={handleClick}\n placeholder={\n !isInternalEditing ? (placeholder ?? 'Click to edit') : undefined\n }\n />\n );\n};\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type ScrollableRowProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
className?: string;
|
|
5
|
+
scrollClassName?: string;
|
|
6
|
+
scrollRef?: React.RefObject<HTMLDivElement>;
|
|
7
|
+
scrollAmount?: number;
|
|
8
|
+
arrowVisibility?: 'hover' | 'always';
|
|
9
|
+
arrowClassName?: string;
|
|
10
|
+
arrowIconClassName?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function ScrollableRow({ children, className, scrollClassName, scrollRef, scrollAmount, arrowVisibility, arrowClassName, arrowIconClassName, }: ScrollableRowProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=scrollable-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollable-row.d.ts","sourceRoot":"","sources":["../../src/components/scrollable-row.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAGzD,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,eAAe,EACf,SAAS,EACT,YAAkB,EAClB,eAAyB,EACzB,cAAc,EACd,kBAAkB,GACnB,EAAE,kBAAkB,2CAkGpB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../lib/utils';
|
|
5
|
+
export function ScrollableRow({ children, className, scrollClassName, scrollRef, scrollAmount = 200, arrowVisibility = 'hover', arrowClassName, arrowIconClassName, }) {
|
|
6
|
+
const internalRef = useRef(null);
|
|
7
|
+
const containerRef = scrollRef ?? internalRef;
|
|
8
|
+
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
|
9
|
+
const [canScrollRight, setCanScrollRight] = useState(false);
|
|
10
|
+
const updateScrollState = () => {
|
|
11
|
+
const container = containerRef.current;
|
|
12
|
+
if (!container)
|
|
13
|
+
return;
|
|
14
|
+
const { scrollLeft, scrollWidth, clientWidth } = container;
|
|
15
|
+
setCanScrollLeft(scrollLeft > 0);
|
|
16
|
+
setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);
|
|
17
|
+
};
|
|
18
|
+
const scrollBy = (direction) => {
|
|
19
|
+
const container = containerRef.current;
|
|
20
|
+
if (!container)
|
|
21
|
+
return;
|
|
22
|
+
container.scrollBy({
|
|
23
|
+
left: direction === 'left' ? -scrollAmount : scrollAmount,
|
|
24
|
+
behavior: 'smooth',
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const container = containerRef.current;
|
|
29
|
+
if (!container)
|
|
30
|
+
return;
|
|
31
|
+
updateScrollState();
|
|
32
|
+
container.addEventListener('scroll', updateScrollState);
|
|
33
|
+
const resizeObserver = new ResizeObserver(updateScrollState);
|
|
34
|
+
resizeObserver.observe(container);
|
|
35
|
+
return () => {
|
|
36
|
+
container.removeEventListener('scroll', updateScrollState);
|
|
37
|
+
resizeObserver.disconnect();
|
|
38
|
+
};
|
|
39
|
+
}, [children, containerRef]);
|
|
40
|
+
const arrowBaseClass = cn('absolute top-0 z-10 flex h-full w-8 items-center backdrop-blur-md bg-background/50 transition-colors', arrowVisibility === 'hover'
|
|
41
|
+
? 'opacity-0 transition-opacity hover:opacity-100'
|
|
42
|
+
: 'opacity-100', arrowClassName);
|
|
43
|
+
return (_jsxs("div", { className: cn('relative', className), children: [_jsx("button", { type: "button", onClick: () => scrollBy('left'), disabled: !canScrollLeft, className: cn(arrowBaseClass, 'left-0 justify-start pl-1', 'from-background/90 via-background/60 group bg-gradient-to-r to-transparent', !canScrollLeft && 'pointer-events-none opacity-0'), "aria-label": "Scroll left", title: "Scroll left", children: _jsx(ChevronLeft, { className: cn('text-muted-foreground group-hover:text-foreground h-5 w-5 transition-colors', arrowIconClassName) }) }), _jsx("div", { ref: containerRef, className: scrollClassName, children: children }), _jsx("button", { type: "button", onClick: () => scrollBy('right'), disabled: !canScrollRight, className: cn(arrowBaseClass, 'right-0 justify-end pr-1', 'from-background/90 via-background/60 group bg-gradient-to-l to-transparent', !canScrollRight && 'pointer-events-none opacity-0'), "aria-label": "Scroll right", title: "Scroll right", children: _jsx(ChevronRight, { className: cn('text-muted-foreground group-hover:text-foreground h-5 w-5 transition-colors', arrowIconClassName) }) })] }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=scrollable-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollable-row.js","sourceRoot":"","sources":["../../src/components/scrollable-row.tsx"],"names":[],"mappings":"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","sourcesContent":["import {ChevronLeft, ChevronRight} from 'lucide-react';\nimport React, {useEffect, useRef, useState} from 'react';\nimport {cn} from '../lib/utils';\n\ntype ScrollableRowProps = {\n children: React.ReactNode;\n className?: string;\n scrollClassName?: string;\n scrollRef?: React.RefObject<HTMLDivElement>;\n scrollAmount?: number;\n arrowVisibility?: 'hover' | 'always';\n arrowClassName?: string;\n arrowIconClassName?: string;\n};\n\nexport function ScrollableRow({\n children,\n className,\n scrollClassName,\n scrollRef,\n scrollAmount = 200,\n arrowVisibility = 'hover',\n arrowClassName,\n arrowIconClassName,\n}: ScrollableRowProps) {\n const internalRef = useRef<HTMLDivElement>(null);\n const containerRef = scrollRef ?? internalRef;\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const updateScrollState = () => {\n const container = containerRef.current;\n if (!container) return;\n\n const {scrollLeft, scrollWidth, clientWidth} = container;\n setCanScrollLeft(scrollLeft > 0);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n };\n\n const scrollBy = (direction: 'left' | 'right') => {\n const container = containerRef.current;\n if (!container) return;\n\n container.scrollBy({\n left: direction === 'left' ? -scrollAmount : scrollAmount,\n behavior: 'smooth',\n });\n };\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n updateScrollState();\n\n container.addEventListener('scroll', updateScrollState);\n const resizeObserver = new ResizeObserver(updateScrollState);\n resizeObserver.observe(container);\n\n return () => {\n container.removeEventListener('scroll', updateScrollState);\n resizeObserver.disconnect();\n };\n }, [children, containerRef]);\n\n const arrowBaseClass = cn(\n 'absolute top-0 z-10 flex h-full w-8 items-center backdrop-blur-md bg-background/50 transition-colors',\n arrowVisibility === 'hover'\n ? 'opacity-0 transition-opacity hover:opacity-100'\n : 'opacity-100',\n arrowClassName,\n );\n\n return (\n <div className={cn('relative', className)}>\n <button\n type=\"button\"\n onClick={() => scrollBy('left')}\n disabled={!canScrollLeft}\n className={cn(\n arrowBaseClass,\n 'left-0 justify-start pl-1',\n 'from-background/90 via-background/60 group bg-gradient-to-r to-transparent',\n !canScrollLeft && 'pointer-events-none opacity-0',\n )}\n aria-label=\"Scroll left\"\n title=\"Scroll left\"\n >\n <ChevronLeft\n className={cn(\n 'text-muted-foreground group-hover:text-foreground h-5 w-5 transition-colors',\n arrowIconClassName,\n )}\n />\n </button>\n\n <div ref={containerRef} className={scrollClassName}>\n {children}\n </div>\n\n <button\n type=\"button\"\n onClick={() => scrollBy('right')}\n disabled={!canScrollRight}\n className={cn(\n arrowBaseClass,\n 'right-0 justify-end pr-1',\n 'from-background/90 via-background/60 group bg-gradient-to-l to-transparent',\n !canScrollRight && 'pointer-events-none opacity-0',\n )}\n aria-label=\"Scroll right\"\n title=\"Scroll right\"\n >\n <ChevronRight\n className={cn(\n 'text-muted-foreground group-hover:text-foreground h-5 w-5 transition-colors',\n arrowIconClassName,\n )}\n />\n </button>\n </div>\n );\n}\n"]}
|
|
@@ -50,12 +50,22 @@ interface TabStripSearchDropdownProps {
|
|
|
50
50
|
tooltip?: React.ReactNode;
|
|
51
51
|
/** Optional custom icon for the trigger button. */
|
|
52
52
|
triggerIcon?: React.ReactNode;
|
|
53
|
+
/** Message shown when there are no tabs at all. */
|
|
54
|
+
emptyMessage?: React.ReactNode;
|
|
55
|
+
/** Message shown when searching and there are no matching tabs. */
|
|
56
|
+
searchEmptyMessage?: React.ReactNode;
|
|
57
|
+
/** Label for the closed tabs group. */
|
|
58
|
+
closedTabsLabel?: React.ReactNode;
|
|
59
|
+
/** Sorting mode for search dropdown items. */
|
|
60
|
+
sortSearchItems?: 'none' | 'recent';
|
|
61
|
+
/** Optional accessor for tab recency timestamps. */
|
|
62
|
+
getTabLastOpenedAt?: (tab: TabDescriptor) => number | undefined;
|
|
53
63
|
}
|
|
54
64
|
/**
|
|
55
65
|
* Renders the dropdown with search for browsing tabs.
|
|
56
|
-
*
|
|
66
|
+
* Shows open tabs first and closed tabs second (dimmed). When searching, shows all matching tabs.
|
|
57
67
|
*/
|
|
58
|
-
declare function TabStripSearchDropdown({ className, triggerClassName, autoFocus, tooltip, triggerIcon, }: TabStripSearchDropdownProps): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
declare function TabStripSearchDropdown({ className, triggerClassName, autoFocus, tooltip, triggerIcon, emptyMessage, searchEmptyMessage, closedTabsLabel, sortSearchItems, getTabLastOpenedAt, }: TabStripSearchDropdownProps): import("react/jsx-runtime").JSX.Element;
|
|
59
69
|
interface TabStripNewButtonProps {
|
|
60
70
|
className?: string;
|
|
61
71
|
/** Optional tooltip content for the button. */
|
|
@@ -72,7 +82,7 @@ export interface TabStripProps {
|
|
|
72
82
|
/** All available tabs. */
|
|
73
83
|
tabs: TabDescriptor[];
|
|
74
84
|
/** IDs of tabs that are currently open. */
|
|
75
|
-
openTabs
|
|
85
|
+
openTabs?: string[];
|
|
76
86
|
/** ID of the currently selected tab. */
|
|
77
87
|
selectedTabId?: string | null;
|
|
78
88
|
/** If true, hides the close button when only one tab remains open. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-strip.d.ts","sourceRoot":"","sources":["../../src/components/tab-strip.tsx"],"names":[],"mappings":"AAyBA,OAAO,
|
|
1
|
+
{"version":3,"file":"tab-strip.d.ts","sourceRoot":"","sources":["../../src/components/tab-strip.tsx"],"names":[],"mappings":"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"}
|
|
@@ -3,13 +3,14 @@ import { DndContext, PointerSensor, closestCenter, useSensor, useSensors, } from
|
|
|
3
3
|
import { restrictToHorizontalAxis, restrictToParentElement, } from '@dnd-kit/modifiers';
|
|
4
4
|
import { SortableContext, arrayMove, horizontalListSortingStrategy, useSortable, } from '@dnd-kit/sortable';
|
|
5
5
|
import { EllipsisVerticalIcon, ListCollapseIcon, PlusIcon, SearchIcon, XIcon, } from 'lucide-react';
|
|
6
|
-
import { createContext, useContext, useEffect, useMemo, useRef, useState, } from 'react';
|
|
6
|
+
import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
7
7
|
const DRAG_MODIFIERS = [restrictToHorizontalAxis, restrictToParentElement];
|
|
8
8
|
import { cn } from '../lib/utils';
|
|
9
9
|
import { Button } from './button';
|
|
10
10
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from './dropdown-menu';
|
|
11
11
|
import { EditableText } from './editable-text';
|
|
12
12
|
import { Input } from './input';
|
|
13
|
+
import { ScrollableRow } from './scrollable-row';
|
|
13
14
|
import { Tabs, TabsList, TabsTrigger } from './tabs';
|
|
14
15
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from './tooltip';
|
|
15
16
|
const TabStripContext = createContext(null);
|
|
@@ -34,23 +35,23 @@ function SortableTab({ tab, tabClassName, editingTabId, hideCloseButton, onClose
|
|
|
34
35
|
opacity: isDragging ? 0.5 : 1,
|
|
35
36
|
};
|
|
36
37
|
const menuContent = renderTabMenu?.(tab);
|
|
37
|
-
return (_jsx("div", { ref: setNodeRef, className: "h-full flex-shrink-0", style: style, ...attributes, ...listeners, children:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
38
|
+
return (_jsx("div", { ref: setNodeRef, className: "h-full flex-shrink-0", style: style, "data-tab-id": tab.id, ...attributes, ...listeners, tabIndex: -1, children: _jsx("div", { "data-state": editingTabId === tab.id ? 'editing' : undefined, className: cn('data-[state=inactive]:hover:bg-primary/5', 'group flex h-full min-w-[100px] max-w-[200px] flex-shrink-0 cursor-grab', 'items-center gap-0.5 overflow-visible rounded-b-none', 'py-0 pl-0 pr-0 font-normal data-[state=active]:shadow-none', tabClassName, editingTabId === tab.id && 'focus-visible:ring-0'), children: _jsxs("div", { className: "relative flex h-full min-w-0 flex-1 items-center", children: [_jsx(TabsTrigger, { value: tab.id, tabIndex: editingTabId === tab.id ? -1 : undefined, "data-editing": editingTabId === tab.id ? '' : undefined, className: cn('flex h-full min-w-0 flex-1 items-center justify-start gap-1', 'hover:bg-primary/10 overflow-hidden px-6 py-1 font-normal', 'min-h-7', 'data-[state=active]:bg-primary/10 data-[state=active]:text-foreground data-[state=active]:shadow-none', 'focus-visible:ring-primary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-offset-0', editingTabId === tab.id && 'focus-visible:ring-0'), onDoubleClick: () => onStartEditing(tab.id), children: editingTabId !== tab.id ? (_jsx("div", { className: "truncate text-sm", children: renderTabLabel ? renderTabLabel(tab) : tab.name })) : (_jsx(EditableText, { value: tab.name, onChange: (newName) => onInlineRename(tab.id, newName), className: "h-6 min-w-0 flex-1 truncate text-sm shadow-none", isEditing: true, autoFocus: true, selectOnFocus: true, allowTabFocusWhenNotEditing: false, onEditingChange: (isEditing) => {
|
|
39
|
+
if (!isEditing) {
|
|
40
|
+
onStopEditing();
|
|
41
|
+
}
|
|
42
|
+
} })) }), menuContent && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "Tab options", className: "hover:bg-primary/10 focus-visible:bg-primary/10 focus-visible:ring-primary absolute left-1 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded p-1 opacity-0 outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-0 group-hover:opacity-100 data-[state=open]:opacity-100", onMouseDown: (event) => {
|
|
43
|
+
event.stopPropagation();
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
}, onClick: (event) => {
|
|
46
|
+
event.stopPropagation();
|
|
47
|
+
}, children: _jsx(EllipsisVerticalIcon, { className: "h-3 w-3" }) }) }), _jsx(DropdownMenuContent, { align: "start", children: menuContent })] })), !hideCloseButton && (_jsx("button", { type: "button", "aria-label": "Close tab", className: "hover:bg-primary/10 focus-visible:bg-primary/10 focus-visible:ring-primary absolute right-1 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded p-1 opacity-0 outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-0 group-hover:opacity-100", onMouseDown: (event) => {
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
}, onClick: (event) => {
|
|
51
|
+
event.stopPropagation();
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
onClose(tab.id);
|
|
54
|
+
}, children: _jsx(XIcon, { className: "h-4 w-4" }) }))] }) }) }));
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
56
57
|
* A menu item for the tab's dropdown menu.
|
|
@@ -98,14 +99,14 @@ function TabStripTabs({ className, tabClassName }) {
|
|
|
98
99
|
}
|
|
99
100
|
};
|
|
100
101
|
const tabIds = useMemo(() => openTabItems.map((t) => t.id), [openTabItems]);
|
|
101
|
-
return (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, modifiers: DRAG_MODIFIERS, autoScroll: true, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: tabIds, strategy: horizontalListSortingStrategy, children: _jsx(
|
|
102
|
+
return (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, modifiers: DRAG_MODIFIERS, autoScroll: true, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: tabIds, strategy: horizontalListSortingStrategy, children: _jsx(ScrollableRow, { className: "h-full min-w-0 flex-1", scrollRef: scrollContainerRef, scrollClassName: cn('flex h-full min-w-0 items-center gap-1 overflow-x-auto overflow-y-visible', 'py-1 pl-1 pr-1 scroll-pl-7 scroll-pr-7 [&::-webkit-scrollbar]:hidden', className), arrowVisibility: "always", arrowClassName: "w-7", arrowIconClassName: "h-4 w-4 opacity-60", children: openTabItems.map((tab) => (_jsx(SortableTab, { tab: tab, tabClassName: tabClassName, editingTabId: editingTabId, hideCloseButton: preventCloseLastTab && openTabItems.length === 1, onClose: handleClose, onStartEditing: handleStartEditing, onStopEditing: handleStopEditing, onInlineRename: handleInlineRename, renderTabMenu: renderTabMenu, renderTabLabel: renderTabLabel }, tab.id))) }) }) }));
|
|
102
103
|
}
|
|
103
104
|
/**
|
|
104
105
|
* Renders the dropdown with search for browsing tabs.
|
|
105
|
-
*
|
|
106
|
+
* Shows open tabs first and closed tabs second (dimmed). When searching, shows all matching tabs.
|
|
106
107
|
*/
|
|
107
|
-
function TabStripSearchDropdown({ className, triggerClassName, autoFocus = true, tooltip, triggerIcon, }) {
|
|
108
|
-
const { search, setSearch, closedTabs, filteredTabs, closedTabIds, openTabs, onOpenTabsChange, onSelect, renderSearchItemActions, } = useTabStripContext();
|
|
108
|
+
function TabStripSearchDropdown({ className, triggerClassName, autoFocus = true, tooltip, triggerIcon, emptyMessage = 'No tabs', searchEmptyMessage = 'No matching tabs', closedTabsLabel = 'Recently closed', sortSearchItems = 'recent', getTabLastOpenedAt, }) {
|
|
109
|
+
const { openTabItems, search, setSearch, closedTabs, filteredTabs, closedTabIds, openTabs, preventCloseLastTab, onOpenTabsChange, onSelect, renderSearchItemActions, getLastOpenedAt, handleClose, } = useTabStripContext();
|
|
109
110
|
const [isOpen, setIsOpen] = useState(false);
|
|
110
111
|
const isSearching = search.trim().length > 0;
|
|
111
112
|
const handleOpenChange = (open) => {
|
|
@@ -117,7 +118,7 @@ function TabStripSearchDropdown({ className, triggerClassName, autoFocus = true,
|
|
|
117
118
|
const handleTabClick = (tabId) => {
|
|
118
119
|
if (closedTabIds.has(tabId)) {
|
|
119
120
|
// Opening a closed tab: add to openTabs and select it
|
|
120
|
-
onOpenTabsChange?.([...openTabs, tabId]);
|
|
121
|
+
onOpenTabsChange?.([...(openTabs ?? []), tabId]);
|
|
121
122
|
onSelect?.(tabId);
|
|
122
123
|
}
|
|
123
124
|
else {
|
|
@@ -126,8 +127,38 @@ function TabStripSearchDropdown({ className, triggerClassName, autoFocus = true,
|
|
|
126
127
|
}
|
|
127
128
|
setIsOpen(false);
|
|
128
129
|
};
|
|
130
|
+
const sortByRecency = (tabsToSort) => {
|
|
131
|
+
if (sortSearchItems !== 'recent') {
|
|
132
|
+
return tabsToSort;
|
|
133
|
+
}
|
|
134
|
+
const withIndex = tabsToSort.map((tab, index) => ({
|
|
135
|
+
tab,
|
|
136
|
+
index,
|
|
137
|
+
ts: getTabLastOpenedAt?.(tab) ?? getLastOpenedAt(tab.id),
|
|
138
|
+
}));
|
|
139
|
+
return withIndex
|
|
140
|
+
.slice()
|
|
141
|
+
.sort((a, b) => {
|
|
142
|
+
const aTs = a.ts ?? -1;
|
|
143
|
+
const bTs = b.ts ?? -1;
|
|
144
|
+
if (aTs === bTs) {
|
|
145
|
+
return a.index - b.index;
|
|
146
|
+
}
|
|
147
|
+
return bTs - aTs;
|
|
148
|
+
})
|
|
149
|
+
.map((item) => item.tab);
|
|
150
|
+
};
|
|
151
|
+
const openTabsList = sortByRecency(openTabItems);
|
|
152
|
+
const closedTabsList = sortByRecency(closedTabs);
|
|
153
|
+
const hasAnyTabs = openTabsList.length + closedTabsList.length > 0;
|
|
154
|
+
const filteredOpenTabs = sortByRecency(filteredTabs.filter((tab) => !closedTabIds.has(tab.id)));
|
|
155
|
+
const filteredClosedTabs = sortByRecency(filteredTabs.filter((tab) => closedTabIds.has(tab.id)));
|
|
156
|
+
const renderOpenTabActions = (tab) => {
|
|
157
|
+
const disableClose = preventCloseLastTab && (openTabsList.length ?? 0) <= 1;
|
|
158
|
+
return (_jsxs(_Fragment, { children: [renderSearchItemActions?.(tab), _jsx(TabStripSearchItemAction, { icon: _jsx(XIcon, { className: "h-3 w-3" }), "aria-label": `Close ${tab.name}`, onClick: disableClose ? undefined : () => handleClose(tab.id), className: cn(disableClose && 'pointer-events-none opacity-40') })] }));
|
|
159
|
+
};
|
|
129
160
|
const triggerButton = (_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", "aria-label": "Browse tabs", className: cn('hover:bg-primary/10 h-full flex-shrink-0', triggerClassName), children: triggerIcon ?? _jsx(ListCollapseIcon, { className: "h-4 w-4" }) }) }));
|
|
130
|
-
return (_jsxs(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [tooltip ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: triggerButton }), _jsx(TooltipContent, { children: tooltip })] }) })) : (triggerButton), _jsxs(DropdownMenuContent, { align: "start", onCloseAutoFocus: (event) => event.preventDefault(), className: cn('flex max-h-[400px] max-w-[240px] flex-col', className), children: [_jsxs("div", { className: "flex flex-shrink-0 items-center gap-1 px-2", children: [_jsx(SearchIcon, { className: "text-muted-foreground", size: 14 }), _jsx(Input, { value: search, onChange: (event) => setSearch(event.target.value), onKeyDown: (event) => {
|
|
161
|
+
return (_jsxs(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [tooltip ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: triggerButton }), _jsx(TooltipContent, { children: tooltip })] }) })) : (triggerButton), _jsxs(DropdownMenuContent, { align: "start", onCloseAutoFocus: (event) => event.preventDefault(), className: cn('flex max-h-[400px] max-w-[240px] flex-col overflow-x-hidden', className), children: [_jsxs("div", { className: "flex flex-shrink-0 items-center gap-1 px-2", children: [_jsx(SearchIcon, { className: "text-muted-foreground", size: 14 }), _jsx(Input, { value: search, onChange: (event) => setSearch(event.target.value), onKeyDown: (event) => {
|
|
131
162
|
if (event.key === 'ArrowDown' || event.key === 'Tab') {
|
|
132
163
|
event.preventDefault();
|
|
133
164
|
const firstItem = event.currentTarget
|
|
@@ -138,15 +169,15 @@ function TabStripSearchDropdown({ className, triggerClassName, autoFocus = true,
|
|
|
138
169
|
else {
|
|
139
170
|
event.stopPropagation();
|
|
140
171
|
}
|
|
141
|
-
}, onKeyUp: (event) => event.stopPropagation(), className: "border-none text-xs shadow-none focus-visible:ring-0", placeholder: "Search...", "aria-label": "Search", autoFocus: autoFocus })] }), _jsx(DropdownMenuSeparator, { className: "flex-shrink-0" }), _jsx("div", { className: "overflow-y-auto", children: isSearching ? (_jsx(DropdownTabItems, { tabs: filteredTabs, emptyMessage:
|
|
172
|
+
}, onKeyUp: (event) => event.stopPropagation(), className: "border-none text-xs shadow-none focus-visible:ring-0", placeholder: "Search...", "aria-label": "Search", autoFocus: autoFocus })] }), _jsx(DropdownMenuSeparator, { className: "flex-shrink-0" }), _jsx("div", { className: "overflow-y-auto overflow-x-hidden", children: isSearching ? (filteredTabs.length === 0 ? (_jsx(DropdownTabItems, { tabs: filteredTabs, emptyMessage: searchEmptyMessage, onTabClick: handleTabClick, renderActions: renderSearchItemActions })) : (_jsxs(_Fragment, { children: [_jsx(DropdownTabItems, { tabs: filteredOpenTabs, onTabClick: handleTabClick, renderActions: renderOpenTabActions }), filteredClosedTabs.length > 0 && (_jsxs(_Fragment, { children: [filteredOpenTabs.length > 0 && _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { className: "text-muted-foreground py-1 text-xs font-medium", children: closedTabsLabel }), _jsx(DropdownTabItems, { tabs: filteredClosedTabs, onTabClick: handleTabClick, renderActions: renderSearchItemActions, getItemClassName: () => 'text-muted-foreground' })] }))] }))) : (_jsx(_Fragment, { children: hasAnyTabs ? (_jsxs(_Fragment, { children: [_jsx(DropdownTabItems, { tabs: openTabsList, onTabClick: handleTabClick, renderActions: renderOpenTabActions }), closedTabsList.length > 0 && (_jsxs(_Fragment, { children: [openTabsList.length > 0 && _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { className: "text-muted-foreground py-1 text-xs font-medium", children: closedTabsLabel }), _jsx(DropdownTabItems, { tabs: closedTabsList, onTabClick: handleTabClick, renderActions: renderSearchItemActions, getItemClassName: () => 'text-muted-foreground' })] }))] })) : (_jsx(DropdownTabItems, { tabs: [], emptyMessage: emptyMessage, onTabClick: handleTabClick, renderActions: renderSearchItemActions })) })) })] })] }));
|
|
142
173
|
}
|
|
143
|
-
function DropdownTabItems({ tabs, emptyMessage, onTabClick, renderActions, }) {
|
|
174
|
+
function DropdownTabItems({ tabs, emptyMessage, onTabClick, renderActions, getItemClassName, }) {
|
|
144
175
|
if (tabs.length === 0) {
|
|
145
176
|
if (!emptyMessage)
|
|
146
177
|
return null;
|
|
147
178
|
return (_jsx(DropdownMenuLabel, { className: "items-center justify-center text-xs", children: emptyMessage }));
|
|
148
179
|
}
|
|
149
|
-
return (_jsx(_Fragment, { children: tabs.map((tab) => (_jsxs(DropdownMenuItem, { onClick: () => onTabClick?.(tab.id), className:
|
|
180
|
+
return (_jsx(_Fragment, { children: tabs.map((tab) => (_jsxs(DropdownMenuItem, { onClick: () => onTabClick?.(tab.id), className: cn('flex h-7 cursor-pointer items-center justify-between truncate', getItemClassName?.(tab)), children: [_jsx("span", { className: "xs truncate pl-1", children: tab.name }), renderActions && (_jsx("div", { className: "flex items-center gap-2", children: renderActions(tab) }))] }, tab.id))) }));
|
|
150
181
|
}
|
|
151
182
|
/**
|
|
152
183
|
* Renders a button to create a new tab.
|
|
@@ -188,11 +219,13 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
188
219
|
const [editingTabId, setEditingTabId] = useState(null);
|
|
189
220
|
const scrollContainerRef = useRef(null);
|
|
190
221
|
const prevSelectedIdRef = useRef(null);
|
|
222
|
+
const prevOpenTabIdsRef = useRef(new Set());
|
|
223
|
+
const lastOpenedAtRef = useRef(new Map());
|
|
191
224
|
const openTabsSet = useMemo(() => new Set(openTabs), [openTabs]);
|
|
192
225
|
// Build openTabItems in the order of openTabs (for drag-to-reorder)
|
|
193
226
|
const openTabItems = useMemo(() => {
|
|
194
227
|
const tabsById = new Map(tabs.map((tab) => [tab.id, tab]));
|
|
195
|
-
return openTabs
|
|
228
|
+
return (openTabs ?? [])
|
|
196
229
|
.map((id) => tabsById.get(id))
|
|
197
230
|
.filter((tab) => tab !== undefined);
|
|
198
231
|
}, [tabs, openTabs]);
|
|
@@ -202,8 +235,23 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
202
235
|
const filteredTabs = useMemo(() => trimmedSearch
|
|
203
236
|
? tabs.filter((tab) => tab.name.toLowerCase().includes(trimmedSearch))
|
|
204
237
|
: [], [tabs, trimmedSearch]);
|
|
205
|
-
// Auto-scroll to selected tab
|
|
206
238
|
useEffect(() => {
|
|
239
|
+
if (!selectedTabId)
|
|
240
|
+
return;
|
|
241
|
+
lastOpenedAtRef.current.set(selectedTabId, Date.now());
|
|
242
|
+
}, [selectedTabId]);
|
|
243
|
+
useEffect(() => {
|
|
244
|
+
const ids = new Set(tabs.map((tab) => tab.id));
|
|
245
|
+
const next = new Map();
|
|
246
|
+
for (const [id, ts] of lastOpenedAtRef.current.entries()) {
|
|
247
|
+
if (ids.has(id)) {
|
|
248
|
+
next.set(id, ts);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
lastOpenedAtRef.current = next;
|
|
252
|
+
}, [tabs]);
|
|
253
|
+
// Auto-scroll to selected tab
|
|
254
|
+
useLayoutEffect(() => {
|
|
207
255
|
if (!selectedTabId)
|
|
208
256
|
return;
|
|
209
257
|
if (prevSelectedIdRef.current === selectedTabId)
|
|
@@ -215,7 +263,8 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
215
263
|
const isOpen = openTabItems.some((tab) => tab.id === selectedTabId);
|
|
216
264
|
if (!isOpen)
|
|
217
265
|
return;
|
|
218
|
-
|
|
266
|
+
// Use queueMicrotask to defer scroll until after Radix UI updates the DOM
|
|
267
|
+
queueMicrotask(() => {
|
|
219
268
|
const activeTab = container.querySelector('[data-state="active"]');
|
|
220
269
|
if (!activeTab)
|
|
221
270
|
return;
|
|
@@ -225,10 +274,41 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
225
274
|
inline: 'nearest',
|
|
226
275
|
});
|
|
227
276
|
});
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
277
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
278
|
+
}, [selectedTabId]);
|
|
279
|
+
// Auto-scroll to newly added tab
|
|
280
|
+
useLayoutEffect(() => {
|
|
281
|
+
const container = scrollContainerRef.current;
|
|
282
|
+
if (!container)
|
|
283
|
+
return;
|
|
284
|
+
// Find newly added tabs (in openTabs but not in prevOpenTabIdsRef)
|
|
285
|
+
const newTabIds = (openTabs ?? []).filter((id) => !prevOpenTabIdsRef.current.has(id));
|
|
286
|
+
// Update ref for next comparison
|
|
287
|
+
prevOpenTabIdsRef.current = new Set(openTabs);
|
|
288
|
+
if (newTabIds.length > 0) {
|
|
289
|
+
const now = Date.now();
|
|
290
|
+
for (const id of newTabIds) {
|
|
291
|
+
lastOpenedAtRef.current.set(id, now);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Skip scroll on initial render (when ref was empty, all tabs appear "new")
|
|
295
|
+
if (newTabIds.length === (openTabs?.length ?? 0))
|
|
296
|
+
return;
|
|
297
|
+
// If there are new tabs, scroll to the last one added
|
|
298
|
+
if (newTabIds.length === 0)
|
|
299
|
+
return;
|
|
300
|
+
const newTabId = newTabIds[newTabIds.length - 1];
|
|
301
|
+
queueMicrotask(() => {
|
|
302
|
+
const newTabElement = container.querySelector(`[data-tab-id="${newTabId}"]`);
|
|
303
|
+
if (!newTabElement)
|
|
304
|
+
return;
|
|
305
|
+
newTabElement.scrollIntoView({
|
|
306
|
+
behavior: 'smooth',
|
|
307
|
+
block: 'nearest',
|
|
308
|
+
inline: 'nearest',
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}, [openTabs]);
|
|
232
312
|
const handleInlineRename = (tabId, newName) => {
|
|
233
313
|
if (!onRename)
|
|
234
314
|
return;
|
|
@@ -273,6 +353,7 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
273
353
|
selectedTabId,
|
|
274
354
|
openTabs,
|
|
275
355
|
preventCloseLastTab,
|
|
356
|
+
getLastOpenedAt: (tabId) => lastOpenedAtRef.current.get(tabId),
|
|
276
357
|
onOpenTabsChange,
|
|
277
358
|
onSelect,
|
|
278
359
|
onCreate,
|
|
@@ -289,7 +370,7 @@ function TabStripRoot({ className, tabsListClassName, children, tabs, openTabs,
|
|
|
289
370
|
const handleValueChange = (value) => {
|
|
290
371
|
onSelect?.(value);
|
|
291
372
|
};
|
|
292
|
-
return (_jsx(Tabs, { value: selectedTabId ?? undefined, onValueChange: handleValueChange, className: cn('bg-muted w-full min-w-0', className), children: _jsx(TabStripContext.Provider, { value: contextValue, children: _jsx(TabsList, { className: cn('flex w-full min-w-0 justify-start gap-2 bg-transparent p-0', tabsListClassName), children: children ?? (_jsxs(_Fragment, { children: [_jsx(TabStripSearchDropdown, {}), _jsx(TabStripTabs, {}), _jsx(TabStripNewButton, {})] })) }) }) }));
|
|
373
|
+
return (_jsx(Tabs, { value: selectedTabId ?? undefined, onValueChange: handleValueChange, activationMode: "manual", className: cn('bg-muted w-full min-w-0', className), children: _jsx(TabStripContext.Provider, { value: contextValue, children: _jsx(TabsList, { className: cn('flex h-9 w-full min-w-0 items-center justify-start gap-2 overflow-visible bg-transparent p-0', tabsListClassName), children: children ?? (_jsxs(_Fragment, { children: [_jsx(TabStripSearchDropdown, {}), _jsx(TabStripTabs, {}), _jsx(TabStripNewButton, {})] })) }) }) }));
|
|
293
374
|
}
|
|
294
375
|
// Attach subcomponents
|
|
295
376
|
export const TabStrip = Object.assign(TabStripRoot, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-strip.js","sourceRoot":"","sources":["../../src/components/tab-strip.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DndContext,\n DragEndEvent,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n restrictToHorizontalAxis,\n restrictToParentElement,\n} from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n arrayMove,\n horizontalListSortingStrategy,\n useSortable,\n} from '@dnd-kit/sortable';\nimport {\n EllipsisVerticalIcon,\n ListCollapseIcon,\n PlusIcon,\n SearchIcon,\n XIcon,\n} from 'lucide-react';\nimport React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nconst DRAG_MODIFIERS = [restrictToHorizontalAxis, restrictToParentElement];\n\nimport {cn} from '../lib/utils';\nimport {Button} from './button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport {EditableText} from './editable-text';\nimport {Input} from './input';\nimport {Tabs, TabsList, TabsTrigger} from './tabs';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from './tooltip';\n\nexport interface TabDescriptor {\n id: string;\n name: string;\n [key: string]: unknown;\n}\n\n// -----------------------------------------------------------------------------\n// Context\n// -----------------------------------------------------------------------------\n\ninterface TabStripContextValue {\n // Data\n openTabItems: TabDescriptor[];\n closedTabs: TabDescriptor[];\n closedTabIds: Set<string>;\n filteredTabs: TabDescriptor[];\n editingTabId: string | null;\n search: string;\n scrollContainerRef: React.RefObject<HTMLDivElement>;\n selectedTabId?: string | null;\n openTabs: string[];\n preventCloseLastTab: boolean;\n\n // Callbacks\n onOpenTabsChange?: (tabIds: string[]) => void;\n onSelect?: (tabId: string) => void;\n onCreate?: () => void;\n onRename?: (tabId: string, newName: string) => void;\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n renderSearchItemActions?: (tab: TabDescriptor) => React.ReactNode;\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n\n // Internal handlers\n setSearch: (value: string) => void;\n handleStartEditing: (tabId: string) => void;\n handleStopEditing: () => void;\n handleInlineRename: (tabId: string, newName: string) => void;\n handleClose: (tabId: string) => void;\n}\n\nconst TabStripContext = createContext<TabStripContextValue | null>(null);\n\nfunction useTabStripContext() {\n const context = useContext(TabStripContext);\n if (!context) {\n throw new Error('TabStrip subcomponents must be used within a TabStrip');\n }\n return context;\n}\n\n// -----------------------------------------------------------------------------\n// Subcomponents\n// -----------------------------------------------------------------------------\n\ninterface TabStripTabsProps {\n className?: string;\n /** Custom className for individual tab triggers. */\n tabClassName?: string;\n}\n\ninterface SortableTabProps {\n tab: TabDescriptor;\n tabClassName?: string;\n editingTabId: string | null;\n hideCloseButton?: boolean;\n onClose: (tabId: string) => void;\n onStartEditing: (tabId: string) => void;\n onStopEditing: () => void;\n onInlineRename: (tabId: string, newName: string) => void;\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n}\n\n/**\n * A single sortable tab item.\n */\nfunction SortableTab({\n tab,\n tabClassName,\n editingTabId,\n hideCloseButton,\n onClose,\n onStartEditing,\n onStopEditing,\n onInlineRename,\n renderTabMenu,\n renderTabLabel,\n}: SortableTabProps) {\n const {attributes, listeners, setNodeRef, transform, transition, isDragging} =\n useSortable({id: tab.id});\n\n const style: React.CSSProperties = {\n // Use Translate instead of Transform to avoid scale changes that squeeze the tab\n transform: transform\n ? `translate3d(${transform.x}px, ${transform.y}px, 0)`\n : undefined,\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n const menuContent = renderTabMenu?.(tab);\n\n return (\n <div\n ref={setNodeRef}\n className=\"h-full flex-shrink-0\"\n style={style}\n {...attributes}\n {...listeners}\n >\n <TabsTrigger\n value={tab.id}\n className={cn(\n 'data-[state=inactive]:hover:bg-primary/5',\n 'group flex h-full min-w-[100px] max-w-[200px] flex-shrink-0 cursor-grab',\n 'items-center justify-between gap-1 overflow-hidden rounded-b-none',\n 'py-0 pl-4 pr-1 font-normal data-[state=active]:shadow-none',\n tabClassName,\n )}\n >\n <div\n className=\"flex min-w-0 items-center\"\n onDoubleClick={() => onStartEditing(tab.id)}\n >\n {editingTabId !== tab.id ? (\n <div className=\"truncate text-sm\">\n {renderTabLabel ? renderTabLabel(tab) : tab.name}\n </div>\n ) : (\n <EditableText\n value={tab.name}\n onChange={(newName) => onInlineRename(tab.id, newName)}\n className=\"h-6 min-w-0 flex-1 truncate text-sm shadow-none\"\n isEditing\n onEditingChange={(isEditing) => {\n if (!isEditing) {\n onStopEditing();\n }\n }}\n />\n )}\n </div>\n\n <div className=\"flex flex-shrink-0 items-center\">\n {menuContent && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Tab options\"\n className=\"hover:bg-primary/10 flex h-5 w-5 cursor-pointer items-center justify-center rounded p-1 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100\"\n onMouseDown={(event) => {\n event.stopPropagation();\n event.preventDefault();\n }}\n onClick={(event) => {\n event.stopPropagation();\n }}\n >\n <EllipsisVerticalIcon className=\"h-3 w-3\" />\n </span>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n {menuContent}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n\n {!hideCloseButton && (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Close tab\"\n className=\"hover:bg-primary/10 flex h-5 w-5 cursor-pointer items-center justify-center rounded p-1\"\n onMouseDown={(event) => {\n event.stopPropagation();\n event.preventDefault();\n }}\n onClick={(event) => {\n event.stopPropagation();\n event.preventDefault();\n onClose(tab.id);\n }}\n >\n <XIcon className=\"h-4 w-4\" />\n </span>\n )}\n </div>\n </TabsTrigger>\n </div>\n );\n}\n\n// -----------------------------------------------------------------------------\n// Tab Menu Components (for use with renderTabMenu)\n// -----------------------------------------------------------------------------\n\ninterface TabStripMenuItemProps {\n children: React.ReactNode;\n onClick?: () => void;\n variant?: 'default' | 'destructive';\n className?: string;\n disabled?: boolean;\n}\n\n/**\n * A menu item for the tab's dropdown menu.\n */\nfunction TabStripMenuItem({\n children,\n onClick,\n variant = 'default',\n className,\n disabled,\n}: TabStripMenuItemProps) {\n return (\n <DropdownMenuItem\n disabled={disabled}\n onClick={(event) => {\n event.stopPropagation();\n onClick?.();\n }}\n className={cn(\n variant === 'destructive' && 'text-destructive focus:text-destructive',\n className,\n )}\n >\n {children}\n </DropdownMenuItem>\n );\n}\n\ninterface TabStripMenuSeparatorProps {\n className?: string;\n}\n\n/**\n * A separator for the tab's dropdown menu.\n */\nfunction TabStripMenuSeparator({className}: TabStripMenuSeparatorProps) {\n return <DropdownMenuSeparator className={className} />;\n}\n\ninterface TabStripSearchItemActionProps {\n icon: React.ReactNode;\n onClick?: () => void;\n 'aria-label': string;\n className?: string;\n}\n\n/**\n * An action button for search dropdown items.\n */\nfunction TabStripSearchItemAction({\n icon,\n onClick,\n 'aria-label': ariaLabel,\n className,\n}: TabStripSearchItemActionProps) {\n return (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label={ariaLabel}\n className={cn(\n 'text-muted-foreground hover:text-foreground flex h-4 w-4 cursor-pointer items-center justify-center rounded',\n className,\n )}\n onClick={(event) => {\n event.stopPropagation();\n onClick?.();\n }}\n >\n {icon}\n </span>\n );\n}\n\n/**\n * Renders the scrollable row of open tabs with drag-to-reorder support.\n */\nfunction TabStripTabs({className, tabClassName}: TabStripTabsProps) {\n const {\n openTabItems,\n editingTabId,\n scrollContainerRef,\n onOpenTabsChange,\n renderTabMenu,\n renderTabLabel,\n preventCloseLastTab,\n handleStartEditing,\n handleStopEditing,\n handleInlineRename,\n handleClose,\n } = useTabStripContext();\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5, // 5px movement before drag starts (allows clicks)\n },\n }),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const {active, over} = event;\n if (!over || active.id === over.id || !onOpenTabsChange) return;\n\n const oldIndex = openTabItems.findIndex((tab) => tab.id === active.id);\n const newIndex = openTabItems.findIndex((tab) => tab.id === over.id);\n\n if (oldIndex !== -1 && newIndex !== -1) {\n const newOrder = arrayMove(\n openTabItems.map((t) => t.id),\n oldIndex,\n newIndex,\n );\n onOpenTabsChange(newOrder);\n }\n };\n\n const tabIds = useMemo(() => openTabItems.map((t) => t.id), [openTabItems]);\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={DRAG_MODIFIERS}\n autoScroll={true}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={tabIds} strategy={horizontalListSortingStrategy}>\n <div\n ref={scrollContainerRef}\n className={cn(\n 'flex h-full min-w-0 items-center gap-1 overflow-x-auto overflow-y-hidden pr-1 [&::-webkit-scrollbar]:hidden',\n className,\n )}\n >\n {openTabItems.map((tab) => (\n <SortableTab\n key={tab.id}\n tab={tab}\n tabClassName={tabClassName}\n editingTabId={editingTabId}\n hideCloseButton={preventCloseLastTab && openTabItems.length === 1}\n onClose={handleClose}\n onStartEditing={handleStartEditing}\n onStopEditing={handleStopEditing}\n onInlineRename={handleInlineRename}\n renderTabMenu={renderTabMenu}\n renderTabLabel={renderTabLabel}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n );\n}\n\ninterface TabStripSearchDropdownProps {\n className?: string;\n triggerClassName?: string;\n /** Whether to auto-focus the search input when dropdown opens. Defaults to true. */\n autoFocus?: boolean;\n /** Optional tooltip content for the trigger button. */\n tooltip?: React.ReactNode;\n /** Optional custom icon for the trigger button. */\n triggerIcon?: React.ReactNode;\n}\n\n/**\n * Renders the dropdown with search for browsing tabs.\n * By default shows only closed tabs. When searching, shows all matching tabs.\n */\nfunction TabStripSearchDropdown({\n className,\n triggerClassName,\n autoFocus = true,\n tooltip,\n triggerIcon,\n}: TabStripSearchDropdownProps) {\n const {\n search,\n setSearch,\n closedTabs,\n filteredTabs,\n closedTabIds,\n openTabs,\n onOpenTabsChange,\n onSelect,\n renderSearchItemActions,\n } = useTabStripContext();\n\n const [isOpen, setIsOpen] = useState(false);\n\n const isSearching = search.trim().length > 0;\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (!open) {\n setSearch('');\n }\n };\n\n const handleTabClick = (tabId: string) => {\n if (closedTabIds.has(tabId)) {\n // Opening a closed tab: add to openTabs and select it\n onOpenTabsChange?.([...openTabs, tabId]);\n onSelect?.(tabId);\n } else {\n // Already open: just select it\n onSelect?.(tabId);\n }\n setIsOpen(false);\n };\n\n const triggerButton = (\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n aria-label=\"Browse tabs\"\n className={cn(\n 'hover:bg-primary/10 h-full flex-shrink-0',\n triggerClassName,\n )}\n >\n {triggerIcon ?? <ListCollapseIcon className=\"h-4 w-4\" />}\n </Button>\n </DropdownMenuTrigger>\n );\n\n return (\n <DropdownMenu open={isOpen} onOpenChange={handleOpenChange}>\n {tooltip ? (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{triggerButton}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : (\n triggerButton\n )}\n\n <DropdownMenuContent\n align=\"start\"\n onCloseAutoFocus={(event) => event.preventDefault()}\n className={cn('flex max-h-[400px] max-w-[240px] flex-col', className)}\n >\n <div className=\"flex flex-shrink-0 items-center gap-1 px-2\">\n <SearchIcon className=\"text-muted-foreground\" size={14} />\n <Input\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'ArrowDown' || event.key === 'Tab') {\n event.preventDefault();\n const firstItem = event.currentTarget\n .closest('[role=\"menu\"]')\n ?.querySelector<HTMLElement>(\n '[role=\"menuitem\"]:not([disabled])',\n );\n firstItem?.focus();\n } else {\n event.stopPropagation();\n }\n }}\n onKeyUp={(event) => event.stopPropagation()}\n className=\"border-none text-xs shadow-none focus-visible:ring-0\"\n placeholder=\"Search...\"\n aria-label=\"Search\"\n autoFocus={autoFocus}\n />\n </div>\n <DropdownMenuSeparator className=\"flex-shrink-0\" />\n\n <div className=\"overflow-y-auto\">\n {isSearching ? (\n <DropdownTabItems\n tabs={filteredTabs}\n emptyMessage=\"No matching tabs\"\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n />\n ) : (\n <DropdownTabItems\n tabs={closedTabs}\n emptyMessage=\"No closed tabs\"\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n />\n )}\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\ninterface DropdownTabItemsProps {\n tabs: TabDescriptor[];\n emptyMessage?: string;\n onTabClick?: (tabId: string) => void;\n renderActions?: (tab: TabDescriptor) => React.ReactNode;\n}\n\nfunction DropdownTabItems({\n tabs,\n emptyMessage,\n onTabClick,\n renderActions,\n}: DropdownTabItemsProps) {\n if (tabs.length === 0) {\n if (!emptyMessage) return null;\n return (\n <DropdownMenuLabel className=\"items-center justify-center text-xs\">\n {emptyMessage}\n </DropdownMenuLabel>\n );\n }\n\n return (\n <>\n {tabs.map((tab) => (\n <DropdownMenuItem\n key={tab.id}\n onClick={() => onTabClick?.(tab.id)}\n className=\"flex h-7 cursor-pointer items-center justify-between truncate\"\n >\n <span className=\"xs truncate pl-1\">{tab.name}</span>\n {renderActions && (\n <div className=\"flex items-center gap-2\">{renderActions(tab)}</div>\n )}\n </DropdownMenuItem>\n ))}\n </>\n );\n}\n\ninterface TabStripNewButtonProps {\n className?: string;\n /** Optional tooltip content for the button. */\n tooltip?: React.ReactNode;\n}\n\n/**\n * Renders a button to create a new tab.\n */\nfunction TabStripNewButton({className, tooltip}: TabStripNewButtonProps) {\n const {onCreate} = useTabStripContext();\n\n if (!onCreate) {\n return null;\n }\n\n const button = (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n aria-label=\"Create new tab\"\n onClick={() => onCreate()}\n className={cn('hover:bg-primary/10 h-full flex-shrink-0', className)}\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n );\n\n if (tooltip) {\n return (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n }\n\n return button;\n}\n\n// -----------------------------------------------------------------------------\n// Main Component\n// -----------------------------------------------------------------------------\n\nexport interface TabStripProps {\n className?: string;\n tabsListClassName?: string;\n children?: React.ReactNode;\n /** All available tabs. */\n tabs: TabDescriptor[];\n /** IDs of tabs that are currently open. */\n openTabs: string[];\n /** ID of the currently selected tab. */\n selectedTabId?: string | null;\n /** If true, hides the close button when only one tab remains open. */\n preventCloseLastTab?: boolean;\n /** Called when a tab is closed (hidden, can be reopened). */\n onClose?: (tabId: string) => void;\n /** Called when the list of open tabs changes (open from dropdown or reorder). */\n onOpenTabsChange?: (tabIds: string[]) => void;\n /** Called when a tab is selected. */\n onSelect?: (tabId: string) => void;\n /** Called when a new tab should be created. */\n onCreate?: () => void;\n /** Called when a tab is renamed inline. */\n onRename?: (tabId: string, newName: string) => void;\n /** Render function for the tab's dropdown menu. Use TabStrip.MenuItem and TabStrip.MenuSeparator. */\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n /** Render function for search dropdown item actions. Use TabStrip.SearchItemAction. */\n renderSearchItemActions?: (tab: TabDescriptor) => React.ReactNode;\n /** Render function for custom tab content. Receives the tab and returns the content to display. */\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n}\n\n/**\n * A composable tab strip component with search dropdown and tab management.\n *\n * @example\n * // Default layout\n * <TabStrip\n * tabs={tabs}\n * openTabs={openTabs}\n * onClose={closeTab}\n * onOpen={openTab}\n * onCreate={createTab}\n * />\n *\n * @example\n * // Custom layout with subcomponents\n * <TabStrip tabs={tabs} openTabs={openTabs} onClose={closeTab}>\n * <TabStrip.Tabs className=\"flex-1\" />\n * <TabStrip.SearchDropdown />\n * <TabStrip.NewButton />\n * </TabStrip>\n */\nfunction TabStripRoot({\n className,\n tabsListClassName,\n children,\n tabs,\n openTabs,\n selectedTabId,\n preventCloseLastTab = false,\n onClose,\n onOpenTabsChange,\n onSelect,\n onCreate,\n onRename,\n renderTabMenu,\n renderSearchItemActions,\n renderTabLabel,\n}: TabStripProps) {\n const [search, setSearch] = useState('');\n const [editingTabId, setEditingTabId] = useState<string | null>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null!);\n const prevSelectedIdRef = useRef<string | null>(null);\n\n const openTabsSet = useMemo(() => new Set(openTabs), [openTabs]);\n\n // Build openTabItems in the order of openTabs (for drag-to-reorder)\n const openTabItems = useMemo(() => {\n const tabsById = new Map(tabs.map((tab) => [tab.id, tab]));\n return openTabs\n .map((id) => tabsById.get(id))\n .filter((tab): tab is TabDescriptor => tab !== undefined);\n }, [tabs, openTabs]);\n\n const closedTabs = useMemo(\n () => tabs.filter((tab) => !openTabsSet.has(tab.id)),\n [tabs, openTabsSet],\n );\n\n const closedTabIds = useMemo(\n () => new Set(closedTabs.map((tab) => tab.id)),\n [closedTabs],\n );\n\n const trimmedSearch = search.trim().toLowerCase();\n\n const filteredTabs = useMemo(\n () =>\n trimmedSearch\n ? tabs.filter((tab) => tab.name.toLowerCase().includes(trimmedSearch))\n : [],\n [tabs, trimmedSearch],\n );\n\n // Auto-scroll to selected tab\n useEffect(() => {\n if (!selectedTabId) return;\n if (prevSelectedIdRef.current === selectedTabId) return;\n prevSelectedIdRef.current = selectedTabId;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const isOpen = openTabItems.some((tab) => tab.id === selectedTabId);\n if (!isOpen) return;\n\n const frameId = requestAnimationFrame(() => {\n const activeTab = container.querySelector<HTMLElement>(\n '[data-state=\"active\"]',\n );\n if (!activeTab) return;\n\n activeTab.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest',\n });\n });\n\n return () => {\n cancelAnimationFrame(frameId);\n };\n }, [selectedTabId, openTabItems]);\n\n const handleInlineRename = (tabId: string, newName: string) => {\n if (!onRename) return;\n const tab = tabs.find((t) => t.id === tabId);\n const trimmed = newName.trim();\n if (!trimmed || trimmed === tab?.name) {\n setEditingTabId(null);\n return;\n }\n onRename(tabId, trimmed);\n setEditingTabId(null);\n };\n\n const handleStartEditing = (tabId: string) => {\n if (!onRename) return;\n setEditingTabId(tabId);\n };\n\n const handleStopEditing = () => {\n setEditingTabId(null);\n };\n\n const handleClose = (tabId: string) => {\n // If closing the selected tab, select the one to the left (or right if leftmost)\n if (selectedTabId === tabId && openTabItems.length > 1) {\n const closingIndex = openTabItems.findIndex((t) => t.id === tabId);\n // If closing the leftmost, select the next; otherwise select the previous\n const newIndex = closingIndex === 0 ? 1 : closingIndex - 1;\n const newSelectedId = openTabItems[newIndex]?.id;\n if (newSelectedId) {\n onSelect?.(newSelectedId);\n }\n }\n onClose?.(tabId);\n };\n\n const contextValue: TabStripContextValue = {\n openTabItems,\n closedTabs,\n closedTabIds,\n filteredTabs,\n editingTabId,\n search,\n scrollContainerRef,\n selectedTabId,\n openTabs,\n preventCloseLastTab,\n onOpenTabsChange,\n onSelect,\n onCreate,\n onRename,\n renderTabMenu,\n renderSearchItemActions,\n renderTabLabel,\n setSearch,\n handleStartEditing,\n handleStopEditing,\n handleInlineRename,\n handleClose,\n };\n\n const handleValueChange = (value: string) => {\n onSelect?.(value);\n };\n\n return (\n <Tabs\n value={selectedTabId ?? undefined}\n onValueChange={handleValueChange}\n className={cn('bg-muted w-full min-w-0', className)}\n >\n <TabStripContext.Provider value={contextValue}>\n <TabsList\n className={cn(\n 'flex w-full min-w-0 justify-start gap-2 bg-transparent p-0',\n tabsListClassName,\n )}\n >\n {children ?? (\n <>\n <TabStripSearchDropdown />\n <TabStripTabs />\n <TabStripNewButton />\n </>\n )}\n </TabsList>\n </TabStripContext.Provider>\n </Tabs>\n );\n}\n\n// Attach subcomponents\nexport const TabStrip = Object.assign(TabStripRoot, {\n Tabs: TabStripTabs,\n SearchDropdown: TabStripSearchDropdown,\n NewButton: TabStripNewButton,\n MenuItem: TabStripMenuItem,\n MenuSeparator: TabStripMenuSeparator,\n SearchItemAction: TabStripSearchItemAction,\n});\n\nexport type {\n TabStripMenuItemProps,\n TabStripMenuSeparatorProps,\n TabStripNewButtonProps,\n TabStripSearchDropdownProps,\n TabStripSearchItemActionProps,\n TabStripTabsProps,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"tab-strip.js","sourceRoot":"","sources":["../../src/components/tab-strip.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,UAAU,EAEV,aAAa,EACb,aAAa,EACb,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,SAAS,EACT,6BAA6B,EAC7B,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,KAAK,GACN,MAAM,cAAc,CAAC;AACtB,OAAc,EACZ,aAAa,EACb,UAAU,EACV,SAAS,EACT,eAAe,EACf,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AAEf,MAAM,cAAc,GAAG,CAAC,wBAAwB,EAAE,uBAAuB,CAAC,CAAC;AAE3E,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAChC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAC,MAAM,QAAQ,CAAC;AACnD,OAAO,EACL,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AA2CnB,MAAM,eAAe,GAAG,aAAa,CAA8B,IAAI,CAAC,CAAC;AAEzE,SAAS,kBAAkB;IACzB,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAyBD;;GAEG;AACH,SAAS,WAAW,CAAC,EACnB,GAAG,EACH,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,OAAO,EACP,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,GACG;IACjB,MAAM,EAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAC,GAC1E,WAAW,CAAC,EAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAC,CAAC,CAAC;IAE5B,MAAM,KAAK,GAAwB;QACjC,iFAAiF;QACjF,SAAS,EAAE,SAAS;YAClB,CAAC,CAAC,eAAe,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,QAAQ;YACtD,CAAC,CAAC,SAAS;QACb,UAAU;QACV,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAC9B,CAAC;IAEF,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC;IAEzC,OAAO,CACL,cACE,GAAG,EAAE,UAAU,EACf,SAAS,EAAC,sBAAsB,EAChC,KAAK,EAAE,KAAK,iBACC,GAAG,CAAC,EAAE,KACf,UAAU,KACV,SAAS,EACb,QAAQ,EAAE,CAAC,CAAC,YAEZ,4BACc,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC3D,SAAS,EAAE,EAAE,CACX,0CAA0C,EAC1C,yEAAyE,EACzE,sDAAsD,EACtD,4DAA4D,EAC5D,YAAY,EACZ,YAAY,KAAK,GAAG,CAAC,EAAE,IAAI,sBAAsB,CAClD,YAED,eAAK,SAAS,EAAC,kDAAkD,aAC/D,KAAC,WAAW,IACV,KAAK,EAAE,GAAG,CAAC,EAAE,EACb,QAAQ,EAAE,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,kBACpC,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EACtD,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,2DAA2D,EAC3D,SAAS,EACT,uGAAuG,EACvG,sGAAsG,EACtG,YAAY,KAAK,GAAG,CAAC,EAAE,IAAI,sBAAsB,CAClD,EACD,aAAa,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,YAE1C,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CACzB,cAAK,SAAS,EAAC,kBAAkB,YAC9B,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAC5C,CACP,CAAC,CAAC,CAAC,CACF,KAAC,YAAY,IACX,KAAK,EAAE,GAAG,CAAC,IAAI,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,EACtD,SAAS,EAAC,iDAAiD,EAC3D,SAAS,QACT,SAAS,QACT,aAAa,QACb,2BAA2B,EAAE,KAAK,EAClC,eAAe,EAAE,CAAC,SAAS,EAAE,EAAE;gCAC7B,IAAI,CAAC,SAAS,EAAE,CAAC;oCACf,aAAa,EAAE,CAAC;gCAClB,CAAC;4BACH,CAAC,GACD,CACH,GACW,EAEb,WAAW,IAAI,CACd,MAAC,YAAY,eACX,KAAC,mBAAmB,IAAC,OAAO,kBAC1B,iBACE,IAAI,EAAC,QAAQ,gBACF,aAAa,EACxB,SAAS,EAAC,kUAAkU,EAC5U,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;wCACrB,KAAK,CAAC,eAAe,EAAE,CAAC;wCACxB,KAAK,CAAC,cAAc,EAAE,CAAC;oCACzB,CAAC,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;wCACjB,KAAK,CAAC,eAAe,EAAE,CAAC;oCAC1B,CAAC,YAED,KAAC,oBAAoB,IAAC,SAAS,EAAC,SAAS,GAAG,GACrC,GACW,EACtB,KAAC,mBAAmB,IAAC,KAAK,EAAC,OAAO,YAC/B,WAAW,GACQ,IACT,CAChB,EAEA,CAAC,eAAe,IAAI,CACnB,iBACE,IAAI,EAAC,QAAQ,gBACF,WAAW,EACtB,SAAS,EAAC,qSAAqS,EAC/S,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;4BACrB,KAAK,CAAC,eAAe,EAAE,CAAC;4BACxB,KAAK,CAAC,cAAc,EAAE,CAAC;wBACzB,CAAC,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;4BACjB,KAAK,CAAC,eAAe,EAAE,CAAC;4BACxB,KAAK,CAAC,cAAc,EAAE,CAAC;4BACvB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBAClB,CAAC,YAED,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,GACtB,CACV,IACG,GACF,GACF,CACP,CAAC;AACJ,CAAC;AAcD;;GAEG;AACH,SAAS,gBAAgB,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,OAAO,GAAG,SAAS,EACnB,SAAS,EACT,QAAQ,GACc;IACtB,OAAO,CACL,KAAC,gBAAgB,IACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,EACD,SAAS,EAAE,EAAE,CACX,OAAO,KAAK,aAAa,IAAI,yCAAyC,EACtE,SAAS,CACV,YAEA,QAAQ,GACQ,CACpB,CAAC;AACJ,CAAC;AAMD;;GAEG;AACH,SAAS,qBAAqB,CAAC,EAAC,SAAS,EAA6B;IACpE,OAAO,KAAC,qBAAqB,IAAC,SAAS,EAAE,SAAS,GAAI,CAAC;AACzD,CAAC;AASD;;GAEG;AACH,SAAS,wBAAwB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,YAAY,EAAE,SAAS,EACvB,SAAS,GACqB;IAC9B,OAAO,CACL,eACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,CAAC,gBACA,SAAS,EACrB,SAAS,EAAE,EAAE,CACX,6GAA6G,EAC7G,SAAS,CACV,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,YAEA,IAAI,GACA,CACR,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,EAAC,SAAS,EAAE,YAAY,EAAoB;IAChE,MAAM,EACJ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,GACZ,GAAG,kBAAkB,EAAE,CAAC;IAEzB,MAAM,OAAO,GAAG,UAAU,CACxB,SAAS,CAAC,aAAa,EAAE;QACvB,oBAAoB,EAAE;YACpB,QAAQ,EAAE,CAAC,EAAE,kDAAkD;SAChE;KACF,CAAC,CACH,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAE,EAAE;QAC5C,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAEhE,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QAErE,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,SAAS,CACxB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC7B,QAAQ,EACR,QAAQ,CACT,CAAC;YACF,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAE5E,OAAO,CACL,KAAC,UAAU,IACT,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,aAAa,EACjC,SAAS,EAAE,cAAc,EACzB,UAAU,EAAE,IAAI,EAChB,SAAS,EAAE,aAAa,YAExB,KAAC,eAAe,IAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,6BAA6B,YACrE,KAAC,aAAa,IACZ,SAAS,EAAC,uBAAuB,EACjC,SAAS,EAAE,kBAAkB,EAC7B,eAAe,EAAE,EAAE,CACjB,2EAA2E,EAC3E,sEAAsE,EACtE,SAAS,CACV,EACD,eAAe,EAAC,QAAQ,EACxB,cAAc,EAAC,KAAK,EACpB,kBAAkB,EAAC,oBAAoB,YAEtC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACzB,KAAC,WAAW,IAEV,GAAG,EAAE,GAAG,EACR,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,mBAAmB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EACjE,OAAO,EAAE,WAAW,EACpB,cAAc,EAAE,kBAAkB,EAClC,aAAa,EAAE,iBAAiB,EAChC,cAAc,EAAE,kBAAkB,EAClC,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,IAVzB,GAAG,CAAC,EAAE,CAWX,CACH,CAAC,GACY,GACA,GACP,CACd,CAAC;AACJ,CAAC;AAuBD;;;GAGG;AACH,SAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,gBAAgB,EAChB,SAAS,GAAG,IAAI,EAChB,OAAO,EACP,WAAW,EACX,YAAY,GAAG,SAAS,EACxB,kBAAkB,GAAG,kBAAkB,EACvC,eAAe,GAAG,iBAAiB,EACnC,eAAe,GAAG,QAAQ,EAC1B,kBAAkB,GACU;IAC5B,MAAM,EACJ,YAAY,EACZ,MAAM,EACN,SAAS,EACT,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,EACR,uBAAuB,EACvB,eAAe,EACf,WAAW,GACZ,GAAG,kBAAkB,EAAE,CAAC;IAEzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAE7C,MAAM,gBAAgB,GAAG,CAAC,IAAa,EAAE,EAAE;QACzC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,EAAE;QACvC,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,sDAAsD;YACtD,gBAAgB,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACjD,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,+BAA+B;YAC/B,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,SAAS,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,UAA2B,EAAE,EAAE;QACpD,IAAI,eAAe,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAChD,GAAG;YACH,KAAK;YACL,EAAE,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC,CAAC;QAEJ,OAAO,SAAS;aACb,KAAK,EAAE;aACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YACvB,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YACvB,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAChB,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3B,CAAC;YACD,OAAO,GAAG,GAAG,GAAG,CAAC;QACnB,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAEnE,MAAM,gBAAgB,GAAG,aAAa,CACpC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CACxD,CAAC;IACF,MAAM,kBAAkB,GAAG,aAAa,CACtC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CACvD,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,GAAkB,EAAE,EAAE;QAClD,MAAM,YAAY,GAAG,mBAAmB,IAAI,CAAC,YAAY,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5E,OAAO,CACL,8BACG,uBAAuB,EAAE,CAAC,GAAG,CAAC,EAC/B,KAAC,wBAAwB,IACvB,IAAI,EAAE,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,gBACvB,SAAS,GAAG,CAAC,IAAI,EAAE,EAC/B,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAC7D,SAAS,EAAE,EAAE,CAAC,YAAY,IAAI,gCAAgC,CAAC,GAC/D,IACD,CACJ,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CACpB,KAAC,mBAAmB,IAAC,OAAO,kBAC1B,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,gBACJ,aAAa,EACxB,SAAS,EAAE,EAAE,CACX,0CAA0C,EAC1C,gBAAgB,CACjB,YAEA,WAAW,IAAI,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,GACjD,GACW,CACvB,CAAC;IAEF,OAAO,CACL,MAAC,YAAY,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,aACvD,OAAO,CAAC,CAAC,CAAC,CACT,KAAC,eAAe,cACd,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBAAE,aAAa,GAAkB,EACxD,KAAC,cAAc,cAAE,OAAO,GAAkB,IAClC,GACM,CACnB,CAAC,CAAC,CAAC,CACF,aAAa,CACd,EAED,MAAC,mBAAmB,IAClB,KAAK,EAAC,OAAO,EACb,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EACnD,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,SAAS,CACV,aAED,eAAK,SAAS,EAAC,4CAA4C,aACzD,KAAC,UAAU,IAAC,SAAS,EAAC,uBAAuB,EAAC,IAAI,EAAE,EAAE,GAAI,EAC1D,KAAC,KAAK,IACJ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;oCACnB,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;wCACrD,KAAK,CAAC,cAAc,EAAE,CAAC;wCACvB,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa;6CAClC,OAAO,CAAC,eAAe,CAAC;4CACzB,EAAE,aAAa,CACb,mCAAmC,CACpC,CAAC;wCACJ,SAAS,EAAE,KAAK,EAAE,CAAC;oCACrB,CAAC;yCAAM,CAAC;wCACN,KAAK,CAAC,eAAe,EAAE,CAAC;oCAC1B,CAAC;gCACH,CAAC,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAC3C,SAAS,EAAC,sDAAsD,EAChE,WAAW,EAAC,WAAW,gBACZ,QAAQ,EACnB,SAAS,EAAE,SAAS,GACpB,IACE,EACN,KAAC,qBAAqB,IAAC,SAAS,EAAC,eAAe,GAAG,EAEnD,cAAK,SAAS,EAAC,mCAAmC,YAC/C,WAAW,CAAC,CAAC,CAAC,CACb,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC1B,KAAC,gBAAgB,IACf,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,uBAAuB,GACtC,CACH,CAAC,CAAC,CAAC,CACF,8BACE,KAAC,gBAAgB,IACf,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,oBAAoB,GACnC,EACD,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,CAChC,8BACG,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,KAAC,qBAAqB,KAAG,EACzD,KAAC,iBAAiB,IAAC,SAAS,EAAC,gDAAgD,YAC1E,eAAe,GACE,EACpB,KAAC,gBAAgB,IACf,IAAI,EAAE,kBAAkB,EACxB,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,uBAAuB,EACtC,gBAAgB,EAAE,GAAG,EAAE,CAAC,uBAAuB,GAC/C,IACD,CACJ,IACA,CACJ,CACF,CAAC,CAAC,CAAC,CACF,4BACG,UAAU,CAAC,CAAC,CAAC,CACZ,8BACE,KAAC,gBAAgB,IACf,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,oBAAoB,GACnC,EACD,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,CAC5B,8BACG,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,KAAC,qBAAqB,KAAG,EACrD,KAAC,iBAAiB,IAAC,SAAS,EAAC,gDAAgD,YAC1E,eAAe,GACE,EACpB,KAAC,gBAAgB,IACf,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,uBAAuB,EACtC,gBAAgB,EAAE,GAAG,EAAE,CAAC,uBAAuB,GAC/C,IACD,CACJ,IACA,CACJ,CAAC,CAAC,CAAC,CACF,KAAC,gBAAgB,IACf,IAAI,EAAE,EAAE,EACR,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,uBAAuB,GACtC,CACH,GACA,CACJ,GACG,IACc,IACT,CAChB,CAAC;AACJ,CAAC;AAUD,SAAS,gBAAgB,CAAC,EACxB,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,gBAAgB,GACM;IACtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QAC/B,OAAO,CACL,KAAC,iBAAiB,IAAC,SAAS,EAAC,qCAAqC,YAC/D,YAAY,GACK,CACrB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,4BACG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,MAAC,gBAAgB,IAEf,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EACnC,SAAS,EAAE,EAAE,CACX,+DAA+D,EAC/D,gBAAgB,EAAE,CAAC,GAAG,CAAC,CACxB,aAED,eAAM,SAAS,EAAC,kBAAkB,YAAE,GAAG,CAAC,IAAI,GAAQ,EACnD,aAAa,IAAI,CAChB,cAAK,SAAS,EAAC,yBAAyB,YAAE,aAAa,CAAC,GAAG,CAAC,GAAO,CACpE,KAVI,GAAG,CAAC,EAAE,CAWM,CACpB,CAAC,GACD,CACJ,CAAC;AACJ,CAAC;AAQD;;GAEG;AACH,SAAS,iBAAiB,CAAC,EAAC,SAAS,EAAE,OAAO,EAAyB;IACrE,MAAM,EAAC,QAAQ,EAAC,GAAG,kBAAkB,EAAE,CAAC;IAExC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,CACb,KAAC,MAAM,IACL,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,OAAO,gBACJ,gBAAgB,EAC3B,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,EACzB,SAAS,EAAE,EAAE,CAAC,0CAA0C,EAAE,SAAS,CAAC,YAEpE,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,CACV,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,KAAC,eAAe,cACd,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBAAE,MAAM,GAAkB,EACjD,KAAC,cAAc,cAAE,OAAO,GAAkB,IAClC,GACM,CACnB,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAoCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAS,YAAY,CAAC,EACpB,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,mBAAmB,GAAG,KAAK,EAC3B,OAAO,EACP,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,uBAAuB,EACvB,cAAc,GACA;IACd,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,kBAAkB,GAAG,MAAM,CAAiB,IAAK,CAAC,CAAC;IACzD,MAAM,iBAAiB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,MAAM,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IACzD,MAAM,eAAe,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAE,CAAC,CAAC;IAE/D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEjE,oEAAoE;IACpE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE;QAChC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;aACpB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;aAC7B,MAAM,CAAC,CAAC,GAAG,EAAwB,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;IAC9D,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAErB,MAAM,UAAU,GAAG,OAAO,CACxB,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EACpD,CAAC,IAAI,EAAE,WAAW,CAAC,CACpB,CAAC;IAEF,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAC9C,CAAC,UAAU,CAAC,CACb,CAAC;IAEF,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAElD,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CACH,aAAa;QACX,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACtE,CAAC,CAAC,EAAE,EACR,CAAC,IAAI,EAAE,aAAa,CAAC,CACtB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvC,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;IACjC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,8BAA8B;IAC9B,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,IAAI,iBAAiB,CAAC,OAAO,KAAK,aAAa;YAAE,OAAO;QACxD,iBAAiB,CAAC,OAAO,GAAG,aAAa,CAAC;QAE1C,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,0EAA0E;QAC1E,cAAc,CAAC,GAAG,EAAE;YAClB,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CACvC,uBAAuB,CACxB,CAAC;YACF,IAAI,CAAC,SAAS;gBAAE,OAAO;YAEvB,SAAS,CAAC,cAAc,CAAC;gBACvB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;aAClB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,uDAAuD;IACzD,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,mEAAmE;QACnE,MAAM,SAAS,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CACvC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAC3C,CAAC;QAEF,iCAAiC;QACjC,iBAAiB,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE9C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,4EAA4E;QAC5E,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;YAAE,OAAO;QAEzD,sDAAsD;QACtD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjD,cAAc,CAAC,GAAG,EAAE;YAClB,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAC3C,iBAAiB,QAAQ,IAAI,CAC9B,CAAC;YACF,IAAI,CAAC,aAAa;gBAAE,OAAO;YAE3B,aAAa,CAAC,cAAc,CAAC;gBAC3B,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;aAClB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAE,OAAe,EAAE,EAAE;QAC5D,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC;YACtC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzB,eAAe,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAE,EAAE;QAC3C,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,eAAe,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,eAAe,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE;QACpC,iFAAiF;QACjF,IAAI,aAAa,KAAK,KAAK,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;YACnE,0EAA0E;YAC1E,MAAM,QAAQ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;YAC3D,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjD,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAyB;QACzC,YAAY;QACZ,UAAU;QACV,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,MAAM;QACN,kBAAkB;QAClB,aAAa;QACb,QAAQ;QACR,mBAAmB;QACnB,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9D,gBAAgB;QAChB,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,aAAa;QACb,uBAAuB;QACvB,cAAc;QACd,SAAS;QACT,kBAAkB;QAClB,iBAAiB;QACjB,kBAAkB;QAClB,WAAW;KACZ,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAE,EAAE;QAC1C,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,IAAI,IACH,KAAK,EAAE,aAAa,IAAI,SAAS,EACjC,aAAa,EAAE,iBAAiB,EAChC,cAAc,EAAC,QAAQ,EACvB,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,YAEnD,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,YAC3C,KAAC,QAAQ,IACP,SAAS,EAAE,EAAE,CACX,8FAA8F,EAC9F,iBAAiB,CAClB,YAEA,QAAQ,IAAI,CACX,8BACE,KAAC,sBAAsB,KAAG,EAC1B,KAAC,YAAY,KAAG,EAChB,KAAC,iBAAiB,KAAG,IACpB,CACJ,GACQ,GACc,GACtB,CACR,CAAC;AACJ,CAAC;AAED,uBAAuB;AACvB,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE;IAClD,IAAI,EAAE,YAAY;IAClB,cAAc,EAAE,sBAAsB;IACtC,SAAS,EAAE,iBAAiB;IAC5B,QAAQ,EAAE,gBAAgB;IAC1B,aAAa,EAAE,qBAAqB;IACpC,gBAAgB,EAAE,wBAAwB;CAC3C,CAAC,CAAC","sourcesContent":["import {\n DndContext,\n DragEndEvent,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n restrictToHorizontalAxis,\n restrictToParentElement,\n} from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n arrayMove,\n horizontalListSortingStrategy,\n useSortable,\n} from '@dnd-kit/sortable';\nimport {\n EllipsisVerticalIcon,\n ListCollapseIcon,\n PlusIcon,\n SearchIcon,\n XIcon,\n} from 'lucide-react';\nimport React, {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nconst DRAG_MODIFIERS = [restrictToHorizontalAxis, restrictToParentElement];\n\nimport {cn} from '../lib/utils';\nimport {Button} from './button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport {EditableText} from './editable-text';\nimport {Input} from './input';\nimport {ScrollableRow} from './scrollable-row';\nimport {Tabs, TabsList, TabsTrigger} from './tabs';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from './tooltip';\n\nexport interface TabDescriptor {\n id: string;\n name: string;\n [key: string]: unknown;\n}\n\n// -----------------------------------------------------------------------------\n// Context\n// -----------------------------------------------------------------------------\n\ninterface TabStripContextValue {\n // Data\n openTabItems: TabDescriptor[];\n closedTabs: TabDescriptor[];\n closedTabIds: Set<string>;\n filteredTabs: TabDescriptor[];\n editingTabId: string | null;\n search: string;\n scrollContainerRef: React.RefObject<HTMLDivElement>;\n selectedTabId?: string | null;\n openTabs?: string[];\n preventCloseLastTab: boolean;\n getLastOpenedAt: (tabId: string) => number | undefined;\n\n // Callbacks\n onOpenTabsChange?: (tabIds: string[]) => void;\n onSelect?: (tabId: string) => void;\n onCreate?: () => void;\n onRename?: (tabId: string, newName: string) => void;\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n renderSearchItemActions?: (tab: TabDescriptor) => React.ReactNode;\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n\n // Internal handlers\n setSearch: (value: string) => void;\n handleStartEditing: (tabId: string) => void;\n handleStopEditing: () => void;\n handleInlineRename: (tabId: string, newName: string) => void;\n handleClose: (tabId: string) => void;\n}\n\nconst TabStripContext = createContext<TabStripContextValue | null>(null);\n\nfunction useTabStripContext() {\n const context = useContext(TabStripContext);\n if (!context) {\n throw new Error('TabStrip subcomponents must be used within a TabStrip');\n }\n return context;\n}\n\n// -----------------------------------------------------------------------------\n// Subcomponents\n// -----------------------------------------------------------------------------\n\ninterface TabStripTabsProps {\n className?: string;\n /** Custom className for individual tab triggers. */\n tabClassName?: string;\n}\n\ninterface SortableTabProps {\n tab: TabDescriptor;\n tabClassName?: string;\n editingTabId: string | null;\n hideCloseButton?: boolean;\n onClose: (tabId: string) => void;\n onStartEditing: (tabId: string) => void;\n onStopEditing: () => void;\n onInlineRename: (tabId: string, newName: string) => void;\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n}\n\n/**\n * A single sortable tab item.\n */\nfunction SortableTab({\n tab,\n tabClassName,\n editingTabId,\n hideCloseButton,\n onClose,\n onStartEditing,\n onStopEditing,\n onInlineRename,\n renderTabMenu,\n renderTabLabel,\n}: SortableTabProps) {\n const {attributes, listeners, setNodeRef, transform, transition, isDragging} =\n useSortable({id: tab.id});\n\n const style: React.CSSProperties = {\n // Use Translate instead of Transform to avoid scale changes that squeeze the tab\n transform: transform\n ? `translate3d(${transform.x}px, ${transform.y}px, 0)`\n : undefined,\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n const menuContent = renderTabMenu?.(tab);\n\n return (\n <div\n ref={setNodeRef}\n className=\"h-full flex-shrink-0\"\n style={style}\n data-tab-id={tab.id}\n {...attributes}\n {...listeners}\n tabIndex={-1}\n >\n <div\n data-state={editingTabId === tab.id ? 'editing' : undefined}\n className={cn(\n 'data-[state=inactive]:hover:bg-primary/5',\n 'group flex h-full min-w-[100px] max-w-[200px] flex-shrink-0 cursor-grab',\n 'items-center gap-0.5 overflow-visible rounded-b-none',\n 'py-0 pl-0 pr-0 font-normal data-[state=active]:shadow-none',\n tabClassName,\n editingTabId === tab.id && 'focus-visible:ring-0',\n )}\n >\n <div className=\"relative flex h-full min-w-0 flex-1 items-center\">\n <TabsTrigger\n value={tab.id}\n tabIndex={editingTabId === tab.id ? -1 : undefined}\n data-editing={editingTabId === tab.id ? '' : undefined}\n className={cn(\n 'flex h-full min-w-0 flex-1 items-center justify-start gap-1',\n 'hover:bg-primary/10 overflow-hidden px-6 py-1 font-normal',\n 'min-h-7',\n 'data-[state=active]:bg-primary/10 data-[state=active]:text-foreground data-[state=active]:shadow-none',\n 'focus-visible:ring-primary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-offset-0',\n editingTabId === tab.id && 'focus-visible:ring-0',\n )}\n onDoubleClick={() => onStartEditing(tab.id)}\n >\n {editingTabId !== tab.id ? (\n <div className=\"truncate text-sm\">\n {renderTabLabel ? renderTabLabel(tab) : tab.name}\n </div>\n ) : (\n <EditableText\n value={tab.name}\n onChange={(newName) => onInlineRename(tab.id, newName)}\n className=\"h-6 min-w-0 flex-1 truncate text-sm shadow-none\"\n isEditing\n autoFocus\n selectOnFocus\n allowTabFocusWhenNotEditing={false}\n onEditingChange={(isEditing) => {\n if (!isEditing) {\n onStopEditing();\n }\n }}\n />\n )}\n </TabsTrigger>\n\n {menuContent && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Tab options\"\n className=\"hover:bg-primary/10 focus-visible:bg-primary/10 focus-visible:ring-primary absolute left-1 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded p-1 opacity-0 outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-0 group-hover:opacity-100 data-[state=open]:opacity-100\"\n onMouseDown={(event) => {\n event.stopPropagation();\n event.preventDefault();\n }}\n onClick={(event) => {\n event.stopPropagation();\n }}\n >\n <EllipsisVerticalIcon className=\"h-3 w-3\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n {menuContent}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n\n {!hideCloseButton && (\n <button\n type=\"button\"\n aria-label=\"Close tab\"\n className=\"hover:bg-primary/10 focus-visible:bg-primary/10 focus-visible:ring-primary absolute right-1 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded p-1 opacity-0 outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-0 group-hover:opacity-100\"\n onMouseDown={(event) => {\n event.stopPropagation();\n event.preventDefault();\n }}\n onClick={(event) => {\n event.stopPropagation();\n event.preventDefault();\n onClose(tab.id);\n }}\n >\n <XIcon className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n// -----------------------------------------------------------------------------\n// Tab Menu Components (for use with renderTabMenu)\n// -----------------------------------------------------------------------------\n\ninterface TabStripMenuItemProps {\n children: React.ReactNode;\n onClick?: () => void;\n variant?: 'default' | 'destructive';\n className?: string;\n disabled?: boolean;\n}\n\n/**\n * A menu item for the tab's dropdown menu.\n */\nfunction TabStripMenuItem({\n children,\n onClick,\n variant = 'default',\n className,\n disabled,\n}: TabStripMenuItemProps) {\n return (\n <DropdownMenuItem\n disabled={disabled}\n onClick={(event) => {\n event.stopPropagation();\n onClick?.();\n }}\n className={cn(\n variant === 'destructive' && 'text-destructive focus:text-destructive',\n className,\n )}\n >\n {children}\n </DropdownMenuItem>\n );\n}\n\ninterface TabStripMenuSeparatorProps {\n className?: string;\n}\n\n/**\n * A separator for the tab's dropdown menu.\n */\nfunction TabStripMenuSeparator({className}: TabStripMenuSeparatorProps) {\n return <DropdownMenuSeparator className={className} />;\n}\n\ninterface TabStripSearchItemActionProps {\n icon: React.ReactNode;\n onClick?: () => void;\n 'aria-label': string;\n className?: string;\n}\n\n/**\n * An action button for search dropdown items.\n */\nfunction TabStripSearchItemAction({\n icon,\n onClick,\n 'aria-label': ariaLabel,\n className,\n}: TabStripSearchItemActionProps) {\n return (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label={ariaLabel}\n className={cn(\n 'text-muted-foreground hover:text-foreground flex h-4 w-4 cursor-pointer items-center justify-center rounded',\n className,\n )}\n onClick={(event) => {\n event.stopPropagation();\n onClick?.();\n }}\n >\n {icon}\n </span>\n );\n}\n\n/**\n * Renders the scrollable row of open tabs with drag-to-reorder support.\n */\nfunction TabStripTabs({className, tabClassName}: TabStripTabsProps) {\n const {\n openTabItems,\n editingTabId,\n scrollContainerRef,\n onOpenTabsChange,\n renderTabMenu,\n renderTabLabel,\n preventCloseLastTab,\n handleStartEditing,\n handleStopEditing,\n handleInlineRename,\n handleClose,\n } = useTabStripContext();\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5, // 5px movement before drag starts (allows clicks)\n },\n }),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const {active, over} = event;\n if (!over || active.id === over.id || !onOpenTabsChange) return;\n\n const oldIndex = openTabItems.findIndex((tab) => tab.id === active.id);\n const newIndex = openTabItems.findIndex((tab) => tab.id === over.id);\n\n if (oldIndex !== -1 && newIndex !== -1) {\n const newOrder = arrayMove(\n openTabItems.map((t) => t.id),\n oldIndex,\n newIndex,\n );\n onOpenTabsChange(newOrder);\n }\n };\n\n const tabIds = useMemo(() => openTabItems.map((t) => t.id), [openTabItems]);\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={DRAG_MODIFIERS}\n autoScroll={true}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={tabIds} strategy={horizontalListSortingStrategy}>\n <ScrollableRow\n className=\"h-full min-w-0 flex-1\"\n scrollRef={scrollContainerRef}\n scrollClassName={cn(\n 'flex h-full min-w-0 items-center gap-1 overflow-x-auto overflow-y-visible',\n 'py-1 pl-1 pr-1 scroll-pl-7 scroll-pr-7 [&::-webkit-scrollbar]:hidden',\n className,\n )}\n arrowVisibility=\"always\"\n arrowClassName=\"w-7\"\n arrowIconClassName=\"h-4 w-4 opacity-60\"\n >\n {openTabItems.map((tab) => (\n <SortableTab\n key={tab.id}\n tab={tab}\n tabClassName={tabClassName}\n editingTabId={editingTabId}\n hideCloseButton={preventCloseLastTab && openTabItems.length === 1}\n onClose={handleClose}\n onStartEditing={handleStartEditing}\n onStopEditing={handleStopEditing}\n onInlineRename={handleInlineRename}\n renderTabMenu={renderTabMenu}\n renderTabLabel={renderTabLabel}\n />\n ))}\n </ScrollableRow>\n </SortableContext>\n </DndContext>\n );\n}\n\ninterface TabStripSearchDropdownProps {\n className?: string;\n triggerClassName?: string;\n /** Whether to auto-focus the search input when dropdown opens. Defaults to true. */\n autoFocus?: boolean;\n /** Optional tooltip content for the trigger button. */\n tooltip?: React.ReactNode;\n /** Optional custom icon for the trigger button. */\n triggerIcon?: React.ReactNode;\n /** Message shown when there are no tabs at all. */\n emptyMessage?: React.ReactNode;\n /** Message shown when searching and there are no matching tabs. */\n searchEmptyMessage?: React.ReactNode;\n /** Label for the closed tabs group. */\n closedTabsLabel?: React.ReactNode;\n /** Sorting mode for search dropdown items. */\n sortSearchItems?: 'none' | 'recent';\n /** Optional accessor for tab recency timestamps. */\n getTabLastOpenedAt?: (tab: TabDescriptor) => number | undefined;\n}\n\n/**\n * Renders the dropdown with search for browsing tabs.\n * Shows open tabs first and closed tabs second (dimmed). When searching, shows all matching tabs.\n */\nfunction TabStripSearchDropdown({\n className,\n triggerClassName,\n autoFocus = true,\n tooltip,\n triggerIcon,\n emptyMessage = 'No tabs',\n searchEmptyMessage = 'No matching tabs',\n closedTabsLabel = 'Recently closed',\n sortSearchItems = 'recent',\n getTabLastOpenedAt,\n}: TabStripSearchDropdownProps) {\n const {\n openTabItems,\n search,\n setSearch,\n closedTabs,\n filteredTabs,\n closedTabIds,\n openTabs,\n preventCloseLastTab,\n onOpenTabsChange,\n onSelect,\n renderSearchItemActions,\n getLastOpenedAt,\n handleClose,\n } = useTabStripContext();\n\n const [isOpen, setIsOpen] = useState(false);\n\n const isSearching = search.trim().length > 0;\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (!open) {\n setSearch('');\n }\n };\n\n const handleTabClick = (tabId: string) => {\n if (closedTabIds.has(tabId)) {\n // Opening a closed tab: add to openTabs and select it\n onOpenTabsChange?.([...(openTabs ?? []), tabId]);\n onSelect?.(tabId);\n } else {\n // Already open: just select it\n onSelect?.(tabId);\n }\n setIsOpen(false);\n };\n\n const sortByRecency = (tabsToSort: TabDescriptor[]) => {\n if (sortSearchItems !== 'recent') {\n return tabsToSort;\n }\n\n const withIndex = tabsToSort.map((tab, index) => ({\n tab,\n index,\n ts: getTabLastOpenedAt?.(tab) ?? getLastOpenedAt(tab.id),\n }));\n\n return withIndex\n .slice()\n .sort((a, b) => {\n const aTs = a.ts ?? -1;\n const bTs = b.ts ?? -1;\n if (aTs === bTs) {\n return a.index - b.index;\n }\n return bTs - aTs;\n })\n .map((item) => item.tab);\n };\n\n const openTabsList = sortByRecency(openTabItems);\n const closedTabsList = sortByRecency(closedTabs);\n const hasAnyTabs = openTabsList.length + closedTabsList.length > 0;\n\n const filteredOpenTabs = sortByRecency(\n filteredTabs.filter((tab) => !closedTabIds.has(tab.id)),\n );\n const filteredClosedTabs = sortByRecency(\n filteredTabs.filter((tab) => closedTabIds.has(tab.id)),\n );\n\n const renderOpenTabActions = (tab: TabDescriptor) => {\n const disableClose = preventCloseLastTab && (openTabsList.length ?? 0) <= 1;\n return (\n <>\n {renderSearchItemActions?.(tab)}\n <TabStripSearchItemAction\n icon={<XIcon className=\"h-3 w-3\" />}\n aria-label={`Close ${tab.name}`}\n onClick={disableClose ? undefined : () => handleClose(tab.id)}\n className={cn(disableClose && 'pointer-events-none opacity-40')}\n />\n </>\n );\n };\n\n const triggerButton = (\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n aria-label=\"Browse tabs\"\n className={cn(\n 'hover:bg-primary/10 h-full flex-shrink-0',\n triggerClassName,\n )}\n >\n {triggerIcon ?? <ListCollapseIcon className=\"h-4 w-4\" />}\n </Button>\n </DropdownMenuTrigger>\n );\n\n return (\n <DropdownMenu open={isOpen} onOpenChange={handleOpenChange}>\n {tooltip ? (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{triggerButton}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : (\n triggerButton\n )}\n\n <DropdownMenuContent\n align=\"start\"\n onCloseAutoFocus={(event) => event.preventDefault()}\n className={cn(\n 'flex max-h-[400px] max-w-[240px] flex-col overflow-x-hidden',\n className,\n )}\n >\n <div className=\"flex flex-shrink-0 items-center gap-1 px-2\">\n <SearchIcon className=\"text-muted-foreground\" size={14} />\n <Input\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'ArrowDown' || event.key === 'Tab') {\n event.preventDefault();\n const firstItem = event.currentTarget\n .closest('[role=\"menu\"]')\n ?.querySelector<HTMLElement>(\n '[role=\"menuitem\"]:not([disabled])',\n );\n firstItem?.focus();\n } else {\n event.stopPropagation();\n }\n }}\n onKeyUp={(event) => event.stopPropagation()}\n className=\"border-none text-xs shadow-none focus-visible:ring-0\"\n placeholder=\"Search...\"\n aria-label=\"Search\"\n autoFocus={autoFocus}\n />\n </div>\n <DropdownMenuSeparator className=\"flex-shrink-0\" />\n\n <div className=\"overflow-y-auto overflow-x-hidden\">\n {isSearching ? (\n filteredTabs.length === 0 ? (\n <DropdownTabItems\n tabs={filteredTabs}\n emptyMessage={searchEmptyMessage}\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n />\n ) : (\n <>\n <DropdownTabItems\n tabs={filteredOpenTabs}\n onTabClick={handleTabClick}\n renderActions={renderOpenTabActions}\n />\n {filteredClosedTabs.length > 0 && (\n <>\n {filteredOpenTabs.length > 0 && <DropdownMenuSeparator />}\n <DropdownMenuLabel className=\"text-muted-foreground py-1 text-xs font-medium\">\n {closedTabsLabel}\n </DropdownMenuLabel>\n <DropdownTabItems\n tabs={filteredClosedTabs}\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n getItemClassName={() => 'text-muted-foreground'}\n />\n </>\n )}\n </>\n )\n ) : (\n <>\n {hasAnyTabs ? (\n <>\n <DropdownTabItems\n tabs={openTabsList}\n onTabClick={handleTabClick}\n renderActions={renderOpenTabActions}\n />\n {closedTabsList.length > 0 && (\n <>\n {openTabsList.length > 0 && <DropdownMenuSeparator />}\n <DropdownMenuLabel className=\"text-muted-foreground py-1 text-xs font-medium\">\n {closedTabsLabel}\n </DropdownMenuLabel>\n <DropdownTabItems\n tabs={closedTabsList}\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n getItemClassName={() => 'text-muted-foreground'}\n />\n </>\n )}\n </>\n ) : (\n <DropdownTabItems\n tabs={[]}\n emptyMessage={emptyMessage}\n onTabClick={handleTabClick}\n renderActions={renderSearchItemActions}\n />\n )}\n </>\n )}\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\ninterface DropdownTabItemsProps {\n tabs: TabDescriptor[];\n emptyMessage?: React.ReactNode;\n onTabClick?: (tabId: string) => void;\n renderActions?: (tab: TabDescriptor) => React.ReactNode;\n getItemClassName?: (tab: TabDescriptor) => string | undefined;\n}\n\nfunction DropdownTabItems({\n tabs,\n emptyMessage,\n onTabClick,\n renderActions,\n getItemClassName,\n}: DropdownTabItemsProps) {\n if (tabs.length === 0) {\n if (!emptyMessage) return null;\n return (\n <DropdownMenuLabel className=\"items-center justify-center text-xs\">\n {emptyMessage}\n </DropdownMenuLabel>\n );\n }\n\n return (\n <>\n {tabs.map((tab) => (\n <DropdownMenuItem\n key={tab.id}\n onClick={() => onTabClick?.(tab.id)}\n className={cn(\n 'flex h-7 cursor-pointer items-center justify-between truncate',\n getItemClassName?.(tab),\n )}\n >\n <span className=\"xs truncate pl-1\">{tab.name}</span>\n {renderActions && (\n <div className=\"flex items-center gap-2\">{renderActions(tab)}</div>\n )}\n </DropdownMenuItem>\n ))}\n </>\n );\n}\n\ninterface TabStripNewButtonProps {\n className?: string;\n /** Optional tooltip content for the button. */\n tooltip?: React.ReactNode;\n}\n\n/**\n * Renders a button to create a new tab.\n */\nfunction TabStripNewButton({className, tooltip}: TabStripNewButtonProps) {\n const {onCreate} = useTabStripContext();\n\n if (!onCreate) {\n return null;\n }\n\n const button = (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n aria-label=\"Create new tab\"\n onClick={() => onCreate()}\n className={cn('hover:bg-primary/10 h-full flex-shrink-0', className)}\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n );\n\n if (tooltip) {\n return (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n }\n\n return button;\n}\n\n// -----------------------------------------------------------------------------\n// Main Component\n// -----------------------------------------------------------------------------\n\nexport interface TabStripProps {\n className?: string;\n tabsListClassName?: string;\n children?: React.ReactNode;\n /** All available tabs. */\n tabs: TabDescriptor[];\n /** IDs of tabs that are currently open. */\n openTabs?: string[];\n /** ID of the currently selected tab. */\n selectedTabId?: string | null;\n /** If true, hides the close button when only one tab remains open. */\n preventCloseLastTab?: boolean;\n /** Called when a tab is closed (hidden, can be reopened). */\n onClose?: (tabId: string) => void;\n /** Called when the list of open tabs changes (open from dropdown or reorder). */\n onOpenTabsChange?: (tabIds: string[]) => void;\n /** Called when a tab is selected. */\n onSelect?: (tabId: string) => void;\n /** Called when a new tab should be created. */\n onCreate?: () => void;\n /** Called when a tab is renamed inline. */\n onRename?: (tabId: string, newName: string) => void;\n /** Render function for the tab's dropdown menu. Use TabStrip.MenuItem and TabStrip.MenuSeparator. */\n renderTabMenu?: (tab: TabDescriptor) => React.ReactNode;\n /** Render function for search dropdown item actions. Use TabStrip.SearchItemAction. */\n renderSearchItemActions?: (tab: TabDescriptor) => React.ReactNode;\n /** Render function for custom tab content. Receives the tab and returns the content to display. */\n renderTabLabel?: (tab: TabDescriptor) => React.ReactNode;\n}\n\n/**\n * A composable tab strip component with search dropdown and tab management.\n *\n * @example\n * // Default layout\n * <TabStrip\n * tabs={tabs}\n * openTabs={openTabs}\n * onClose={closeTab}\n * onOpen={openTab}\n * onCreate={createTab}\n * />\n *\n * @example\n * // Custom layout with subcomponents\n * <TabStrip tabs={tabs} openTabs={openTabs} onClose={closeTab}>\n * <TabStrip.Tabs className=\"flex-1\" />\n * <TabStrip.SearchDropdown />\n * <TabStrip.NewButton />\n * </TabStrip>\n */\nfunction TabStripRoot({\n className,\n tabsListClassName,\n children,\n tabs,\n openTabs,\n selectedTabId,\n preventCloseLastTab = false,\n onClose,\n onOpenTabsChange,\n onSelect,\n onCreate,\n onRename,\n renderTabMenu,\n renderSearchItemActions,\n renderTabLabel,\n}: TabStripProps) {\n const [search, setSearch] = useState('');\n const [editingTabId, setEditingTabId] = useState<string | null>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null!);\n const prevSelectedIdRef = useRef<string | null>(null);\n const prevOpenTabIdsRef = useRef<Set<string>>(new Set());\n const lastOpenedAtRef = useRef<Map<string, number>>(new Map());\n\n const openTabsSet = useMemo(() => new Set(openTabs), [openTabs]);\n\n // Build openTabItems in the order of openTabs (for drag-to-reorder)\n const openTabItems = useMemo(() => {\n const tabsById = new Map(tabs.map((tab) => [tab.id, tab]));\n return (openTabs ?? [])\n .map((id) => tabsById.get(id))\n .filter((tab): tab is TabDescriptor => tab !== undefined);\n }, [tabs, openTabs]);\n\n const closedTabs = useMemo(\n () => tabs.filter((tab) => !openTabsSet.has(tab.id)),\n [tabs, openTabsSet],\n );\n\n const closedTabIds = useMemo(\n () => new Set(closedTabs.map((tab) => tab.id)),\n [closedTabs],\n );\n\n const trimmedSearch = search.trim().toLowerCase();\n\n const filteredTabs = useMemo(\n () =>\n trimmedSearch\n ? tabs.filter((tab) => tab.name.toLowerCase().includes(trimmedSearch))\n : [],\n [tabs, trimmedSearch],\n );\n\n useEffect(() => {\n if (!selectedTabId) return;\n lastOpenedAtRef.current.set(selectedTabId, Date.now());\n }, [selectedTabId]);\n\n useEffect(() => {\n const ids = new Set(tabs.map((tab) => tab.id));\n const next = new Map<string, number>();\n for (const [id, ts] of lastOpenedAtRef.current.entries()) {\n if (ids.has(id)) {\n next.set(id, ts);\n }\n }\n lastOpenedAtRef.current = next;\n }, [tabs]);\n\n // Auto-scroll to selected tab\n useLayoutEffect(() => {\n if (!selectedTabId) return;\n if (prevSelectedIdRef.current === selectedTabId) return;\n prevSelectedIdRef.current = selectedTabId;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const isOpen = openTabItems.some((tab) => tab.id === selectedTabId);\n if (!isOpen) return;\n\n // Use queueMicrotask to defer scroll until after Radix UI updates the DOM\n queueMicrotask(() => {\n const activeTab = container.querySelector<HTMLElement>(\n '[data-state=\"active\"]',\n );\n if (!activeTab) return;\n\n activeTab.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest',\n });\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedTabId]);\n\n // Auto-scroll to newly added tab\n useLayoutEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Find newly added tabs (in openTabs but not in prevOpenTabIdsRef)\n const newTabIds = (openTabs ?? []).filter(\n (id) => !prevOpenTabIdsRef.current.has(id),\n );\n\n // Update ref for next comparison\n prevOpenTabIdsRef.current = new Set(openTabs);\n\n if (newTabIds.length > 0) {\n const now = Date.now();\n for (const id of newTabIds) {\n lastOpenedAtRef.current.set(id, now);\n }\n }\n\n // Skip scroll on initial render (when ref was empty, all tabs appear \"new\")\n if (newTabIds.length === (openTabs?.length ?? 0)) return;\n\n // If there are new tabs, scroll to the last one added\n if (newTabIds.length === 0) return;\n const newTabId = newTabIds[newTabIds.length - 1];\n\n queueMicrotask(() => {\n const newTabElement = container.querySelector<HTMLElement>(\n `[data-tab-id=\"${newTabId}\"]`,\n );\n if (!newTabElement) return;\n\n newTabElement.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest',\n });\n });\n }, [openTabs]);\n\n const handleInlineRename = (tabId: string, newName: string) => {\n if (!onRename) return;\n const tab = tabs.find((t) => t.id === tabId);\n const trimmed = newName.trim();\n if (!trimmed || trimmed === tab?.name) {\n setEditingTabId(null);\n return;\n }\n onRename(tabId, trimmed);\n setEditingTabId(null);\n };\n\n const handleStartEditing = (tabId: string) => {\n if (!onRename) return;\n setEditingTabId(tabId);\n };\n\n const handleStopEditing = () => {\n setEditingTabId(null);\n };\n\n const handleClose = (tabId: string) => {\n // If closing the selected tab, select the one to the left (or right if leftmost)\n if (selectedTabId === tabId && openTabItems.length > 1) {\n const closingIndex = openTabItems.findIndex((t) => t.id === tabId);\n // If closing the leftmost, select the next; otherwise select the previous\n const newIndex = closingIndex === 0 ? 1 : closingIndex - 1;\n const newSelectedId = openTabItems[newIndex]?.id;\n if (newSelectedId) {\n onSelect?.(newSelectedId);\n }\n }\n onClose?.(tabId);\n };\n\n const contextValue: TabStripContextValue = {\n openTabItems,\n closedTabs,\n closedTabIds,\n filteredTabs,\n editingTabId,\n search,\n scrollContainerRef,\n selectedTabId,\n openTabs,\n preventCloseLastTab,\n getLastOpenedAt: (tabId) => lastOpenedAtRef.current.get(tabId),\n onOpenTabsChange,\n onSelect,\n onCreate,\n onRename,\n renderTabMenu,\n renderSearchItemActions,\n renderTabLabel,\n setSearch,\n handleStartEditing,\n handleStopEditing,\n handleInlineRename,\n handleClose,\n };\n\n const handleValueChange = (value: string) => {\n onSelect?.(value);\n };\n\n return (\n <Tabs\n value={selectedTabId ?? undefined}\n onValueChange={handleValueChange}\n activationMode=\"manual\"\n className={cn('bg-muted w-full min-w-0', className)}\n >\n <TabStripContext.Provider value={contextValue}>\n <TabsList\n className={cn(\n 'flex h-9 w-full min-w-0 items-center justify-start gap-2 overflow-visible bg-transparent p-0',\n tabsListClassName,\n )}\n >\n {children ?? (\n <>\n <TabStripSearchDropdown />\n <TabStripTabs />\n <TabStripNewButton />\n </>\n )}\n </TabsList>\n </TabStripContext.Provider>\n </Tabs>\n );\n}\n\n// Attach subcomponents\nexport const TabStrip = Object.assign(TabStripRoot, {\n Tabs: TabStripTabs,\n SearchDropdown: TabStripSearchDropdown,\n NewButton: TabStripNewButton,\n MenuItem: TabStripMenuItem,\n MenuSeparator: TabStripMenuSeparator,\n SearchItemAction: TabStripSearchItemAction,\n});\n\nexport type {\n TabStripMenuItemProps,\n TabStripMenuSeparatorProps,\n TabStripNewButtonProps,\n TabStripSearchDropdownProps,\n TabStripSearchItemActionProps,\n TabStripTabsProps,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG;IACtD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG;IACtD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,QAAQ,wGAwDb,CAAC;AAGF,OAAO,EAAC,QAAQ,EAAC,CAAC"}
|
|
@@ -4,12 +4,23 @@ import { cn } from '../lib/utils';
|
|
|
4
4
|
const Textarea = React.forwardRef(({ className, autoResize = false, onInput, value, defaultValue, ...props }, ref) => {
|
|
5
5
|
const localRef = React.useRef(null);
|
|
6
6
|
React.useImperativeHandle(ref, () => localRef.current);
|
|
7
|
+
const [hasOverflow, setHasOverflow] = React.useState(false);
|
|
7
8
|
const resizeToFitContent = React.useCallback(() => {
|
|
8
9
|
const el = localRef.current;
|
|
9
10
|
if (!el || !autoResize)
|
|
10
11
|
return;
|
|
11
12
|
el.style.height = 'auto';
|
|
12
13
|
el.style.height = `${el.scrollHeight}px`;
|
|
14
|
+
// Check if content exceeds the max-height constraint
|
|
15
|
+
const computedStyle = window.getComputedStyle(el);
|
|
16
|
+
const maxHeight = computedStyle.maxHeight;
|
|
17
|
+
if (maxHeight && maxHeight !== 'none') {
|
|
18
|
+
const maxHeightValue = parseFloat(maxHeight);
|
|
19
|
+
setHasOverflow(el.scrollHeight > maxHeightValue);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
setHasOverflow(false);
|
|
23
|
+
}
|
|
13
24
|
}, [autoResize]);
|
|
14
25
|
React.useEffect(() => {
|
|
15
26
|
// Trigger on mount and whenever the controlled value changes
|
|
@@ -21,7 +32,7 @@ const Textarea = React.forwardRef(({ className, autoResize = false, onInput, val
|
|
|
21
32
|
if (onInput)
|
|
22
33
|
onInput(e);
|
|
23
34
|
};
|
|
24
|
-
return (_jsx("textarea", { className: cn('border-input placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-sm focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', autoResize ? 'overflow-y-hidden' : undefined, className), ref: localRef, onInput: handleInput, value: value, defaultValue: defaultValue, ...props }));
|
|
35
|
+
return (_jsx("textarea", { className: cn('border-input placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-sm focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', autoResize ? (hasOverflow ? 'overflow-y-auto' : 'overflow-y-hidden') : undefined, className), ref: localRef, onInput: handleInput, value: value, defaultValue: defaultValue, ...props }));
|
|
25
36
|
});
|
|
26
37
|
Textarea.displayName = 'Textarea';
|
|
27
38
|
export { Textarea };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAMhC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAC/B,CACE,EAAC,SAAS,EAAE,UAAU,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,KAAK,EAAC,EACvE,GAAG,EACH,EAAE;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAsB,IAAI,CAAC,CAAC;IAEzD,KAAK,CAAC,mBAAmB,CACvB,GAAG,EACH,GAAG,EAAE,CAAC,QAAQ,CAAC,OAA8B,CAC9C,CAAC;IAEF,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAChD,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU;YAAE,OAAO;QAC/B,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAMhC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAC/B,CACE,EAAC,SAAS,EAAE,UAAU,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,KAAK,EAAC,EACvE,GAAG,EACH,EAAE;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAsB,IAAI,CAAC,CAAC;IAEzD,KAAK,CAAC,mBAAmB,CACvB,GAAG,EACH,GAAG,EAAE,CAAC,QAAQ,CAAC,OAA8B,CAC9C,CAAC;IAEF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5D,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAChD,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU;YAAE,OAAO;QAC/B,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,IAAI,CAAC;QAEzC,qDAAqD;QACrD,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;QAC1C,IAAI,SAAS,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACtC,MAAM,cAAc,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YAC7C,cAAc,CAAC,EAAE,CAAC,YAAY,GAAG,cAAc,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,6DAA6D;QAC7D,kBAAkB,EAAE,CAAC;IACvB,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9C,MAAM,WAAW,GAAG,CAAC,CAAuC,EAAE,EAAE;QAC9D,IAAI,UAAU;YAAE,kBAAkB,EAAE,CAAC;QACrC,IAAI,OAAO;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,OAAO,CACL,mBACE,SAAS,EAAE,EAAE,CACX,2QAA2Q,EAC3Q,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,EAChF,SAAS,CACV,EACD,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,KACtB,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AACF,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC;AAElC,OAAO,EAAC,QAAQ,EAAC,CAAC","sourcesContent":["import * as React from 'react';\nimport {cn} from '../lib/utils';\n\ntype TextareaProps = React.ComponentProps<'textarea'> & {\n autoResize?: boolean;\n};\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {className, autoResize = false, onInput, value, defaultValue, ...props},\n ref,\n ) => {\n const localRef = React.useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(\n ref,\n () => localRef.current as HTMLTextAreaElement,\n );\n\n const [hasOverflow, setHasOverflow] = React.useState(false);\n\n const resizeToFitContent = React.useCallback(() => {\n const el = localRef.current;\n if (!el || !autoResize) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n\n // Check if content exceeds the max-height constraint\n const computedStyle = window.getComputedStyle(el);\n const maxHeight = computedStyle.maxHeight;\n if (maxHeight && maxHeight !== 'none') {\n const maxHeightValue = parseFloat(maxHeight);\n setHasOverflow(el.scrollHeight > maxHeightValue);\n } else {\n setHasOverflow(false);\n }\n }, [autoResize]);\n\n React.useEffect(() => {\n // Trigger on mount and whenever the controlled value changes\n resizeToFitContent();\n }, [resizeToFitContent, value, defaultValue]);\n\n const handleInput = (e: React.FormEvent<HTMLTextAreaElement>) => {\n if (autoResize) resizeToFitContent();\n if (onInput) onInput(e);\n };\n\n return (\n <textarea\n className={cn(\n 'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-sm focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n autoResize ? (hasOverflow ? 'overflow-y-auto' : 'overflow-y-hidden') : undefined,\n className,\n )}\n ref={localRef}\n onInput={handleInput}\n value={value}\n defaultValue={defaultValue}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = 'Textarea';\n\nexport {Textarea};\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export { Progress } from './components/progress';
|
|
|
32
32
|
export { RadioGroup, RadioGroupItem } from './components/radio-group';
|
|
33
33
|
export { ResizablePanelGroup, ResizablePanel, ResizableHandle, } from './components/resizable';
|
|
34
34
|
export { TabStrip, type TabDescriptor, type TabStripProps, } from './components/tab-strip';
|
|
35
|
+
export { ScrollableRow } from './components/scrollable-row';
|
|
35
36
|
export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, } from './components/select';
|
|
36
37
|
export { ScrollArea, ScrollBar } from './components/scroll-area';
|
|
37
38
|
export { Separator } from './components/separator';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export { Progress } from './components/progress';
|
|
|
33
33
|
export { RadioGroup, RadioGroupItem } from './components/radio-group';
|
|
34
34
|
export { ResizablePanelGroup, ResizablePanel, ResizableHandle, } from './components/resizable';
|
|
35
35
|
export { TabStrip, } from './components/tab-strip';
|
|
36
|
+
export { ScrollableRow } from './components/scrollable-row';
|
|
36
37
|
export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, } from './components/select';
|
|
37
38
|
export { ScrollArea, ScrollBar } from './components/scroll-area';
|
|
38
39
|
export { Separator } from './components/separator';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,aAAa;AACb,OAAO,EACL,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAC,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAAC,KAAK,EAAE,aAAa,EAAkB,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAC,MAAM,EAAE,cAAc,EAAmB,MAAM,qBAAqB,CAAC;AAE7E,OAAO,EAAC,QAAQ,EAAqB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAAC,SAAS,EAAC,MAAM,yBAAyB,CAAC;AAElD,OAAO,EACL,YAAY,EACZ,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,eAAe,EACf,WAAW,EACX,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AAEzC,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AAEzC,OAAO,EACL,OAAO,EACP,WAAW,EACX,cAAc,EACd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,QAAQ,GAGT,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAC,SAAS,EAAC,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EACL,KAAK,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAAC,OAAO,EAAC,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EACL,KAAK,EACL,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAGL,aAAa,EACb,aAAa,EACb,KAAK,EACL,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,OAAO,EAAC,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAC,WAAW,EAAE,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EAAC,MAAM,EAAE,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAC,UAAU,EAAuB,MAAM,0BAA0B,CAAC;AAE1E,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,EACd,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,IAAI,EAAoB,MAAM,mBAAmB,CAAC;AAE1D,QAAQ;AACR,OAAO,EAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAC,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EACL,wBAAwB,GAGzB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,aAAa,GAEd,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAC;AAEtE,YAAY;AACZ,OAAO,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAC/B,OAAO,EAAC,oBAAoB,EAAqB,MAAM,gBAAgB,CAAC;AAExE,kBAAkB;AAClB,OAAO,EAAC,sBAAsB,EAAC,MAAM,mBAAmB,CAAC;AAEzD,QAAQ;AACR,OAAO,EAAC,aAAa,EAAE,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAE/D,uBAAuB;AACvB,OAAO,EAAC,IAAI,EAAC,MAAM,sBAAsB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\n// Components\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from './components/accordion';\n\nexport {Alert, AlertTitle, AlertDescription} from './components/alert';\n\nexport {AspectRatio} from './components/aspect-ratio';\n\nexport {Badge, badgeVariants, type BadgeProps} from './components/badge';\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n} from './components/breadcrumb';\n\nexport {Button, buttonVariants, type ButtonProps} from './components/button';\n\nexport {Calendar, type CalendarProps} from './components/calendar';\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardDescription,\n CardContent,\n} from './components/card';\n\nexport {Checkbox} from './components/checkbox';\n\nexport {ComboboxDemo} from './components/combobox';\n\nexport {\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n} from './components/collapsible';\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n} from './components/command';\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n} from './components/context-menu';\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n} from './components/dialog';\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n DrawerHandle,\n} from './components/drawer';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n} from './components/dropdown-menu';\n\nexport {EditableText} from './components/editable-text';\n\nexport {ErrorBoundary} from './components/error-boundary';\n\nexport {ErrorPane} from './components/error-pane';\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n} from './components/form';\n\nexport {Input} from './components/input';\n\nexport {Label} from './components/label';\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarShortcut,\n} from './components/menu-bar';\n\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n} from './components/pagination';\n\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n PopoverAnchor,\n} from './components/popover';\n\nexport {ProgressModal} from './components/progress-modal';\n\nexport {Progress} from './components/progress';\n\nexport {RadioGroup, RadioGroupItem} from './components/radio-group';\n\nexport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from './components/resizable';\n\nexport {\n TabStrip,\n type TabDescriptor,\n type TabStripProps,\n} from './components/tab-strip';\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n} from './components/select';\n\nexport {ScrollArea, ScrollBar} from './components/scroll-area';\n\nexport {Separator} from './components/separator';\n\nexport {\n Sheet,\n SheetPortal,\n SheetOverlay,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n} from './components/sheet';\n\nexport {SkeletonPane} from './components/skeleton-pane';\n\nexport {Skeleton} from './components/skeleton';\n\nexport {Slider} from './components/slider';\n\nexport {SpinnerPane} from './components/spinner-pane';\n\nexport {Spinner} from './components/spinner';\n\nexport {Switch} from './components/switch';\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from './components/table';\n\nexport {Tabs, TabsList, TabsTrigger, TabsContent} from './components/tabs';\n\nexport {Textarea} from './components/textarea';\n\nexport {ThemeSwitch} from './components/theme-switch';\n\nexport {\n type ToastProps,\n type ToastActionElement,\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n} from './components/toast';\n\nexport {Toaster} from './components/toaster';\n\nexport {ToggleGroup, ToggleGroupItem} from './components/toggle-group';\n\nexport {Toggle, toggleVariants} from './components/toggle';\n\nexport {CopyButton, type CopyButtonProps} from './components/copy-button';\n\nexport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n TooltipProvider,\n} from './components/tooltip';\n\nexport {Tree, type TreeNodeData} from './components/tree';\n\n// Hooks\nexport {useToast, toast, reducer} from './hooks/use-toast';\n\nexport {\n useAspectRatioDimensions,\n type Dimensions,\n type UseAspectRatioDimensionsProps,\n} from './hooks/useAspectRatioDimensions';\n\nexport {\n useDisclosure,\n type UseDisclosureReturnValue,\n} from './hooks/useDisclosure';\n\nexport {useRelativeCoordinates} from './hooks/useRelativeCoordinates';\n\n// Utilities\nexport {cn} from './lib/utils';\nexport {resolveFontSizeClass, type FontSizeToken} from './lib/fontSize';\n\n// Tailwind preset\nexport {sqlroomsTailwindPreset} from './tailwind-preset';\n\n// Theme\nexport {ThemeProvider, useTheme} from './theme/theme-provider';\n\n// Re-export from Radix\nexport {Slot} from '@radix-ui/react-slot';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\n// Components\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from './components/accordion';\n\nexport {Alert, AlertTitle, AlertDescription} from './components/alert';\n\nexport {AspectRatio} from './components/aspect-ratio';\n\nexport {Badge, badgeVariants, type BadgeProps} from './components/badge';\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n} from './components/breadcrumb';\n\nexport {Button, buttonVariants, type ButtonProps} from './components/button';\n\nexport {Calendar, type CalendarProps} from './components/calendar';\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardDescription,\n CardContent,\n} from './components/card';\n\nexport {Checkbox} from './components/checkbox';\n\nexport {ComboboxDemo} from './components/combobox';\n\nexport {\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n} from './components/collapsible';\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n} from './components/command';\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n} from './components/context-menu';\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n} from './components/dialog';\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n DrawerHandle,\n} from './components/drawer';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n} from './components/dropdown-menu';\n\nexport {EditableText} from './components/editable-text';\n\nexport {ErrorBoundary} from './components/error-boundary';\n\nexport {ErrorPane} from './components/error-pane';\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n} from './components/form';\n\nexport {Input} from './components/input';\n\nexport {Label} from './components/label';\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarShortcut,\n} from './components/menu-bar';\n\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n} from './components/pagination';\n\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n PopoverAnchor,\n} from './components/popover';\n\nexport {ProgressModal} from './components/progress-modal';\n\nexport {Progress} from './components/progress';\n\nexport {RadioGroup, RadioGroupItem} from './components/radio-group';\n\nexport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from './components/resizable';\n\nexport {\n TabStrip,\n type TabDescriptor,\n type TabStripProps,\n} from './components/tab-strip';\n\nexport {ScrollableRow} from './components/scrollable-row';\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n} from './components/select';\n\nexport {ScrollArea, ScrollBar} from './components/scroll-area';\n\nexport {Separator} from './components/separator';\n\nexport {\n Sheet,\n SheetPortal,\n SheetOverlay,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n} from './components/sheet';\n\nexport {SkeletonPane} from './components/skeleton-pane';\n\nexport {Skeleton} from './components/skeleton';\n\nexport {Slider} from './components/slider';\n\nexport {SpinnerPane} from './components/spinner-pane';\n\nexport {Spinner} from './components/spinner';\n\nexport {Switch} from './components/switch';\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from './components/table';\n\nexport {Tabs, TabsList, TabsTrigger, TabsContent} from './components/tabs';\n\nexport {Textarea} from './components/textarea';\n\nexport {ThemeSwitch} from './components/theme-switch';\n\nexport {\n type ToastProps,\n type ToastActionElement,\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n} from './components/toast';\n\nexport {Toaster} from './components/toaster';\n\nexport {ToggleGroup, ToggleGroupItem} from './components/toggle-group';\n\nexport {Toggle, toggleVariants} from './components/toggle';\n\nexport {CopyButton, type CopyButtonProps} from './components/copy-button';\n\nexport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n TooltipProvider,\n} from './components/tooltip';\n\nexport {Tree, type TreeNodeData} from './components/tree';\n\n// Hooks\nexport {useToast, toast, reducer} from './hooks/use-toast';\n\nexport {\n useAspectRatioDimensions,\n type Dimensions,\n type UseAspectRatioDimensionsProps,\n} from './hooks/useAspectRatioDimensions';\n\nexport {\n useDisclosure,\n type UseDisclosureReturnValue,\n} from './hooks/useDisclosure';\n\nexport {useRelativeCoordinates} from './hooks/useRelativeCoordinates';\n\n// Utilities\nexport {cn} from './lib/utils';\nexport {resolveFontSizeClass, type FontSizeToken} from './lib/fontSize';\n\n// Tailwind preset\nexport {sqlroomsTailwindPreset} from './tailwind-preset';\n\n// Theme\nexport {ThemeProvider, useTheme} from './theme/theme-provider';\n\n// Re-export from Radix\nexport {Slot} from '@radix-ui/react-slot';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAQA;;;GAGG;AACH,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEzC;;;;;;GAMG;AACH,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AASF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAAgC,EAChC,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAqDpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,QAAQ,0BAOpB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useEffect, useState } from 'react';
|
|
2
|
+
import { createContext, useContext, useEffect, useLayoutEffect, useState, } from 'react';
|
|
3
3
|
const initialState = {
|
|
4
4
|
theme: 'system',
|
|
5
5
|
setTheme: () => null,
|
|
@@ -31,8 +31,22 @@ const ThemeProviderContext = createContext(initialState);
|
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
33
|
export function ThemeProvider({ children, defaultTheme = 'system', storageKey = 'sqlrooms-ui-theme', ...props }) {
|
|
34
|
-
const [theme, setTheme] = useState(() =>
|
|
35
|
-
|
|
34
|
+
const [theme, setTheme] = useState(() => {
|
|
35
|
+
if (typeof window === 'undefined')
|
|
36
|
+
return defaultTheme;
|
|
37
|
+
try {
|
|
38
|
+
return window.localStorage.getItem(storageKey) || defaultTheme;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return defaultTheme;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
// Apply theme class before paint to avoid a light-theme flash on initial load.
|
|
45
|
+
// (useLayoutEffect on the client, fall back to useEffect in non-DOM environments)
|
|
46
|
+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
47
|
+
useIsomorphicLayoutEffect(() => {
|
|
48
|
+
if (typeof window === 'undefined')
|
|
49
|
+
return;
|
|
36
50
|
const root = window.document.documentElement;
|
|
37
51
|
root.classList.remove('light', 'dark');
|
|
38
52
|
if (theme === 'system') {
|
|
@@ -48,7 +62,14 @@ export function ThemeProvider({ children, defaultTheme = 'system', storageKey =
|
|
|
48
62
|
const value = {
|
|
49
63
|
theme,
|
|
50
64
|
setTheme: (theme) => {
|
|
51
|
-
|
|
65
|
+
if (typeof window !== 'undefined') {
|
|
66
|
+
try {
|
|
67
|
+
window.localStorage.setItem(storageKey, theme);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// ignore (e.g. SSR, private mode, blocked storage)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
52
73
|
setTheme(theme);
|
|
53
74
|
},
|
|
54
75
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,eAAe,EACf,QAAQ,GACT,MAAM,OAAO,CAAC;AAgCf,MAAM,YAAY,GAAuB;IACvC,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;CACrB,CAAC;AAEF,MAAM,oBAAoB,GAAG,aAAa,CAAqB,YAAY,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAY,GAAG,QAAQ,EACvB,UAAU,GAAG,mBAAmB,EAChC,GAAG,KAAK,EACW;IACnB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAQ,GAAG,EAAE;QAC7C,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,YAAY,CAAC;QACvD,IAAI,CAAC;YACH,OAAQ,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAW,IAAI,YAAY,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,+EAA+E;IAC/E,kFAAkF;IAClF,MAAM,yBAAyB,GAC7B,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9D,yBAAyB,CAAC,GAAG,EAAE;QAC7B,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;QAE7C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAEvC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC;iBAClE,OAAO;gBACR,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,OAAO,CAAC;YAEZ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG;QACZ,KAAK;QACL,QAAQ,EAAE,CAAC,KAAY,EAAE,EAAE;YACzB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClC,IAAI,CAAC;oBACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBACjD,CAAC;gBAAC,MAAM,CAAC;oBACP,mDAAmD;gBACrD,CAAC;YACH,CAAC;YACD,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;IAEF,OAAO,CACL,KAAC,oBAAoB,CAAC,QAAQ,OAAK,KAAK,EAAE,KAAK,EAAE,KAAK,YACnD,QAAQ,GACqB,CACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAEjD,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAElE,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useState,\n} from 'react';\n\n/**\n * Available theme options\n * @typedef {'dark' | 'light' | 'system'} Theme\n */\ntype Theme = 'dark' | 'light' | 'system';\n\n/**\n * Props for the ThemeProvider component\n * @interface ThemeProviderProps\n * @property {React.ReactNode} children - Child components that will have access to the theme context\n * @property {Theme} [defaultTheme='system'] - Initial theme to use if none is stored\n * @property {string} [storageKey='sqlrooms-ui-theme'] - Local storage key to persist theme preference\n */\ntype ThemeProviderProps = {\n children: React.ReactNode;\n defaultTheme?: Theme;\n storageKey?: string;\n};\n\n/**\n * Theme context state\n * @interface ThemeProviderState\n * @property {Theme} theme - Current active theme\n * @property {(theme: Theme) => void} setTheme - Function to update the current theme\n */\ntype ThemeProviderState = {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n};\n\nconst initialState: ThemeProviderState = {\n theme: 'system',\n setTheme: () => null,\n};\n\nconst ThemeProviderContext = createContext<ThemeProviderState>(initialState);\n\n/**\n * ThemeProvider component that manages and provides theme context to its children.\n * Handles system theme detection and persistence of theme preference.\n *\n * @example\n * ```tsx\n * // Basic usage with default settings\n * function App() {\n * return (\n * <ThemeProvider>\n * <YourApp />\n * </ThemeProvider>\n * );\n * }\n *\n * // Custom default theme and storage key\n * function App() {\n * return (\n * <ThemeProvider defaultTheme=\"dark\" storageKey=\"my-app-theme\">\n * <YourApp />\n * </ThemeProvider>\n * );\n * }\n * ```\n */\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'sqlrooms-ui-theme',\n ...props\n}: ThemeProviderProps) {\n const [theme, setTheme] = useState<Theme>(() => {\n if (typeof window === 'undefined') return defaultTheme;\n try {\n return (window.localStorage.getItem(storageKey) as Theme) || defaultTheme;\n } catch {\n return defaultTheme;\n }\n });\n\n // Apply theme class before paint to avoid a light-theme flash on initial load.\n // (useLayoutEffect on the client, fall back to useEffect in non-DOM environments)\n const useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\n useIsomorphicLayoutEffect(() => {\n if (typeof window === 'undefined') return;\n const root = window.document.documentElement;\n\n root.classList.remove('light', 'dark');\n\n if (theme === 'system') {\n const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')\n .matches\n ? 'dark'\n : 'light';\n\n root.classList.add(systemTheme);\n return;\n }\n\n root.classList.add(theme);\n }, [theme]);\n\n const value = {\n theme,\n setTheme: (theme: Theme) => {\n if (typeof window !== 'undefined') {\n try {\n window.localStorage.setItem(storageKey, theme);\n } catch {\n // ignore (e.g. SSR, private mode, blocked storage)\n }\n }\n setTheme(theme);\n },\n };\n\n return (\n <ThemeProviderContext.Provider {...props} value={value}>\n {children}\n </ThemeProviderContext.Provider>\n );\n}\n\n/**\n * Hook to access the current theme and theme setter function.\n * Must be used within a ThemeProvider component.\n *\n * @example\n * ```tsx\n * import { Button } from '@sqlrooms/ui';\n *\n * function ThemeToggle() {\n * const { theme, setTheme } = useTheme();\n * const isDark = theme === 'dark';\n *\n * return (\n * <Button\n * variant=\"outline\"\n * size=\"sm\"\n * onClick={() => setTheme(isDark ? 'light' : 'dark')}\n * >\n * {isDark ? '☀️ Light' : '🌙 Dark'}\n * </Button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { ThemeSwitch } from '@sqlrooms/ui';\n *\n * function AppHeader() {\n * return (\n * <nav className=\"border-b\">\n * <div className=\"flex h-16 items-center px-4\">\n * <div className=\"ml-auto\">\n * <ThemeSwitch />\n * </div>\n * </div>\n * </nav>\n * );\n * }\n * ```\n *\n * @returns {ThemeProviderState} Object containing current theme and setTheme function\n * @throws {Error} If used outside of a ThemeProvider\n */\nexport const useTheme = () => {\n const context = useContext(ThemeProviderContext);\n\n if (context === undefined)\n throw new Error('useTheme must be used within a ThemeProvider');\n\n return context;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/ui",
|
|
3
|
-
"version": "0.27.0-rc.
|
|
3
|
+
"version": "0.27.0-rc.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"author": "SQLRooms Contributors",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"autoprefixer": "^10.4.20",
|
|
72
72
|
"tailwindcss": "^3.4.17"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "41dabd4b989c2c15d9aed822714aae869a31197e"
|
|
75
75
|
}
|