@sqlrooms/ui 0.29.0-rc.8 → 0.29.0-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/progress-modal.d.ts +2 -0
- package/dist/components/progress-modal.d.ts.map +1 -1
- package/dist/components/progress-modal.js +2 -2
- package/dist/components/progress-modal.js.map +1 -1
- package/dist/components/textarea.d.ts +3 -0
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +86 -10
- package/dist/components/textarea.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-modal.d.ts","sourceRoot":"","sources":["../../src/components/progress-modal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAWzB,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"progress-modal.d.ts","sourceRoot":"","sources":["../../src/components/progress-modal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAWzB,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAwDA,CAAC;AAEF,OAAO,EAAC,aAAa,EAAC,CAAC"}
|
|
@@ -4,8 +4,8 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, }
|
|
|
4
4
|
import { Progress } from './progress';
|
|
5
5
|
import { cn } from '../lib/utils';
|
|
6
6
|
const ProgressModal = (props) => {
|
|
7
|
-
const { className, isOpen, title, loadingStage, progress, indeterminate } = props;
|
|
8
|
-
return (_jsx(Dialog, { open: isOpen, onOpenChange: () => { }, children: _jsxs(DialogContent, { className: cn('rounded-md border-none focus:outline-hidden sm:max-w-[425px]', className), showCloseButton: false, children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: title ?? '' }) }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Progress, { value: progress, className: "h-2 w-full", indeterminate: indeterminate }), _jsxs(DialogDescription, { className: "text-muted-foreground flex justify-between text-sm", children: [_jsx("span", { className: "text-sm", children: loadingStage ?? '' }), progress ? _jsxs("span", { children: [progress, "%"] }) : null] })] })] }) }));
|
|
7
|
+
const { className, isOpen, title, loadingStage, progress, indeterminate, error, errorDetails, } = props;
|
|
8
|
+
return (_jsx(Dialog, { open: isOpen, onOpenChange: () => { }, children: _jsxs(DialogContent, { className: cn('rounded-md border-none focus:outline-hidden sm:max-w-[425px]', className), showCloseButton: false, children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: title ?? '' }) }), error ? (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(DialogDescription, { className: "text-destructive text-sm font-medium", children: loadingStage ?? 'Initialization failed' }), _jsx("p", { className: "text-muted-foreground text-sm", children: error }), errorDetails ? (_jsxs("details", { className: "text-muted-foreground text-sm", children: [_jsx("summary", { className: "hover:text-foreground cursor-pointer font-medium", children: "Details" }), _jsx("pre", { className: "bg-muted text-muted-foreground mt-2 max-h-40 overflow-auto rounded-md p-3 text-xs whitespace-pre-wrap", children: errorDetails })] })) : null] })) : (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Progress, { value: progress, className: "h-2 w-full", indeterminate: indeterminate }), _jsxs(DialogDescription, { className: "text-muted-foreground flex justify-between text-sm", children: [_jsx("span", { className: "text-sm", children: loadingStage ?? '' }), progress !== undefined ? _jsxs("span", { children: [progress, "%"] }) : null] })] }))] }) }));
|
|
9
9
|
};
|
|
10
10
|
export { ProgressModal };
|
|
11
11
|
//# sourceMappingURL=progress-modal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-modal.js","sourceRoot":"","sources":["../../src/components/progress-modal.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAEhC,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"progress-modal.js","sourceRoot":"","sources":["../../src/components/progress-modal.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAEhC,MAAM,aAAa,GASd,CAAC,KAAK,EAAE,EAAE;IACb,MAAM,EACJ,SAAS,EACT,MAAM,EACN,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,KAAK,EACL,YAAY,GACb,GAAG,KAAK,CAAC;IACV,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,YAC1C,MAAC,aAAa,IACZ,SAAS,EAAE,EAAE,CACX,8DAA8D,EAC9D,SAAS,CACV,EACD,eAAe,EAAE,KAAK,aAEtB,KAAC,YAAY,cACX,KAAC,WAAW,cAAE,KAAK,IAAI,EAAE,GAAe,GAC3B,EACd,KAAK,CAAC,CAAC,CAAC,CACP,eAAK,SAAS,EAAC,qBAAqB,aAClC,KAAC,iBAAiB,IAAC,SAAS,EAAC,sCAAsC,YAChE,YAAY,IAAI,uBAAuB,GACtB,EACpB,YAAG,SAAS,EAAC,+BAA+B,YAAE,KAAK,GAAK,EACvD,YAAY,CAAC,CAAC,CAAC,CACd,mBAAS,SAAS,EAAC,+BAA+B,aAChD,kBAAS,SAAS,EAAC,kDAAkD,wBAE3D,EACV,cAAK,SAAS,EAAC,uGAAuG,YACnH,YAAY,GACT,IACE,CACX,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,qBAAqB,aAClC,KAAC,QAAQ,IACP,KAAK,EAAE,QAAQ,EACf,SAAS,EAAC,YAAY,EACtB,aAAa,EAAE,aAAa,GAC5B,EACF,MAAC,iBAAiB,IAAC,SAAS,EAAC,oDAAoD,aAC/E,eAAM,SAAS,EAAC,SAAS,YAAE,YAAY,IAAI,EAAE,GAAQ,EACpD,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,2BAAO,QAAQ,SAAS,CAAC,CAAC,CAAC,IAAI,IACvC,IAChB,CACP,IACa,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAC,aAAa,EAAC,CAAC","sourcesContent":["'use client';\n\nimport {FC} from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from './dialog';\nimport {Progress} from './progress';\nimport {cn} from '../lib/utils';\n\nconst ProgressModal: FC<{\n className?: string;\n isOpen: boolean;\n title?: string;\n loadingStage?: string;\n progress?: number;\n indeterminate?: boolean;\n error?: string;\n errorDetails?: string;\n}> = (props) => {\n const {\n className,\n isOpen,\n title,\n loadingStage,\n progress,\n indeterminate,\n error,\n errorDetails,\n } = props;\n return (\n <Dialog open={isOpen} onOpenChange={() => {}}>\n <DialogContent\n className={cn(\n 'rounded-md border-none focus:outline-hidden sm:max-w-[425px]',\n className,\n )}\n showCloseButton={false}\n >\n <DialogHeader>\n <DialogTitle>{title ?? ''}</DialogTitle>\n </DialogHeader>\n {error ? (\n <div className=\"flex flex-col gap-3\">\n <DialogDescription className=\"text-destructive text-sm font-medium\">\n {loadingStage ?? 'Initialization failed'}\n </DialogDescription>\n <p className=\"text-muted-foreground text-sm\">{error}</p>\n {errorDetails ? (\n <details className=\"text-muted-foreground text-sm\">\n <summary className=\"hover:text-foreground cursor-pointer font-medium\">\n Details\n </summary>\n <pre className=\"bg-muted text-muted-foreground mt-2 max-h-40 overflow-auto rounded-md p-3 text-xs whitespace-pre-wrap\">\n {errorDetails}\n </pre>\n </details>\n ) : null}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n <Progress\n value={progress}\n className=\"h-2 w-full\"\n indeterminate={indeterminate}\n />\n <DialogDescription className=\"text-muted-foreground flex justify-between text-sm\">\n <span className=\"text-sm\">{loadingStage ?? ''}</span>\n {progress !== undefined ? <span>{progress}%</span> : null}\n </DialogDescription>\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nexport {ProgressModal};\n"]}
|
|
@@ -2,6 +2,9 @@ import * as React from 'react';
|
|
|
2
2
|
type TextareaProps = React.ComponentProps<'textarea'> & {
|
|
3
3
|
autoResize?: boolean;
|
|
4
4
|
};
|
|
5
|
+
/**
|
|
6
|
+
* Textarea component with optional auto-resize behavior.
|
|
7
|
+
*/
|
|
5
8
|
declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
|
|
6
9
|
export { Textarea };
|
|
7
10
|
//# sourceMappingURL=textarea.d.ts.map
|
|
@@ -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;
|
|
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;AAmHF;;GAEG;AACH,QAAA,MAAM,QAAQ,wGAoDb,CAAC;AAGF,OAAO,EAAC,QAAQ,EAAC,CAAC"}
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { cn } from '../lib/utils';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Uses layout effect in the browser and falls back to effect during SSR.
|
|
6
|
+
*/
|
|
7
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
|
|
8
|
+
/**
|
|
9
|
+
* Keeps a textarea height synchronized with its content and container width.
|
|
10
|
+
*
|
|
11
|
+
* The resize path is intentionally triggered from multiple sources (input,
|
|
12
|
+
* value changes, and width changes) and then deduped per frame.
|
|
13
|
+
*/
|
|
14
|
+
function useAutoResizeTextarea({ autoResize, textareaRef, value, defaultValue, }) {
|
|
7
15
|
const [hasOverflow, setHasOverflow] = React.useState(false);
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
const lastMeasuredWidthRef = React.useRef(0);
|
|
17
|
+
const resizeFrameRef = React.useRef(null);
|
|
18
|
+
const applyResizeToFitContent = React.useCallback(() => {
|
|
19
|
+
const el = textareaRef.current;
|
|
20
|
+
if (!el || !autoResize || typeof window === 'undefined')
|
|
11
21
|
return;
|
|
12
22
|
el.style.height = 'auto';
|
|
13
23
|
el.style.height = `${el.scrollHeight}px`;
|
|
14
|
-
// Check if content exceeds the max-height constraint
|
|
15
24
|
const computedStyle = window.getComputedStyle(el);
|
|
16
25
|
const maxHeight = computedStyle.maxHeight;
|
|
17
26
|
if (maxHeight && maxHeight !== 'none') {
|
|
@@ -21,11 +30,78 @@ const Textarea = React.forwardRef(({ className, autoResize = false, onInput, val
|
|
|
21
30
|
else {
|
|
22
31
|
setHasOverflow(false);
|
|
23
32
|
}
|
|
24
|
-
}, [autoResize]);
|
|
25
|
-
React.
|
|
26
|
-
|
|
33
|
+
}, [autoResize, textareaRef]);
|
|
34
|
+
const resizeToFitContent = React.useCallback(() => {
|
|
35
|
+
if (!autoResize || typeof window === 'undefined')
|
|
36
|
+
return;
|
|
37
|
+
// Keep input/effect-triggered resize paths for robustness, but collapse
|
|
38
|
+
// same-frame calls into one DOM measurement/write cycle.
|
|
39
|
+
if (resizeFrameRef.current !== null)
|
|
40
|
+
return;
|
|
41
|
+
resizeFrameRef.current = window.requestAnimationFrame(() => {
|
|
42
|
+
resizeFrameRef.current = null;
|
|
43
|
+
applyResizeToFitContent();
|
|
44
|
+
});
|
|
45
|
+
}, [autoResize, applyResizeToFitContent]);
|
|
46
|
+
useIsomorphicLayoutEffect(() => {
|
|
27
47
|
resizeToFitContent();
|
|
28
48
|
}, [resizeToFitContent, value, defaultValue]);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (!autoResize)
|
|
51
|
+
return;
|
|
52
|
+
const el = textareaRef.current;
|
|
53
|
+
if (!el || typeof window === 'undefined')
|
|
54
|
+
return;
|
|
55
|
+
// Re-measure after layout settles so hidden/collapsed mount states
|
|
56
|
+
// don't leave a stale oversized height.
|
|
57
|
+
resizeToFitContent();
|
|
58
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
lastMeasuredWidthRef.current = el.getBoundingClientRect().width;
|
|
62
|
+
const observer = new ResizeObserver((entries) => {
|
|
63
|
+
const entry = entries[0];
|
|
64
|
+
if (!entry)
|
|
65
|
+
return;
|
|
66
|
+
const nextWidth = entry.contentRect.width;
|
|
67
|
+
if (Math.abs(nextWidth - lastMeasuredWidthRef.current) < 1) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
lastMeasuredWidthRef.current = nextWidth;
|
|
71
|
+
resizeToFitContent();
|
|
72
|
+
});
|
|
73
|
+
observer.observe(el);
|
|
74
|
+
return () => {
|
|
75
|
+
observer.disconnect();
|
|
76
|
+
};
|
|
77
|
+
}, [autoResize, resizeToFitContent, textareaRef]);
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
if (typeof window === 'undefined')
|
|
80
|
+
return;
|
|
81
|
+
return () => {
|
|
82
|
+
if (resizeFrameRef.current !== null) {
|
|
83
|
+
window.cancelAnimationFrame(resizeFrameRef.current);
|
|
84
|
+
resizeFrameRef.current = null;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}, []);
|
|
88
|
+
return {
|
|
89
|
+
hasOverflow,
|
|
90
|
+
resizeToFitContent,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Textarea component with optional auto-resize behavior.
|
|
95
|
+
*/
|
|
96
|
+
const Textarea = React.forwardRef(({ className, autoResize = false, onInput, value, defaultValue, rows, ...props }, ref) => {
|
|
97
|
+
const localRef = React.useRef(null);
|
|
98
|
+
React.useImperativeHandle(ref, () => localRef.current);
|
|
99
|
+
const { hasOverflow, resizeToFitContent } = useAutoResizeTextarea({
|
|
100
|
+
autoResize,
|
|
101
|
+
textareaRef: localRef,
|
|
102
|
+
value,
|
|
103
|
+
defaultValue,
|
|
104
|
+
});
|
|
29
105
|
const handleInput = (e) => {
|
|
30
106
|
if (autoResize)
|
|
31
107
|
resizeToFitContent();
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport {cn} from '../lib/utils';\n\ntype TextareaProps = React.ComponentProps<'textarea'> & {\n autoResize?: boolean;\n};\n\n/**\n * Uses layout effect in the browser and falls back to effect during SSR.\n */\nconst useIsomorphicLayoutEffect =\n typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;\n\n/**\n * Keeps a textarea height synchronized with its content and container width.\n *\n * The resize path is intentionally triggered from multiple sources (input,\n * value changes, and width changes) and then deduped per frame.\n */\nfunction useAutoResizeTextarea({\n autoResize,\n textareaRef,\n value,\n defaultValue,\n}: {\n autoResize: boolean;\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n value: React.ComponentProps<'textarea'>['value'];\n defaultValue: React.ComponentProps<'textarea'>['defaultValue'];\n}) {\n const [hasOverflow, setHasOverflow] = React.useState(false);\n const lastMeasuredWidthRef = React.useRef<number>(0);\n const resizeFrameRef = React.useRef<number | null>(null);\n\n const applyResizeToFitContent = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el || !autoResize || typeof window === 'undefined') return;\n\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n\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, textareaRef]);\n\n const resizeToFitContent = React.useCallback(() => {\n if (!autoResize || typeof window === 'undefined') return;\n\n // Keep input/effect-triggered resize paths for robustness, but collapse\n // same-frame calls into one DOM measurement/write cycle.\n if (resizeFrameRef.current !== null) return;\n\n resizeFrameRef.current = window.requestAnimationFrame(() => {\n resizeFrameRef.current = null;\n applyResizeToFitContent();\n });\n }, [autoResize, applyResizeToFitContent]);\n\n useIsomorphicLayoutEffect(() => {\n resizeToFitContent();\n }, [resizeToFitContent, value, defaultValue]);\n\n React.useEffect(() => {\n if (!autoResize) return;\n\n const el = textareaRef.current;\n if (!el || typeof window === 'undefined') return;\n\n // Re-measure after layout settles so hidden/collapsed mount states\n // don't leave a stale oversized height.\n resizeToFitContent();\n\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n lastMeasuredWidthRef.current = el.getBoundingClientRect().width;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (!entry) return;\n\n const nextWidth = entry.contentRect.width;\n if (Math.abs(nextWidth - lastMeasuredWidthRef.current) < 1) {\n return;\n }\n\n lastMeasuredWidthRef.current = nextWidth;\n resizeToFitContent();\n });\n\n observer.observe(el);\n\n return () => {\n observer.disconnect();\n };\n }, [autoResize, resizeToFitContent, textareaRef]);\n\n React.useEffect(() => {\n if (typeof window === 'undefined') return;\n\n return () => {\n if (resizeFrameRef.current !== null) {\n window.cancelAnimationFrame(resizeFrameRef.current);\n resizeFrameRef.current = null;\n }\n };\n }, []);\n\n return {\n hasOverflow,\n resizeToFitContent,\n };\n}\n\n/**\n * Textarea component with optional auto-resize behavior.\n */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n className,\n autoResize = false,\n onInput,\n value,\n defaultValue,\n rows,\n ...props\n },\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, resizeToFitContent} = useAutoResizeTextarea({\n autoResize,\n textareaRef: localRef,\n value,\n defaultValue,\n });\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:ring-1 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n autoResize\n ? hasOverflow\n ? 'overflow-y-auto'\n : 'overflow-y-hidden'\n : undefined,\n className,\n )}\n rows={rows ?? (autoResize ? 1 : undefined)}\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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/ui",
|
|
3
|
-
"version": "0.29.0-rc.
|
|
3
|
+
"version": "0.29.0-rc.9",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/sqlrooms/sqlrooms.git"
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"publishConfig": {
|
|
72
72
|
"access": "public"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "4a477560c0a6509ca00076d74eb3ce8f581c9e4f"
|
|
75
75
|
}
|