@scaleflex/ui-tw 0.0.148 → 0.0.149

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.
@@ -3,7 +3,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  import { Button } from '@scaleflex/ui-tw/button';
5
5
  import { ColorPalette } from '@scaleflex/ui-tw/color-palette';
6
- import { Dialog, DialogFormBody, DialogFormContent, DialogFormFooter, DialogFormHeader, DialogFormIcon, DialogFormTitle, DialogTrigger } from '@scaleflex/ui-tw/dialog';
6
+ import { Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogIcon, DialogTitle, DialogTrigger } from '@scaleflex/ui-tw/dialog';
7
7
  import { inputVariants } from '@scaleflex/ui-tw/input';
8
8
  import { getBaseInputClasses, readOnlyClassNames, selectionHighlightClassNames } from '@scaleflex/ui-tw/styles/shared-classes';
9
9
  import { cn } from '@scaleflex/ui-tw/utils/cn';
@@ -73,10 +73,11 @@ function ColorPicker(_ref) {
73
73
  backgroundColor: value
74
74
  },
75
75
  "aria-label": "Open color picker"
76
- })), /*#__PURE__*/React.createElement(DialogFormContent, {
76
+ })), /*#__PURE__*/React.createElement(DialogContent, {
77
+ variant: "centered",
77
78
  className: cn('w-[316px]', className),
78
79
  overlayClassName: overlayClassName
79
- }, /*#__PURE__*/React.createElement(DialogFormHeader, null, /*#__PURE__*/React.createElement(DialogFormIcon, null, /*#__PURE__*/React.createElement(PaletteIcon, null)), /*#__PURE__*/React.createElement(DialogFormTitle, null, title || 'Pick color')), /*#__PURE__*/React.createElement(DialogFormBody, {
80
+ }, /*#__PURE__*/React.createElement(DialogHeader, null, /*#__PURE__*/React.createElement(DialogIcon, null, /*#__PURE__*/React.createElement(PaletteIcon, null)), /*#__PURE__*/React.createElement(DialogTitle, null, title || 'Pick color')), /*#__PURE__*/React.createElement(DialogBody, {
80
81
  className: "space-y-4"
81
82
  }, /*#__PURE__*/React.createElement(HexColorPicker, {
82
83
  color: tempValue,
@@ -100,7 +101,7 @@ function ColorPicker(_ref) {
100
101
  value: tempValue,
101
102
  colors: presetColors,
102
103
  onSelect: setTempValue
103
- })), /*#__PURE__*/React.createElement(DialogFormFooter, null, /*#__PURE__*/React.createElement(DialogTrigger, {
104
+ })), /*#__PURE__*/React.createElement(DialogFooter, null, /*#__PURE__*/React.createElement(DialogTrigger, {
104
105
  asChild: true
105
106
  }, /*#__PURE__*/React.createElement(Button, {
106
107
  variant: "outline",
@@ -16,7 +16,7 @@ var _excluded = ["className"],
16
16
  import { ButtonVariant, buttonVariants } from '@scaleflex/ui-tw/button';
17
17
  import { getIconSizeInRem } from '@scaleflex/ui-tw/button/button.utils';
18
18
  import { Checkbox } from '@scaleflex/ui-tw/checkbox';
19
- import { Dialog, DialogFormDescription, DialogFormHeader, DialogFormTitle, DialogWideContent } from '@scaleflex/ui-tw/dialog';
19
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@scaleflex/ui-tw/dialog';
20
20
  import { LabelIcon } from '@scaleflex/ui-tw/label/components/label-icon';
21
21
  import { crossSizeOptions } from '@scaleflex/ui-tw/search/search.constants';
22
22
  import { SelectIcon } from '@scaleflex/ui-tw/select/components/select-icon';
@@ -46,11 +46,12 @@ function CommandDialog(_ref2) {
46
46
  description = _ref2$description === void 0 ? 'Search for a command to run...' : _ref2$description,
47
47
  children = _ref2.children,
48
48
  props = _objectWithoutProperties(_ref2, _excluded2);
49
- return /*#__PURE__*/React.createElement(Dialog, props, /*#__PURE__*/React.createElement(DialogFormHeader, {
50
- className: "sr-only"
51
- }, /*#__PURE__*/React.createElement(DialogFormTitle, null, title), /*#__PURE__*/React.createElement(DialogFormDescription, null, description)), /*#__PURE__*/React.createElement(DialogWideContent, {
49
+ return /*#__PURE__*/React.createElement(Dialog, props, /*#__PURE__*/React.createElement(DialogContent, {
50
+ maxWidth: "5xl",
52
51
  className: "overflow-hidden p-0"
53
- }, /*#__PURE__*/React.createElement(Command, {
52
+ }, /*#__PURE__*/React.createElement(DialogHeader, {
53
+ className: "sr-only"
54
+ }, /*#__PURE__*/React.createElement(DialogTitle, null, title), /*#__PURE__*/React.createElement(DialogDescription, null, description)), /*#__PURE__*/React.createElement(Command, {
54
55
  className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
55
56
  }, children)));
56
57
  }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { ConfirmDialogProps } from './confirm-dialog.types';
3
+ declare function ConfirmDialog({ open, onOpenChange, title, description, body, variant, confirmLabel, cancelLabel, onConfirm, onCancel, }: ConfirmDialogProps): React.JSX.Element;
4
+ export { ConfirmDialog };
@@ -0,0 +1,44 @@
1
+ import { Button } from '@scaleflex/ui-tw/button';
2
+ import { Dialog, DialogBody, DialogContent, DialogDescription, DialogErrorIcon, DialogFooter, DialogHeader, DialogTitle, DialogWarningIcon } from '@scaleflex/ui-tw/dialog';
3
+ import React from 'react';
4
+ function ConfirmDialog(_ref) {
5
+ var open = _ref.open,
6
+ onOpenChange = _ref.onOpenChange,
7
+ title = _ref.title,
8
+ description = _ref.description,
9
+ body = _ref.body,
10
+ _ref$variant = _ref.variant,
11
+ variant = _ref$variant === void 0 ? 'warning' : _ref$variant,
12
+ _ref$confirmLabel = _ref.confirmLabel,
13
+ confirmLabel = _ref$confirmLabel === void 0 ? 'Confirm' : _ref$confirmLabel,
14
+ _ref$cancelLabel = _ref.cancelLabel,
15
+ cancelLabel = _ref$cancelLabel === void 0 ? 'Cancel' : _ref$cancelLabel,
16
+ onConfirm = _ref.onConfirm,
17
+ onCancel = _ref.onCancel;
18
+ var handleCancel = function handleCancel() {
19
+ onCancel === null || onCancel === void 0 || onCancel();
20
+ onOpenChange === null || onOpenChange === void 0 || onOpenChange(false);
21
+ };
22
+ var handleConfirm = function handleConfirm() {
23
+ onConfirm === null || onConfirm === void 0 || onConfirm();
24
+ onOpenChange === null || onOpenChange === void 0 || onOpenChange(false);
25
+ };
26
+ var buttonVariant = variant === 'destructive' ? 'error-primary' : variant === 'warning' ? 'warning-primary' : 'primary';
27
+ return /*#__PURE__*/React.createElement(Dialog, {
28
+ open: open,
29
+ onOpenChange: onOpenChange
30
+ }, /*#__PURE__*/React.createElement(DialogContent, {
31
+ variant: "centered"
32
+ }, /*#__PURE__*/React.createElement(DialogHeader, null, variant === 'destructive' && /*#__PURE__*/React.createElement(DialogErrorIcon, null), variant === 'warning' && /*#__PURE__*/React.createElement(DialogWarningIcon, null), /*#__PURE__*/React.createElement(DialogTitle, null, title), description && /*#__PURE__*/React.createElement(DialogDescription, null, description)), body && /*#__PURE__*/React.createElement(DialogBody, {
33
+ className: "text-center"
34
+ }, body), /*#__PURE__*/React.createElement(DialogFooter, null, /*#__PURE__*/React.createElement(Button, {
35
+ className: "flex-1",
36
+ variant: "outline",
37
+ onClick: handleCancel
38
+ }, cancelLabel), /*#__PURE__*/React.createElement(Button, {
39
+ className: "flex-1",
40
+ variant: buttonVariant,
41
+ onClick: handleConfirm
42
+ }, confirmLabel))));
43
+ }
44
+ export { ConfirmDialog };
@@ -0,0 +1,14 @@
1
+ import type React from 'react';
2
+ export type ConfirmDialogVariant = 'default' | 'warning' | 'destructive';
3
+ export interface ConfirmDialogProps {
4
+ open?: boolean;
5
+ onOpenChange?: (open: boolean) => void;
6
+ title: string;
7
+ description?: string;
8
+ body?: React.ReactNode;
9
+ variant?: ConfirmDialogVariant;
10
+ confirmLabel?: string;
11
+ cancelLabel?: string;
12
+ onConfirm?: () => void;
13
+ onCancel?: () => void;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export { ConfirmDialog } from './confirm-dialog.component';
2
+ export type { ConfirmDialogProps, ConfirmDialogVariant } from './confirm-dialog.types';
@@ -0,0 +1 @@
1
+ export { ConfirmDialog } from './confirm-dialog.component';
@@ -1,23 +1,46 @@
1
1
  import * as DialogPrimitive from '@radix-ui/react-dialog';
2
2
  import React, { type ComponentProps } from 'react';
3
- import type { DialogFormContentProps, DialogWideContentProps, DialogWideHeaderProps, DialogWideTitleProps } from './dialog.types';
3
+ import type { DialogContentProps, DialogHeaderProps, DialogTitleProps } from './dialog.types';
4
4
  declare function Dialog({ ...props }: ComponentProps<typeof DialogPrimitive.Root>): React.JSX.Element;
5
5
  declare function DialogTrigger({ ...props }: ComponentProps<typeof DialogPrimitive.Trigger>): React.JSX.Element;
6
6
  declare function DialogPortal({ ...props }: ComponentProps<typeof DialogPrimitive.Portal>): React.JSX.Element;
7
7
  declare function DialogClose({ ...props }: ComponentProps<typeof DialogPrimitive.Close>): React.JSX.Element;
8
8
  declare function DialogOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>): React.JSX.Element;
9
- declare function DialogWideContent({ className, children, overlayClassName, headerSize, maxWidth, ...props }: DialogWideContentProps): React.JSX.Element;
10
- declare function DialogFormContent({ className, children, overlayClassName, maxWidth, ...props }: DialogFormContentProps): React.JSX.Element;
11
- declare function DialogWideHeader({ className, size, ...props }: DialogWideHeaderProps): React.JSX.Element;
12
- declare function DialogFormHeader({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
13
- declare function DialogWideBody({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
14
- declare function DialogFormBody({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
15
- declare function DialogWideTitle({ className, size, align, ...props }: DialogWideTitleProps): React.JSX.Element;
16
- declare function DialogFormTitle({ className, ...props }: ComponentProps<typeof DialogPrimitive.Title>): React.JSX.Element;
17
- declare function DialogFormDescription({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>): React.JSX.Element;
18
- declare function DialogFormIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
19
- declare function DialogFormWarningIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
20
- declare function DialogFormErrorIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
21
- declare function DialogWideFooter({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
22
- declare function DialogFormFooter({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
23
- export { Dialog, DialogClose, DialogWideFooter, DialogOverlay, DialogPortal, DialogTrigger, DialogWideTitle, DialogWideHeader, DialogWideContent, DialogWideBody, DialogFormContent, DialogFormDescription, DialogFormIcon, DialogFormWarningIcon, DialogFormErrorIcon, DialogFormHeader, DialogFormTitle, DialogFormBody, DialogFormFooter, };
9
+ declare function DialogContent({ className, children, overlayClassName, variant, headerSize, maxWidth, ...props }: DialogContentProps): React.JSX.Element;
10
+ declare function DialogHeader({ className, size, ...props }: DialogHeaderProps): React.JSX.Element;
11
+ declare function DialogTitle({ className, size, align, ...props }: DialogTitleProps): React.JSX.Element;
12
+ declare function DialogDescription({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>): React.JSX.Element;
13
+ declare function DialogBody({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
14
+ declare function DialogFooter({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
15
+ declare function DialogIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
16
+ declare function DialogWarningIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
17
+ declare function DialogErrorIcon({ className, ...props }: ComponentProps<'div'>): React.JSX.Element;
18
+ /** @deprecated Use `<DialogContent>` (variant defaults to `'default'`) */
19
+ declare function DialogWideContent(props: DialogContentProps): React.JSX.Element;
20
+ /** @deprecated Use `<DialogContent variant="centered">` */
21
+ declare function DialogFormContent(props: DialogContentProps): React.JSX.Element;
22
+ /** @deprecated Use `<DialogHeader>` */
23
+ declare function DialogWideHeader(props: DialogHeaderProps): React.JSX.Element;
24
+ /** @deprecated Use `<DialogHeader>` inside `<DialogContent variant="centered">` */
25
+ declare function DialogFormHeader(props: ComponentProps<'div'>): React.JSX.Element;
26
+ /** @deprecated Use `<DialogTitle>` */
27
+ declare function DialogWideTitle(props: DialogTitleProps): React.JSX.Element;
28
+ /** @deprecated Use `<DialogTitle>` inside `<DialogContent variant="centered">` */
29
+ declare function DialogFormTitle(props: ComponentProps<typeof DialogPrimitive.Title>): React.JSX.Element;
30
+ /** @deprecated Use `<DialogDescription>` */
31
+ declare function DialogFormDescription(props: ComponentProps<typeof DialogPrimitive.Description>): React.JSX.Element;
32
+ /** @deprecated Use `<DialogBody>` */
33
+ declare function DialogWideBody(props: ComponentProps<'div'>): React.JSX.Element;
34
+ /** @deprecated Use `<DialogBody>` inside `<DialogContent variant="centered">` */
35
+ declare function DialogFormBody(props: ComponentProps<'div'>): React.JSX.Element;
36
+ /** @deprecated Use `<DialogFooter>` */
37
+ declare function DialogWideFooter(props: ComponentProps<'div'>): React.JSX.Element;
38
+ /** @deprecated Use `<DialogFooter>` inside `<DialogContent variant="centered">` */
39
+ declare function DialogFormFooter(props: ComponentProps<'div'>): React.JSX.Element;
40
+ /** @deprecated Use `<DialogIcon>` */
41
+ declare function DialogFormIcon(props: ComponentProps<'div'>): React.JSX.Element;
42
+ /** @deprecated Use `<DialogWarningIcon>` */
43
+ declare function DialogFormWarningIcon(props: ComponentProps<'div'>): React.JSX.Element;
44
+ /** @deprecated Use `<DialogErrorIcon>` */
45
+ declare function DialogFormErrorIcon(props: ComponentProps<'div'>): React.JSX.Element;
46
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogErrorIcon, DialogFooter, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWarningIcon, DialogFormBody, DialogFormContent, DialogFormDescription, DialogFormErrorIcon, DialogFormFooter, DialogFormHeader, DialogFormIcon, DialogFormTitle, DialogFormWarningIcon, DialogWideBody, DialogWideContent, DialogWideFooter, DialogWideHeader, DialogWideTitle, };
@@ -2,27 +2,39 @@ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProper
2
2
  import _objectDestructuringEmpty from "@babel/runtime/helpers/objectDestructuringEmpty";
3
3
  import _extends from "@babel/runtime/helpers/extends";
4
4
  var _excluded = ["className"],
5
- _excluded2 = ["className", "children", "overlayClassName", "headerSize", "maxWidth"],
6
- _excluded3 = ["className", "children", "overlayClassName", "maxWidth"],
7
- _excluded4 = ["className", "size"],
5
+ _excluded2 = ["className", "children", "overlayClassName", "variant", "headerSize", "maxWidth"],
6
+ _excluded3 = ["className", "size"],
7
+ _excluded4 = ["className", "size", "align"],
8
8
  _excluded5 = ["className"],
9
9
  _excluded6 = ["className"],
10
10
  _excluded7 = ["className"],
11
- _excluded8 = ["className", "size", "align"],
11
+ _excluded8 = ["className"],
12
12
  _excluded9 = ["className"],
13
- _excluded10 = ["className"],
14
- _excluded11 = ["className"],
15
- _excluded12 = ["className"],
16
- _excluded13 = ["className"],
17
- _excluded14 = ["className"],
18
- _excluded15 = ["className"];
13
+ _excluded10 = ["className"];
19
14
  import * as DialogPrimitive from '@radix-ui/react-dialog';
20
15
  import { Button } from '@scaleflex/ui-tw/button';
21
16
  import { focusRingClassNames } from '@scaleflex/ui-tw/styles/shared-classes';
22
17
  import { cn } from '@scaleflex/ui-tw/utils/cn';
23
18
  import { CircleAlertIcon, XIcon } from 'lucide-react';
24
- import React from 'react';
25
- import { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogWideHeaderVariants, dialogWideTitleVariants } from './dialog.constants';
19
+ import React, { createContext, useContext } from 'react';
20
+ import { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogHeaderDefaultVariants, dialogTitleDefaultVariants } from './dialog.constants';
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Context
24
+ // ---------------------------------------------------------------------------
25
+
26
+ var DialogVariantContext = /*#__PURE__*/createContext({
27
+ variant: 'default',
28
+ headerSize: 'md'
29
+ });
30
+ function useDialogVariant() {
31
+ return useContext(DialogVariantContext);
32
+ }
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Primitives (unchanged)
36
+ // ---------------------------------------------------------------------------
37
+
26
38
  function Dialog(_ref) {
27
39
  var props = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
28
40
  return /*#__PURE__*/React.createElement(DialogPrimitive.Root, _extends({
@@ -55,28 +67,41 @@ function DialogOverlay(_ref5) {
55
67
  className: cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50', className)
56
68
  }, props));
57
69
  }
58
- function DialogWideContent(_ref6) {
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Unified components
73
+ // ---------------------------------------------------------------------------
74
+
75
+ function DialogContent(_ref6) {
59
76
  var className = _ref6.className,
60
77
  children = _ref6.children,
61
78
  overlayClassName = _ref6.overlayClassName,
79
+ _ref6$variant = _ref6.variant,
80
+ variant = _ref6$variant === void 0 ? 'default' : _ref6$variant,
62
81
  _ref6$headerSize = _ref6.headerSize,
63
82
  headerSize = _ref6$headerSize === void 0 ? 'md' : _ref6$headerSize,
64
- _ref6$maxWidth = _ref6.maxWidth,
65
- maxWidth = _ref6$maxWidth === void 0 ? '2xl' : _ref6$maxWidth,
83
+ maxWidth = _ref6.maxWidth,
66
84
  props = _objectWithoutProperties(_ref6, _excluded2);
67
- return /*#__PURE__*/React.createElement(DialogPortal, {
85
+ var resolvedMaxWidth = maxWidth === 'none' ? undefined : maxWidth !== null && maxWidth !== void 0 ? maxWidth : variant === 'centered' ? 'md' : '4xl';
86
+ var isCentered = variant === 'centered';
87
+ return /*#__PURE__*/React.createElement(DialogVariantContext.Provider, {
88
+ value: {
89
+ variant: variant,
90
+ headerSize: headerSize
91
+ }
92
+ }, /*#__PURE__*/React.createElement(DialogPortal, {
68
93
  "data-slot": "dialog-portal"
69
94
  }, /*#__PURE__*/React.createElement(DialogOverlay, {
70
95
  className: overlayClassName
71
96
  }), /*#__PURE__*/React.createElement(DialogPrimitive.Content, _extends({
72
97
  "data-slot": "dialog-content",
73
- className: cn('bg-background text-foreground border-border fixed top-[50%] left-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200', 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', maxWidth && dialogContentWidthVariants({
74
- maxWidth: maxWidth
98
+ className: cn('bg-background text-foreground border-border fixed top-[50%] left-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200', 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', resolvedMaxWidth && dialogContentWidthVariants({
99
+ maxWidth: resolvedMaxWidth
75
100
  }), className)
76
101
  }, props), children, /*#__PURE__*/React.createElement(DialogPrimitive.Close, {
77
102
  "data-state": "open",
78
103
  asChild: true,
79
- className: cn('text-muted-foreground/70 hover:text-muted-foreground absolute right-3 cursor-pointer rounded-xs transition-opacity disabled:pointer-events-none', "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5", dialogCloseButtonPositionVariants({
104
+ className: cn('text-muted-foreground/70 hover:text-muted-foreground absolute right-3 cursor-pointer rounded-xs transition-opacity disabled:pointer-events-none', "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5", isCentered ? 'top-3' : dialogCloseButtonPositionVariants({
80
105
  headerSize: headerSize
81
106
  }), focusRingClassNames)
82
107
  }, /*#__PURE__*/React.createElement(Button, {
@@ -84,141 +109,221 @@ function DialogWideContent(_ref6) {
84
109
  size: "icon-sm"
85
110
  }, /*#__PURE__*/React.createElement(XIcon, null), /*#__PURE__*/React.createElement("span", {
86
111
  className: "sr-only"
87
- }, "Close")))));
112
+ }, "Close"))))));
88
113
  }
89
- function DialogFormContent(_ref7) {
114
+ function DialogHeader(_ref7) {
90
115
  var className = _ref7.className,
91
- children = _ref7.children,
92
- overlayClassName = _ref7.overlayClassName,
93
- _ref7$maxWidth = _ref7.maxWidth,
94
- maxWidth = _ref7$maxWidth === void 0 ? 'md' : _ref7$maxWidth,
116
+ size = _ref7.size,
95
117
  props = _objectWithoutProperties(_ref7, _excluded3);
96
- return /*#__PURE__*/React.createElement(DialogPortal, {
97
- "data-slot": "dialog-portal"
98
- }, /*#__PURE__*/React.createElement(DialogOverlay, {
99
- className: overlayClassName
100
- }), /*#__PURE__*/React.createElement(DialogPrimitive.Content, _extends({
101
- "data-slot": "dialog-content",
102
- className: cn('bg-background text-foreground border-border fixed top-[50%] left-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200', 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', maxWidth && dialogContentWidthVariants({
103
- maxWidth: maxWidth
118
+ var _useDialogVariant = useDialogVariant(),
119
+ variant = _useDialogVariant.variant,
120
+ headerSize = _useDialogVariant.headerSize;
121
+ var isCentered = variant === 'centered';
122
+ if (isCentered) {
123
+ return /*#__PURE__*/React.createElement("div", _extends({
124
+ "data-slot": "dialog-header",
125
+ className: cn('text-foreground flex flex-col items-center justify-center p-6 pt-8 text-center', className)
126
+ }, props));
127
+ }
128
+ var resolvedSize = size !== null && size !== void 0 ? size : headerSize;
129
+ return /*#__PURE__*/React.createElement("div", _extends({
130
+ "data-slot": "dialog-header",
131
+ className: cn(dialogHeaderDefaultVariants({
132
+ size: resolvedSize
104
133
  }), className)
105
- }, props), children, /*#__PURE__*/React.createElement(DialogPrimitive.Close, {
106
- "data-state": "open",
107
- asChild: true,
108
- className: cn('text-muted-foreground/70 hover:text-muted-foreground absolute top-3 right-3 cursor-pointer rounded-xs transition-opacity disabled:pointer-events-none', "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5", focusRingClassNames)
109
- }, /*#__PURE__*/React.createElement(Button, {
110
- variant: "ghost-secondary",
111
- size: "icon-sm"
112
- }, /*#__PURE__*/React.createElement(XIcon, null), /*#__PURE__*/React.createElement("span", {
113
- className: "sr-only"
114
- }, "Close")))));
134
+ }, props));
115
135
  }
116
- function DialogWideHeader(_ref8) {
136
+ function DialogTitle(_ref8) {
117
137
  var className = _ref8.className,
118
- _ref8$size = _ref8.size,
119
- size = _ref8$size === void 0 ? 'md' : _ref8$size,
138
+ size = _ref8.size,
139
+ align = _ref8.align,
120
140
  props = _objectWithoutProperties(_ref8, _excluded4);
121
- return /*#__PURE__*/React.createElement("div", _extends({
122
- "data-slot": "dialog-header",
123
- className: cn(dialogWideHeaderVariants({
124
- size: size
141
+ var _useDialogVariant2 = useDialogVariant(),
142
+ variant = _useDialogVariant2.variant,
143
+ headerSize = _useDialogVariant2.headerSize;
144
+ var isCentered = variant === 'centered';
145
+ if (isCentered) {
146
+ return /*#__PURE__*/React.createElement(DialogPrimitive.Title, _extends({
147
+ "data-slot": "dialog-title",
148
+ className: cn('text-foreground text-lg leading-7 font-medium', className)
149
+ }, props));
150
+ }
151
+ var resolvedSize = size !== null && size !== void 0 ? size : headerSize;
152
+ var resolvedAlign = align !== null && align !== void 0 ? align : 'center';
153
+ return /*#__PURE__*/React.createElement(DialogPrimitive.Title, _extends({
154
+ "data-slot": "dialog-title",
155
+ className: cn(dialogTitleDefaultVariants({
156
+ size: resolvedSize,
157
+ align: resolvedAlign
125
158
  }), className)
126
159
  }, props));
127
160
  }
128
- function DialogFormHeader(_ref9) {
161
+ function DialogDescription(_ref9) {
129
162
  var className = _ref9.className,
130
163
  props = _objectWithoutProperties(_ref9, _excluded5);
131
- return /*#__PURE__*/React.createElement("div", _extends({
132
- "data-slot": "dialog-header",
133
- className: cn('text-foreground flex flex-col items-center justify-center p-6 pt-8 text-center', className)
164
+ return /*#__PURE__*/React.createElement(DialogPrimitive.Description, _extends({
165
+ "data-slot": "dialog-description",
166
+ className: cn('text-muted-foreground text-sm', className)
134
167
  }, props));
135
168
  }
136
- function DialogWideBody(_ref10) {
169
+ function DialogBody(_ref10) {
137
170
  var className = _ref10.className,
138
171
  props = _objectWithoutProperties(_ref10, _excluded6);
172
+ var _useDialogVariant3 = useDialogVariant(),
173
+ variant = _useDialogVariant3.variant;
174
+ var isCentered = variant === 'centered';
139
175
  return /*#__PURE__*/React.createElement("div", _extends({
140
176
  "data-slot": "dialog-body",
141
- className: cn('p-6', className)
177
+ className: cn(isCentered ? 'px-6' : 'p-6', className)
142
178
  }, props));
143
179
  }
144
- function DialogFormBody(_ref11) {
180
+ function DialogFooter(_ref11) {
145
181
  var className = _ref11.className,
146
182
  props = _objectWithoutProperties(_ref11, _excluded7);
183
+ var _useDialogVariant4 = useDialogVariant(),
184
+ variant = _useDialogVariant4.variant;
185
+ var isCentered = variant === 'centered';
186
+ if (isCentered) {
187
+ return /*#__PURE__*/React.createElement("div", _extends({
188
+ "data-slot": "dialog-footer",
189
+ className: cn('flex justify-end gap-3 p-6', className)
190
+ }, props));
191
+ }
147
192
  return /*#__PURE__*/React.createElement("div", _extends({
148
- "data-slot": "dialog-body",
149
- className: cn('px-6', className)
193
+ "data-slot": "dialog-footer",
194
+ className: cn('border-border flex flex-col-reverse gap-3 border-t p-6 sm:flex-row sm:justify-end', className)
150
195
  }, props));
151
196
  }
152
- function DialogWideTitle(_ref12) {
197
+ function DialogIcon(_ref12) {
153
198
  var className = _ref12.className,
154
- _ref12$size = _ref12.size,
155
- size = _ref12$size === void 0 ? 'md' : _ref12$size,
156
- _ref12$align = _ref12.align,
157
- align = _ref12$align === void 0 ? 'center' : _ref12$align,
158
199
  props = _objectWithoutProperties(_ref12, _excluded8);
159
- return /*#__PURE__*/React.createElement(DialogPrimitive.Title, _extends({
160
- "data-slot": "dialog-title",
161
- className: cn(dialogWideTitleVariants({
162
- size: size,
163
- align: align
164
- }), className)
165
- }, props));
166
- }
167
- function DialogFormTitle(_ref13) {
168
- var className = _ref13.className,
169
- props = _objectWithoutProperties(_ref13, _excluded9);
170
- return /*#__PURE__*/React.createElement(DialogPrimitive.Title, _extends({
171
- "data-slot": "dialog-title",
172
- className: cn('text-foreground text-lg leading-7 font-medium', className)
173
- }, props));
174
- }
175
- function DialogFormDescription(_ref14) {
176
- var className = _ref14.className,
177
- props = _objectWithoutProperties(_ref14, _excluded10);
178
- return /*#__PURE__*/React.createElement(DialogPrimitive.Description, _extends({
179
- "data-slot": "dialog-description",
180
- className: cn('text-muted-foreground text-sm', className)
181
- }, props));
182
- }
183
- function DialogFormIcon(_ref15) {
184
- var className = _ref15.className,
185
- props = _objectWithoutProperties(_ref15, _excluded11);
186
200
  return /*#__PURE__*/React.createElement("div", _extends({
201
+ "data-slot": "dialog-icon",
187
202
  className: cn('bg-accent mb-2 flex h-16 w-16 items-center justify-center rounded-full', "[&_svg:not([class*='text-'])]:text-primary [&_svg:not([class*='size-'])]:size-9", className)
188
203
  }, props));
189
204
  }
190
- function DialogFormWarningIcon(_ref16) {
191
- var className = _ref16.className,
192
- props = _objectWithoutProperties(_ref16, _excluded12);
193
- return /*#__PURE__*/React.createElement(DialogFormIcon, _extends({
205
+ function DialogWarningIcon(_ref13) {
206
+ var className = _ref13.className,
207
+ props = _objectWithoutProperties(_ref13, _excluded9);
208
+ return /*#__PURE__*/React.createElement(DialogIcon, _extends({
194
209
  className: cn(className, 'bg-warning-10')
195
210
  }, props), /*#__PURE__*/React.createElement(CircleAlertIcon, {
196
211
  className: "text-warning"
197
212
  }));
198
213
  }
199
- function DialogFormErrorIcon(_ref17) {
200
- var className = _ref17.className,
201
- props = _objectWithoutProperties(_ref17, _excluded13);
202
- return /*#__PURE__*/React.createElement(DialogFormIcon, _extends({
214
+ function DialogErrorIcon(_ref14) {
215
+ var className = _ref14.className,
216
+ props = _objectWithoutProperties(_ref14, _excluded10);
217
+ return /*#__PURE__*/React.createElement(DialogIcon, _extends({
203
218
  className: cn(className, 'bg-destructive-10')
204
219
  }, props), /*#__PURE__*/React.createElement(CircleAlertIcon, {
205
220
  className: "text-destructive"
206
221
  }));
207
222
  }
208
- function DialogWideFooter(_ref18) {
209
- var className = _ref18.className,
210
- props = _objectWithoutProperties(_ref18, _excluded14);
211
- return /*#__PURE__*/React.createElement("div", _extends({
212
- "data-slot": "dialog-footer",
213
- className: cn('border-border flex flex-col-reverse gap-3 border-t p-6 sm:flex-row sm:justify-end', className)
214
- }, props));
223
+
224
+ // ---------------------------------------------------------------------------
225
+ // Deprecated wrappers
226
+ // ---------------------------------------------------------------------------
227
+
228
+ var warnedComponents = new Set();
229
+ function warnOnce(name, message) {
230
+ if (process.env.NODE_ENV !== 'production' && !warnedComponents.has(name)) {
231
+ warnedComponents.add(name);
232
+ console.warn("[Dialog] ".concat(name, " is deprecated. ").concat(message));
233
+ }
215
234
  }
216
- function DialogFormFooter(_ref19) {
217
- var className = _ref19.className,
218
- props = _objectWithoutProperties(_ref19, _excluded15);
219
- return /*#__PURE__*/React.createElement("div", _extends({
220
- "data-slot": "dialog-footer",
221
- className: cn('flex justify-end gap-3 p-6', className)
222
- }, props));
235
+
236
+ /** @deprecated Use `<DialogContent>` (variant defaults to `'default'`) */
237
+ function DialogWideContent(props) {
238
+ warnOnce('DialogWideContent', 'Use <DialogContent> instead.');
239
+ return /*#__PURE__*/React.createElement(DialogContent, _extends({
240
+ maxWidth: "5xl"
241
+ }, props, {
242
+ variant: "default"
243
+ }));
244
+ }
245
+
246
+ /** @deprecated Use `<DialogContent variant="centered">` */
247
+ function DialogFormContent(props) {
248
+ warnOnce('DialogFormContent', 'Use <DialogContent variant="centered"> instead.');
249
+ return /*#__PURE__*/React.createElement(DialogContent, _extends({}, props, {
250
+ variant: "centered"
251
+ }));
252
+ }
253
+
254
+ /** @deprecated Use `<DialogHeader>` */
255
+ function DialogWideHeader(props) {
256
+ warnOnce('DialogWideHeader', 'Use <DialogHeader> instead.');
257
+ return /*#__PURE__*/React.createElement(DialogHeader, props);
258
+ }
259
+
260
+ /** @deprecated Use `<DialogHeader>` inside `<DialogContent variant="centered">` */
261
+ function DialogFormHeader(props) {
262
+ warnOnce('DialogFormHeader', 'Use <DialogHeader> inside <DialogContent variant="centered"> instead.');
263
+ return /*#__PURE__*/React.createElement(DialogHeader, props);
264
+ }
265
+
266
+ /** @deprecated Use `<DialogTitle>` */
267
+ function DialogWideTitle(props) {
268
+ warnOnce('DialogWideTitle', 'Use <DialogTitle> instead.');
269
+ return /*#__PURE__*/React.createElement(DialogTitle, props);
270
+ }
271
+
272
+ /** @deprecated Use `<DialogTitle>` inside `<DialogContent variant="centered">` */
273
+ function DialogFormTitle(props) {
274
+ warnOnce('DialogFormTitle', 'Use <DialogTitle> inside <DialogContent variant="centered"> instead.');
275
+ return /*#__PURE__*/React.createElement(DialogTitle, props);
276
+ }
277
+
278
+ /** @deprecated Use `<DialogDescription>` */
279
+ function DialogFormDescription(props) {
280
+ warnOnce('DialogFormDescription', 'Use <DialogDescription> instead.');
281
+ return /*#__PURE__*/React.createElement(DialogDescription, props);
282
+ }
283
+
284
+ /** @deprecated Use `<DialogBody>` */
285
+ function DialogWideBody(props) {
286
+ warnOnce('DialogWideBody', 'Use <DialogBody> instead.');
287
+ return /*#__PURE__*/React.createElement(DialogBody, props);
288
+ }
289
+
290
+ /** @deprecated Use `<DialogBody>` inside `<DialogContent variant="centered">` */
291
+ function DialogFormBody(props) {
292
+ warnOnce('DialogFormBody', 'Use <DialogBody> inside <DialogContent variant="centered"> instead.');
293
+ return /*#__PURE__*/React.createElement(DialogBody, props);
294
+ }
295
+
296
+ /** @deprecated Use `<DialogFooter>` */
297
+ function DialogWideFooter(props) {
298
+ warnOnce('DialogWideFooter', 'Use <DialogFooter> instead.');
299
+ return /*#__PURE__*/React.createElement(DialogFooter, props);
300
+ }
301
+
302
+ /** @deprecated Use `<DialogFooter>` inside `<DialogContent variant="centered">` */
303
+ function DialogFormFooter(props) {
304
+ warnOnce('DialogFormFooter', 'Use <DialogFooter> inside <DialogContent variant="centered"> instead.');
305
+ return /*#__PURE__*/React.createElement(DialogFooter, props);
306
+ }
307
+
308
+ /** @deprecated Use `<DialogIcon>` */
309
+ function DialogFormIcon(props) {
310
+ warnOnce('DialogFormIcon', 'Use <DialogIcon> instead.');
311
+ return /*#__PURE__*/React.createElement(DialogIcon, props);
312
+ }
313
+
314
+ /** @deprecated Use `<DialogWarningIcon>` */
315
+ function DialogFormWarningIcon(props) {
316
+ warnOnce('DialogFormWarningIcon', 'Use <DialogWarningIcon> instead.');
317
+ return /*#__PURE__*/React.createElement(DialogWarningIcon, props);
318
+ }
319
+
320
+ /** @deprecated Use `<DialogErrorIcon>` */
321
+ function DialogFormErrorIcon(props) {
322
+ warnOnce('DialogFormErrorIcon', 'Use <DialogErrorIcon> instead.');
323
+ return /*#__PURE__*/React.createElement(DialogErrorIcon, props);
223
324
  }
224
- export { Dialog, DialogClose, DialogWideFooter, DialogOverlay, DialogPortal, DialogTrigger, DialogWideTitle, DialogWideHeader, DialogWideContent, DialogWideBody, DialogFormContent, DialogFormDescription, DialogFormIcon, DialogFormWarningIcon, DialogFormErrorIcon, DialogFormHeader, DialogFormTitle, DialogFormBody, DialogFormFooter };
325
+ export {
326
+ // Unified API
327
+ Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogErrorIcon, DialogFooter, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWarningIcon,
328
+ // Deprecated
329
+ DialogFormBody, DialogFormContent, DialogFormDescription, DialogFormErrorIcon, DialogFormFooter, DialogFormHeader, DialogFormIcon, DialogFormTitle, DialogFormWarningIcon, DialogWideBody, DialogWideContent, DialogWideFooter, DialogWideHeader, DialogWideTitle };
@@ -1,12 +1,21 @@
1
1
  export declare const dialogContentWidthVariants: (props?: ({
2
- maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | null | undefined;
2
+ maxWidth?: "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl" | "full" | null | undefined;
3
3
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
4
- export declare const dialogWideHeaderVariants: (props?: ({
4
+ export declare const dialogHeaderDefaultVariants: (props?: ({
5
5
  size?: "sm" | "md" | null | undefined;
6
6
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
7
  export declare const dialogCloseButtonPositionVariants: (props?: ({
8
8
  headerSize?: "sm" | "md" | null | undefined;
9
9
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
10
+ export declare const dialogTitleDefaultVariants: (props?: ({
11
+ size?: "sm" | "md" | null | undefined;
12
+ align?: "center" | "left" | null | undefined;
13
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
14
+ /** @deprecated Use `dialogHeaderDefaultVariants` instead */
15
+ export declare const dialogWideHeaderVariants: (props?: ({
16
+ size?: "sm" | "md" | null | undefined;
17
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
18
+ /** @deprecated Use `dialogTitleDefaultVariants` instead */
10
19
  export declare const dialogWideTitleVariants: (props?: ({
11
20
  size?: "sm" | "md" | null | undefined;
12
21
  align?: "center" | "left" | null | undefined;
@@ -2,16 +2,20 @@ import { cva } from 'class-variance-authority';
2
2
  export var dialogContentWidthVariants = cva('', {
3
3
  variants: {
4
4
  maxWidth: {
5
- sm: 'max-w-sm',
6
5
  md: 'max-w-md',
7
- lg: 'max-w-2xl',
8
- xl: 'max-w-4xl',
9
- '2xl': 'max-w-5xl',
6
+ lg: 'max-w-lg',
7
+ xl: 'max-w-xl',
8
+ '2xl': 'max-w-2xl',
9
+ '3xl': 'max-w-3xl',
10
+ '4xl': 'max-w-4xl',
11
+ '5xl': 'max-w-5xl',
12
+ '6xl': 'max-w-6xl',
13
+ '7xl': 'max-w-7xl',
10
14
  full: 'max-w-[calc(100%-2rem)]'
11
15
  }
12
16
  }
13
17
  });
14
- export var dialogWideHeaderVariants = cva('border-border text-foreground relative flex items-center border-b', {
18
+ export var dialogHeaderDefaultVariants = cva('border-border text-foreground relative flex items-center border-b', {
15
19
  variants: {
16
20
  size: {
17
21
  sm: 'h-14 justify-start py-3 pr-4 pl-6',
@@ -33,7 +37,7 @@ export var dialogCloseButtonPositionVariants = cva('', {
33
37
  headerSize: 'md'
34
38
  }
35
39
  });
36
- export var dialogWideTitleVariants = cva('', {
40
+ export var dialogTitleDefaultVariants = cva('', {
37
41
  variants: {
38
42
  size: {
39
43
  sm: 'text-base leading-6 font-normal',
@@ -48,4 +52,9 @@ export var dialogWideTitleVariants = cva('', {
48
52
  size: 'md',
49
53
  align: 'center'
50
54
  }
51
- });
55
+ });
56
+
57
+ /** @deprecated Use `dialogHeaderDefaultVariants` instead */
58
+ export var dialogWideHeaderVariants = dialogHeaderDefaultVariants;
59
+ /** @deprecated Use `dialogTitleDefaultVariants` instead */
60
+ export var dialogWideTitleVariants = dialogTitleDefaultVariants;
@@ -1,23 +1,32 @@
1
1
  import type * as DialogPrimitive from '@radix-ui/react-dialog';
2
2
  import type { ComponentProps } from 'react';
3
- export type DialogSize = 'sm' | 'md';
4
- export type DialogAlign = 'center' | 'left';
5
- export type DialogContentWidth = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
6
- export interface DialogWideContentProps extends ComponentProps<typeof DialogPrimitive.Content> {
3
+ export type DialogVariant = 'default' | 'centered';
4
+ export type DialogHeaderSize = 'sm' | 'md';
5
+ export type DialogTitleAlign = 'center' | 'left';
6
+ export type DialogContentWidth = 'none' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | 'full';
7
+ export interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content> {
7
8
  overlayClassName?: string;
8
- headerSize?: DialogSize;
9
- /** Preset max-width. Pass `undefined` to use className for custom width. */
9
+ variant?: DialogVariant;
10
+ headerSize?: DialogHeaderSize;
11
+ /** Preset max-width. Pass `'none'` to skip the preset and use className for custom width. */
10
12
  maxWidth?: DialogContentWidth;
11
13
  }
12
- export interface DialogFormContentProps extends ComponentProps<typeof DialogPrimitive.Content> {
13
- overlayClassName?: string;
14
- /** Preset max-width. Pass `undefined` to use className for custom width. */
15
- maxWidth?: DialogContentWidth;
16
- }
17
- export interface DialogWideHeaderProps extends ComponentProps<'div'> {
18
- size?: DialogSize;
14
+ export interface DialogHeaderProps extends ComponentProps<'div'> {
15
+ size?: DialogHeaderSize;
19
16
  }
20
- export interface DialogWideTitleProps extends ComponentProps<typeof DialogPrimitive.Title> {
21
- size?: DialogSize;
22
- align?: DialogAlign;
17
+ export interface DialogTitleProps extends ComponentProps<typeof DialogPrimitive.Title> {
18
+ size?: DialogHeaderSize;
19
+ align?: DialogTitleAlign;
23
20
  }
21
+ /** @deprecated Use `DialogHeaderSize` instead */
22
+ export type DialogSize = DialogHeaderSize;
23
+ /** @deprecated Use `DialogTitleAlign` instead */
24
+ export type DialogAlign = DialogTitleAlign;
25
+ /** @deprecated Use `DialogContentProps` instead */
26
+ export type DialogWideContentProps = DialogContentProps;
27
+ /** @deprecated Use `DialogContentProps` instead */
28
+ export type DialogFormContentProps = DialogContentProps;
29
+ /** @deprecated Use `DialogHeaderProps` instead */
30
+ export type DialogWideHeaderProps = DialogHeaderProps;
31
+ /** @deprecated Use `DialogTitleProps` instead */
32
+ export type DialogWideTitleProps = DialogTitleProps;
package/dialog/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { Dialog, DialogClose, DialogWideFooter, DialogOverlay, DialogPortal, DialogTrigger, DialogWideTitle, DialogWideHeader, DialogWideContent, DialogWideBody, DialogFormContent, DialogFormDescription, DialogFormIcon, DialogFormWarningIcon, DialogFormErrorIcon, DialogFormHeader, DialogFormTitle, DialogFormBody, DialogFormFooter, } from './dialog.component';
2
- export { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogWideHeaderVariants, dialogWideTitleVariants, } from './dialog.constants';
3
- export type { DialogAlign, DialogContentWidth, DialogFormContentProps, DialogSize, DialogWideContentProps, DialogWideHeaderProps, DialogWideTitleProps, } from './dialog.types';
1
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogErrorIcon, DialogFooter, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWarningIcon, DialogFormBody, DialogFormContent, DialogFormDescription, DialogFormErrorIcon, DialogFormFooter, DialogFormHeader, DialogFormIcon, DialogFormTitle, DialogFormWarningIcon, DialogWideBody, DialogWideContent, DialogWideFooter, DialogWideHeader, DialogWideTitle, } from './dialog.component';
2
+ export { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogHeaderDefaultVariants, dialogTitleDefaultVariants, dialogWideHeaderVariants, dialogWideTitleVariants, } from './dialog.constants';
3
+ export type { DialogAlign, DialogContentProps, DialogContentWidth, DialogFormContentProps, DialogHeaderProps, DialogHeaderSize, DialogSize, DialogTitleAlign, DialogTitleProps, DialogVariant, DialogWideContentProps, DialogWideHeaderProps, DialogWideTitleProps, } from './dialog.types';
package/dialog/index.js CHANGED
@@ -1,2 +1,6 @@
1
- export { Dialog, DialogClose, DialogWideFooter, DialogOverlay, DialogPortal, DialogTrigger, DialogWideTitle, DialogWideHeader, DialogWideContent, DialogWideBody, DialogFormContent, DialogFormDescription, DialogFormIcon, DialogFormWarningIcon, DialogFormErrorIcon, DialogFormHeader, DialogFormTitle, DialogFormBody, DialogFormFooter } from './dialog.component';
2
- export { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogWideHeaderVariants, dialogWideTitleVariants } from './dialog.constants';
1
+ export {
2
+ // Unified API
3
+ Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogErrorIcon, DialogFooter, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWarningIcon,
4
+ // Deprecated
5
+ DialogFormBody, DialogFormContent, DialogFormDescription, DialogFormErrorIcon, DialogFormFooter, DialogFormHeader, DialogFormIcon, DialogFormTitle, DialogFormWarningIcon, DialogWideBody, DialogWideContent, DialogWideFooter, DialogWideHeader, DialogWideTitle } from './dialog.component';
6
+ export { dialogCloseButtonPositionVariants, dialogContentWidthVariants, dialogHeaderDefaultVariants, dialogTitleDefaultVariants, dialogWideHeaderVariants, dialogWideTitleVariants } from './dialog.constants';
@@ -3,5 +3,5 @@ import type { InputProps } from './input.types';
3
3
  declare const inputVariants: (props?: ({
4
4
  size?: "sm" | "md" | "lg" | null | undefined;
5
5
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
- declare function Input({ className, wrapperClassName, type, size, disabled, readOnly, icon: Icon, suffix, clearable, onClear, value, ...props }: InputProps): React.JSX.Element;
6
+ declare function Input({ className, wrapperClassName, type, size, disabled, readOnly, icon: Icon, suffix, clearable, onClear, value, defaultValue, maxCharCount, onChange, ...props }: InputProps): React.JSX.Element;
7
7
  export { Input, inputVariants };
@@ -1,16 +1,17 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
- var _excluded = ["className", "wrapperClassName", "type", "size", "disabled", "readOnly", "icon", "suffix", "clearable", "onClear", "value"];
4
+ var _excluded = ["className", "wrapperClassName", "type", "size", "disabled", "readOnly", "icon", "suffix", "clearable", "onClear", "value", "defaultValue", "maxCharCount", "onChange"];
5
5
  import { buttonVariants } from '@scaleflex/ui-tw/button';
6
6
  import { ButtonVariant } from '@scaleflex/ui-tw/button/button.constants';
7
7
  import { getBaseInputClasses, readOnlyClassNames, selectionHighlightClassNames } from '@scaleflex/ui-tw/styles/shared-classes';
8
8
  import { FormSize } from '@scaleflex/ui-tw/types/form-size';
9
9
  import { cn } from '@scaleflex/ui-tw/utils/cn';
10
+ import { useCharCount } from '@scaleflex/ui-tw/utils/use-char-count';
10
11
  import { cva } from 'class-variance-authority';
11
12
  import { XIcon } from 'lucide-react';
12
13
  import React from 'react';
13
- import { InputType, inputClearButtonSizeOptions, inputClearablePaddingOptions, inputIconSizeOptions, inputSizeOptions, inputSuffixSizeOptions, inputWithIconSizeOptions } from './input.constants';
14
+ import { InputType, inputCharCountPaddingOptions, inputCharCountPositionOptions, inputCharCountWithClearPaddingOptions, inputCharCountWithClearPositionOptions, inputClearButtonSizeOptions, inputClearablePaddingOptions, inputIconSizeOptions, inputSizeOptions, inputSuffixSizeOptions, inputWithIconSizeOptions } from './input.constants';
14
15
  var inputVariants = cva('', {
15
16
  variants: {
16
17
  size: inputSizeOptions
@@ -60,21 +61,39 @@ function Input(_ref) {
60
61
  clearable = _ref$clearable === void 0 ? false : _ref$clearable,
61
62
  onClear = _ref.onClear,
62
63
  value = _ref.value,
64
+ defaultValue = _ref.defaultValue,
65
+ maxCharCount = _ref.maxCharCount,
66
+ onChange = _ref.onChange,
63
67
  props = _objectWithoutProperties(_ref, _excluded);
64
68
  var showClearButton = clearable && value && !readOnly && !disabled;
65
- var hasAddon = Icon || suffix || clearable;
69
+ var hasAddon = Icon || suffix || clearable || maxCharCount;
70
+ var _useCharCount = useCharCount({
71
+ value: value,
72
+ defaultValue: defaultValue,
73
+ maxCharCount: maxCharCount,
74
+ readOnly: readOnly,
75
+ onChange: onChange
76
+ }),
77
+ currentLength = _useCharCount.currentLength,
78
+ showCharCount = _useCharCount.showCharCount,
79
+ handleChange = _useCharCount.handleChange,
80
+ charCountColorClass = _useCharCount.charCountColorClass;
66
81
  var inputElement = /*#__PURE__*/React.createElement("input", _extends({
67
82
  type: type,
68
83
  "data-slot": "input",
69
84
  disabled: disabled,
70
85
  readOnly: readOnly,
71
86
  value: value,
87
+ defaultValue: defaultValue,
88
+ onChange: handleChange,
72
89
  className: cn.apply(void 0, ['flex w-full min-w-0'].concat(_toConsumableArray(getBaseInputClasses()), [readOnlyClassNames, selectionHighlightClassNames, inputVariants({
73
90
  size: size
74
- }), (Icon || suffix) && !clearable && inputWithIconVariants({
91
+ }), (Icon || suffix) && !clearable && !maxCharCount && inputWithIconVariants({
75
92
  size: size
76
- }), clearable && inputClearablePaddingOptions[size], className]))
77
- }, props));
93
+ }), maxCharCount && clearable && inputCharCountWithClearPaddingOptions[size], maxCharCount && !clearable && inputCharCountPaddingOptions[size], clearable && !maxCharCount && inputClearablePaddingOptions[size], className]))
94
+ }, props, maxCharCount !== undefined && maxCharCount > 0 && {
95
+ maxLength: maxCharCount
96
+ }));
78
97
  if (!hasAddon) {
79
98
  return inputElement;
80
99
  }
@@ -84,11 +103,13 @@ function Input(_ref) {
84
103
  className: cn(inputIconSizeVariants({
85
104
  size: size
86
105
  }), 'text-muted-foreground absolute top-1/2 -translate-y-1/2 transform', disabled && 'opacity-50')
87
- }), suffix && !showClearButton && /*#__PURE__*/React.createElement("span", {
106
+ }), suffix && !showCharCount && /*#__PURE__*/React.createElement("span", {
88
107
  className: cn(inputSuffixSizeVariants({
89
108
  size: size
90
109
  }), 'text-muted-foreground absolute top-1/2 -translate-y-1/2 transform', disabled && 'opacity-50')
91
- }, suffix), showClearButton && /*#__PURE__*/React.createElement("button", {
110
+ }, suffix), showCharCount && (!clearable || currentLength > 0) && /*#__PURE__*/React.createElement("span", {
111
+ className: cn('absolute top-1/2 -translate-y-1/2 transform', clearable ? inputCharCountWithClearPositionOptions[size] : inputCharCountPositionOptions[size], charCountColorClass, disabled && 'opacity-50')
112
+ }, currentLength, "/", maxCharCount), showClearButton && /*#__PURE__*/React.createElement("button", {
92
113
  type: "button",
93
114
  tabIndex: 0,
94
115
  onClick: onClear,
@@ -19,22 +19,42 @@ export declare const InputType: {
19
19
  readonly Number: "number";
20
20
  };
21
21
  export declare const inputIconSizeOptions: {
22
- sm: string;
23
- md: string;
24
- lg: string;
22
+ readonly sm: "right-2 size-3";
23
+ readonly md: "right-3 size-4";
24
+ readonly lg: "right-4 size-5";
25
25
  };
26
26
  export declare const inputSuffixSizeOptions: {
27
- sm: string;
28
- md: string;
29
- lg: string;
27
+ readonly sm: "right-2 text-xs";
28
+ readonly md: "right-3 text-sm";
29
+ readonly lg: "right-4 text-base";
30
30
  };
31
31
  export declare const inputWithIconSizeOptions: {
32
- sm: string;
33
- md: string;
34
- lg: string;
32
+ readonly sm: "pr-6";
33
+ readonly md: "pr-8";
34
+ readonly lg: "pr-10";
35
35
  };
36
36
  export declare const inputClearablePaddingOptions: {
37
- sm: string;
38
- md: string;
39
- lg: string;
37
+ readonly sm: "pr-9";
38
+ readonly md: "pr-11";
39
+ readonly lg: "pr-12";
40
+ };
41
+ export declare const inputCharCountPaddingOptions: {
42
+ readonly sm: "pr-12";
43
+ readonly md: "pr-14";
44
+ readonly lg: "pr-16";
45
+ };
46
+ export declare const inputCharCountPositionOptions: {
47
+ readonly sm: "right-2 text-xs";
48
+ readonly md: "right-3 text-xs";
49
+ readonly lg: "right-4 text-sm";
50
+ };
51
+ export declare const inputCharCountWithClearPositionOptions: {
52
+ readonly sm: "right-9 text-xs";
53
+ readonly md: "right-11 text-xs";
54
+ readonly lg: "right-12 text-sm";
55
+ };
56
+ export declare const inputCharCountWithClearPaddingOptions: {
57
+ readonly sm: "pr-18";
58
+ readonly md: "pr-22";
59
+ readonly lg: "pr-24";
40
60
  };
@@ -12,4 +12,8 @@ export var InputType = {
12
12
  export var inputIconSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'right-2 size-3'), FormSize.Md, 'right-3 size-4'), FormSize.Lg, 'right-4 size-5');
13
13
  export var inputSuffixSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'right-2 text-xs'), FormSize.Md, 'right-3 text-sm'), FormSize.Lg, 'right-4 text-base');
14
14
  export var inputWithIconSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-6'), FormSize.Md, 'pr-8'), FormSize.Lg, 'pr-10');
15
- export var inputClearablePaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-9'), FormSize.Md, 'pr-11'), FormSize.Lg, 'pr-12');
15
+ export var inputClearablePaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-9'), FormSize.Md, 'pr-11'), FormSize.Lg, 'pr-12');
16
+ export var inputCharCountPaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-12'), FormSize.Md, 'pr-14'), FormSize.Lg, 'pr-16');
17
+ export var inputCharCountPositionOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'right-2 text-xs'), FormSize.Md, 'right-3 text-xs'), FormSize.Lg, 'right-4 text-sm');
18
+ export var inputCharCountWithClearPositionOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'right-9 text-xs'), FormSize.Md, 'right-11 text-xs'), FormSize.Lg, 'right-12 text-sm');
19
+ export var inputCharCountWithClearPaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-18'), FormSize.Md, 'pr-22'), FormSize.Lg, 'pr-24');
@@ -9,4 +9,5 @@ export interface InputProps extends Omit<ComponentProps<'input'>, 'size'> {
9
9
  clearable?: boolean;
10
10
  onClear?: () => void;
11
11
  wrapperClassName?: string;
12
+ maxCharCount?: number;
12
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scaleflex/ui-tw",
3
- "version": "0.0.148",
3
+ "version": "0.0.149",
4
4
  "author": "scaleflex",
5
5
  "repository": "github:scaleflex/ui",
6
6
  "homepage": "https://github.com/scaleflex/ui/blob/master/README.md",
@@ -29,7 +29,7 @@
29
29
  "@radix-ui/react-switch": "^1.0.1",
30
30
  "@radix-ui/react-tabs": "^1.1.13",
31
31
  "@radix-ui/react-tooltip": "^1.2.6",
32
- "@scaleflex/icons-tw": "^0.0.148",
32
+ "@scaleflex/icons-tw": "^0.0.149",
33
33
  "@tanstack/react-table": "^8.21.3",
34
34
  "@types/lodash.merge": "^4.6.9",
35
35
  "class-variance-authority": "^0.7.1",
@@ -1,9 +1,10 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
3
  var _excluded = ["leftToolbar", "rightToolbar", "className", "onBlur"];
4
- import { textareaBottomActionAreaPadding, textareaWithActionsSizeOptions } from '@scaleflex/ui-tw/textarea/textarea.constants';
4
+ import { textareaBottomActionAreaPadding, textareaCharCountTextSizeOptions, textareaWithActionsSizeOptions } from '@scaleflex/ui-tw/textarea/textarea.constants';
5
5
  import { FormSize } from '@scaleflex/ui-tw/types/form-size';
6
6
  import { cn } from '@scaleflex/ui-tw/utils/cn';
7
+ import { useCharCount } from '@scaleflex/ui-tw/utils/use-char-count';
7
8
  import { cva } from 'class-variance-authority';
8
9
  import React, { useRef } from 'react';
9
10
  import { Textarea } from '../';
@@ -23,8 +24,25 @@ function TextareaWithActions(_ref) {
23
24
  textareaProps = _objectWithoutProperties(_ref, _excluded);
24
25
  var _ref2 = textareaProps || {},
25
26
  _ref2$size = _ref2.size,
26
- size = _ref2$size === void 0 ? FormSize.Md : _ref2$size;
27
+ size = _ref2$size === void 0 ? FormSize.Md : _ref2$size,
28
+ maxCharCount = _ref2.maxCharCount,
29
+ value = _ref2.value,
30
+ defaultValue = _ref2.defaultValue,
31
+ disabled = _ref2.disabled,
32
+ readOnly = _ref2.readOnly,
33
+ onChange = _ref2.onChange;
27
34
  var textareaRef = useRef(null);
35
+ var _useCharCount = useCharCount({
36
+ value: value,
37
+ defaultValue: defaultValue,
38
+ maxCharCount: maxCharCount,
39
+ readOnly: readOnly,
40
+ onChange: onChange
41
+ }),
42
+ currentLength = _useCharCount.currentLength,
43
+ showCharCount = _useCharCount.showCharCount,
44
+ handleChange = _useCharCount.handleChange,
45
+ charCountColorClass = _useCharCount.charCountColorClass;
28
46
  var handleActionClick = function handleActionClick(e) {
29
47
  var _textareaRef$current;
30
48
  e.preventDefault();
@@ -37,23 +55,30 @@ function TextareaWithActions(_ref) {
37
55
  }
38
56
  onBlur === null || onBlur === void 0 || onBlur(e);
39
57
  };
58
+ var hasBottomArea = leftToolbar || rightToolbar || showCharCount;
40
59
  return /*#__PURE__*/React.createElement("div", {
41
60
  className: "relative"
42
61
  }, /*#__PURE__*/React.createElement(Textarea, _extends({}, textareaProps, {
62
+ maxCharCount: undefined,
63
+ onChange: handleChange,
43
64
  className: cn(className, textareaWithActionsVariants({
44
65
  size: size
45
66
  })),
46
67
  ref: textareaRef,
47
68
  onBlur: handleBlur
48
- })), (leftToolbar || rightToolbar) && /*#__PURE__*/React.createElement("div", {
69
+ }, maxCharCount !== undefined && maxCharCount > 0 && {
70
+ maxLength: maxCharCount
71
+ })), hasBottomArea && /*#__PURE__*/React.createElement("div", {
49
72
  "data-action-area": "true",
50
73
  className: cn('bg-background absolute right-2.5 bottom-0.25 left-1.5', textareaBottomActionAreaPadding[size]),
51
74
  onClick: handleActionClick,
52
75
  tabIndex: -1
53
76
  }, leftToolbar && /*#__PURE__*/React.createElement("div", {
54
77
  className: "absolute bottom-1.5 left-0 flex items-center gap-0.5"
55
- }, leftToolbar), rightToolbar && /*#__PURE__*/React.createElement("div", {
78
+ }, leftToolbar), /*#__PURE__*/React.createElement("div", {
56
79
  className: "absolute right-0 bottom-1.5 flex items-center gap-0.5"
57
- }, rightToolbar)));
80
+ }, showCharCount && /*#__PURE__*/React.createElement("span", {
81
+ className: cn(textareaCharCountTextSizeOptions[size], rightToolbar && 'mr-1', charCountColorClass, disabled && 'opacity-50')
82
+ }, currentLength, "/", maxCharCount), rightToolbar)));
58
83
  }
59
84
  export { TextareaWithActions };
@@ -3,5 +3,5 @@ import type { TextareaProps } from './textarea.types';
3
3
  declare const textareaVariants: (props?: ({
4
4
  size?: "sm" | "md" | "lg" | null | undefined;
5
5
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
- declare function Textarea({ className, size, disabled, readOnly, clearable, onClear, value, ...props }: TextareaProps): React.JSX.Element;
6
+ declare function Textarea({ className, size, disabled, readOnly, clearable, onClear, value, defaultValue, maxCharCount, onChange, ...props }: TextareaProps): React.JSX.Element;
7
7
  export { Textarea, textareaVariants };
@@ -1,15 +1,16 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
- var _excluded = ["className", "size", "disabled", "readOnly", "clearable", "onClear", "value"];
3
+ var _excluded = ["className", "size", "disabled", "readOnly", "clearable", "onClear", "value", "defaultValue", "maxCharCount", "onChange"];
4
4
  import { buttonVariants } from '@scaleflex/ui-tw/button';
5
5
  import { ButtonVariant } from '@scaleflex/ui-tw/button/button.constants';
6
6
  import { focusRingClassNames, getBaseInputClasses, readOnlyClassNames, selectionHighlightClassNames } from '@scaleflex/ui-tw/styles/shared-classes';
7
7
  import { FormSize } from '@scaleflex/ui-tw/types/form-size';
8
8
  import { cn } from '@scaleflex/ui-tw/utils/cn';
9
+ import { useCharCount } from '@scaleflex/ui-tw/utils/use-char-count';
9
10
  import { cva } from 'class-variance-authority';
10
11
  import { XIcon } from 'lucide-react';
11
12
  import React from 'react';
12
- import { textareaClearButtonSizeOptions, textareaClearablePaddingOptions, textareaSizeOptions } from './textarea.constants';
13
+ import { textareaCharCountPaddingOptions, textareaCharCountPositionOptions, textareaClearButtonSizeOptions, textareaClearablePaddingOptions, textareaSizeOptions } from './textarea.constants';
13
14
  var textareaVariants = cva('', {
14
15
  variants: {
15
16
  size: textareaSizeOptions
@@ -30,23 +31,44 @@ function Textarea(_ref) {
30
31
  clearable = _ref$clearable === void 0 ? false : _ref$clearable,
31
32
  onClear = _ref.onClear,
32
33
  value = _ref.value,
34
+ defaultValue = _ref.defaultValue,
35
+ maxCharCount = _ref.maxCharCount,
36
+ onChange = _ref.onChange,
33
37
  props = _objectWithoutProperties(_ref, _excluded);
34
38
  var showClearButton = clearable && value && !readOnly && !disabled;
39
+ var hasAddon = clearable || maxCharCount;
40
+ var _useCharCount = useCharCount({
41
+ value: value,
42
+ defaultValue: defaultValue,
43
+ maxCharCount: maxCharCount,
44
+ readOnly: readOnly,
45
+ onChange: onChange
46
+ }),
47
+ currentLength = _useCharCount.currentLength,
48
+ showCharCount = _useCharCount.showCharCount,
49
+ handleChange = _useCharCount.handleChange,
50
+ charCountColorClass = _useCharCount.charCountColorClass;
35
51
  var textareaElement = /*#__PURE__*/React.createElement("textarea", _extends({
36
52
  "data-slot": "textarea",
37
53
  disabled: disabled,
38
54
  readOnly: readOnly,
39
55
  value: value,
56
+ defaultValue: defaultValue,
57
+ onChange: handleChange,
40
58
  className: cn('flex field-sizing-content w-full resize-y', getBaseInputClasses(), readOnlyClassNames, selectionHighlightClassNames, focusRingClassNames, textareaVariants({
41
59
  size: size
42
- }), clearable && textareaClearablePaddingOptions[size], clearable ? undefined : className)
43
- }, props));
44
- if (!clearable) {
60
+ }), maxCharCount && textareaCharCountPaddingOptions[size], clearable && textareaClearablePaddingOptions[size], hasAddon ? undefined : className)
61
+ }, props, maxCharCount !== undefined && maxCharCount > 0 && {
62
+ maxLength: maxCharCount
63
+ }));
64
+ if (!hasAddon) {
45
65
  return textareaElement;
46
66
  }
47
67
  return /*#__PURE__*/React.createElement("div", {
48
68
  className: cn('relative', className)
49
- }, textareaElement, showClearButton && /*#__PURE__*/React.createElement("button", {
69
+ }, textareaElement, showCharCount && (!clearable || currentLength > 0) && /*#__PURE__*/React.createElement("span", {
70
+ className: cn('absolute', textareaCharCountPositionOptions[size], charCountColorClass, disabled && 'opacity-50')
71
+ }, currentLength, "/", maxCharCount), showClearButton && /*#__PURE__*/React.createElement("button", {
50
72
  type: "button",
51
73
  tabIndex: 0,
52
74
  onClick: onClear,
@@ -23,3 +23,18 @@ export declare const textareaBottomActionAreaPadding: {
23
23
  readonly md: "h-10";
24
24
  readonly lg: "h-12";
25
25
  };
26
+ export declare const textareaCharCountPositionOptions: {
27
+ readonly sm: "bottom-1.5 right-3 text-xs";
28
+ readonly md: "bottom-1.5 right-4 text-xs";
29
+ readonly lg: "bottom-1.5 right-4 text-sm";
30
+ };
31
+ export declare const textareaCharCountPaddingOptions: {
32
+ readonly sm: "pb-7";
33
+ readonly md: "pb-8";
34
+ readonly lg: "pb-9";
35
+ };
36
+ export declare const textareaCharCountTextSizeOptions: {
37
+ readonly sm: "text-xs";
38
+ readonly md: "text-xs";
39
+ readonly lg: "text-sm";
40
+ };
@@ -5,4 +5,7 @@ export var textareaSizeOptions = _defineProperty(_defineProperty(_defineProperty
5
5
  export var textareaClearButtonSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, ButtonSize.IconXs), FormSize.Md, ButtonSize.IconSm), FormSize.Lg, ButtonSize.IconMd);
6
6
  export var textareaClearablePaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pr-9'), FormSize.Md, 'pr-11'), FormSize.Lg, 'pr-12');
7
7
  export var textareaWithActionsSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pb-10 scroll-pb-10'), FormSize.Md, 'pb-12 scroll-pb-12'), FormSize.Lg, 'pb-14 scroll-pb-14');
8
- export var textareaBottomActionAreaPadding = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'h-8'), FormSize.Md, 'h-10'), FormSize.Lg, 'h-12');
8
+ export var textareaBottomActionAreaPadding = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'h-8'), FormSize.Md, 'h-10'), FormSize.Lg, 'h-12');
9
+ export var textareaCharCountPositionOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'bottom-1.5 right-3 text-xs'), FormSize.Md, 'bottom-1.5 right-4 text-xs'), FormSize.Lg, 'bottom-1.5 right-4 text-sm');
10
+ export var textareaCharCountPaddingOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'pb-7'), FormSize.Md, 'pb-8'), FormSize.Lg, 'pb-9');
11
+ export var textareaCharCountTextSizeOptions = _defineProperty(_defineProperty(_defineProperty({}, FormSize.Sm, 'text-xs'), FormSize.Md, 'text-xs'), FormSize.Lg, 'text-sm');
@@ -5,6 +5,7 @@ export interface TextareaProps extends Omit<ComponentProps<'textarea'>, 'size'>
5
5
  'aria-invalid'?: boolean;
6
6
  clearable?: boolean;
7
7
  onClear?: () => void;
8
+ maxCharCount?: number;
8
9
  }
9
10
  export interface TextareaWithActionsProps extends TextareaProps {
10
11
  leftToolbar?: ReactElement;
@@ -0,0 +1,21 @@
1
+ type ChangeEvent = {
2
+ currentTarget: {
3
+ value: string;
4
+ };
5
+ };
6
+ interface UseCharCountOptions<E extends ChangeEvent> {
7
+ value?: string | number | readonly string[];
8
+ defaultValue?: string | number | readonly string[];
9
+ maxCharCount?: number;
10
+ readOnly?: boolean;
11
+ onChange?: (e: E) => void;
12
+ }
13
+ export declare function useCharCount<E extends ChangeEvent>({ value, defaultValue, maxCharCount, readOnly, onChange, }: UseCharCountOptions<E>): {
14
+ currentLength: number;
15
+ isNearLimit: boolean;
16
+ isAtLimit: boolean;
17
+ showCharCount: boolean;
18
+ handleChange: ((e: E) => void) | undefined;
19
+ charCountColorClass: string;
20
+ };
21
+ export {};
@@ -0,0 +1,44 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { useState } from 'react';
3
+ var NEAR_LIMIT_RATIO = 0.1;
4
+ var MIN_NEAR_LIMIT_THRESHOLD = 1;
5
+ function getStringLength(val) {
6
+ if (val == null) return 0;
7
+ if (typeof val === 'string') return val.length;
8
+ return String(val).length;
9
+ }
10
+ export function useCharCount(_ref) {
11
+ var value = _ref.value,
12
+ defaultValue = _ref.defaultValue,
13
+ maxCharCount = _ref.maxCharCount,
14
+ readOnly = _ref.readOnly,
15
+ onChange = _ref.onChange;
16
+ var hasValidMaxCharCount = maxCharCount !== undefined && maxCharCount > 0;
17
+ var isControlled = value !== undefined;
18
+ var _useState = useState(function () {
19
+ return getStringLength(defaultValue);
20
+ }),
21
+ _useState2 = _slicedToArray(_useState, 2),
22
+ internalLength = _useState2[0],
23
+ setInternalLength = _useState2[1];
24
+ var currentLength = isControlled ? getStringLength(value) : internalLength;
25
+ var nearLimitThreshold = hasValidMaxCharCount ? Math.max(MIN_NEAR_LIMIT_THRESHOLD, Math.round(maxCharCount * NEAR_LIMIT_RATIO)) : 0;
26
+ var isNearLimit = hasValidMaxCharCount && currentLength >= maxCharCount - nearLimitThreshold;
27
+ var isAtLimit = hasValidMaxCharCount && currentLength >= maxCharCount;
28
+ var showCharCount = hasValidMaxCharCount && !readOnly;
29
+ var handleChange = hasValidMaxCharCount ? function (e) {
30
+ if (!isControlled) {
31
+ setInternalLength(e.currentTarget.value.length);
32
+ }
33
+ onChange === null || onChange === void 0 || onChange(e);
34
+ } : onChange;
35
+ var charCountColorClass = isAtLimit ? 'text-destructive-foreground' : isNearLimit ? 'text-warning-foreground' : 'text-muted-foreground';
36
+ return {
37
+ currentLength: currentLength,
38
+ isNearLimit: isNearLimit,
39
+ isAtLimit: isAtLimit,
40
+ showCharCount: showCharCount,
41
+ handleChange: handleChange,
42
+ charCountColorClass: charCountColorClass
43
+ };
44
+ }