@wellingtonhlc/shared-ui 0.29.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -10
- package/dist/cli/check-page-actions.d.ts +9 -0
- package/dist/cli/check-page-actions.d.ts.map +1 -0
- package/dist/cli/check-page-actions.js +108 -0
- package/dist/components/ActionBar.d.ts +26 -0
- package/dist/components/ActionBar.d.ts.map +1 -0
- package/dist/components/ActionBar.js +29 -0
- package/dist/components/ActionPrimitives.d.ts +31 -0
- package/dist/components/ActionPrimitives.d.ts.map +1 -0
- package/dist/components/ActionPrimitives.js +27 -0
- package/dist/components/AppShell.d.ts +65 -0
- package/dist/components/AppShell.d.ts.map +1 -0
- package/dist/components/AppShell.js +50 -0
- package/dist/components/AppShellActions.d.ts +24 -0
- package/dist/components/AppShellActions.d.ts.map +1 -0
- package/dist/components/AppShellActions.js +15 -0
- package/dist/components/Badge.d.ts +16 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +36 -0
- package/dist/components/Banner.d.ts +13 -0
- package/dist/components/Banner.d.ts.map +1 -0
- package/dist/components/Banner.js +29 -0
- package/dist/components/Button.d.ts +14 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +39 -0
- package/dist/components/Card.d.ts +36 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +56 -0
- package/dist/components/ConfirmationDialog.d.ts +74 -0
- package/dist/components/ConfirmationDialog.d.ts.map +1 -0
- package/dist/components/ConfirmationDialog.js +234 -0
- package/dist/components/CopyableField.d.ts +10 -0
- package/dist/components/CopyableField.d.ts.map +1 -0
- package/dist/components/CopyableField.js +60 -0
- package/dist/components/DateField.d.ts +20 -0
- package/dist/components/DateField.d.ts.map +1 -0
- package/dist/components/DateField.js +172 -0
- package/dist/components/DecimalField.d.ts +21 -0
- package/dist/components/DecimalField.d.ts.map +1 -0
- package/dist/components/DecimalField.js +137 -0
- package/dist/components/DismissiblePopover.d.ts +14 -0
- package/dist/components/DismissiblePopover.d.ts.map +1 -0
- package/dist/components/DismissiblePopover.js +51 -0
- package/dist/components/EmptyState.d.ts +15 -0
- package/dist/components/EmptyState.d.ts.map +1 -0
- package/dist/components/EmptyState.js +32 -0
- package/dist/components/FieldControl.d.ts +20 -0
- package/dist/components/FieldControl.d.ts.map +1 -0
- package/dist/components/FieldControl.js +73 -0
- package/dist/components/FieldGroup.d.ts +11 -0
- package/dist/components/FieldGroup.d.ts.map +1 -0
- package/dist/components/FieldGroup.js +11 -0
- package/dist/components/FieldSkeleton.d.ts +14 -0
- package/dist/components/FieldSkeleton.d.ts.map +1 -0
- package/dist/components/FieldSkeleton.js +23 -0
- package/dist/components/FieldValidationError.d.ts +8 -0
- package/dist/components/FieldValidationError.d.ts.map +1 -0
- package/dist/components/FieldValidationError.js +7 -0
- package/dist/components/Filter.d.ts +51 -0
- package/dist/components/Filter.d.ts.map +1 -0
- package/dist/components/Filter.js +68 -0
- package/dist/components/Loading.d.ts +17 -0
- package/dist/components/Loading.d.ts.map +1 -0
- package/dist/components/Loading.js +15 -0
- package/dist/components/LoadingOverlay.d.ts +11 -0
- package/dist/components/LoadingOverlay.d.ts.map +1 -0
- package/dist/components/LoadingOverlay.js +8 -0
- package/dist/components/Modal.d.ts +49 -0
- package/dist/components/Modal.d.ts.map +1 -0
- package/dist/components/Modal.js +108 -0
- package/dist/components/MultiSelectField.d.ts +22 -0
- package/dist/components/MultiSelectField.d.ts.map +1 -0
- package/dist/components/MultiSelectField.js +84 -0
- package/dist/components/NavCard.d.ts +15 -0
- package/dist/components/NavCard.d.ts.map +1 -0
- package/dist/components/NavCard.js +13 -0
- package/dist/components/Page.d.ts +89 -0
- package/dist/components/Page.d.ts.map +1 -0
- package/dist/components/Page.js +347 -0
- package/dist/components/PageMessage.d.ts +12 -0
- package/dist/components/PageMessage.d.ts.map +1 -0
- package/dist/components/PageMessage.js +36 -0
- package/dist/components/Pagination.d.ts +15 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +57 -0
- package/dist/components/PasswordInput.d.ts +8 -0
- package/dist/components/PasswordInput.d.ts.map +1 -0
- package/dist/components/PasswordInput.js +17 -0
- package/dist/components/RadioGroup.d.ts +32 -0
- package/dist/components/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup.js +86 -0
- package/dist/components/RenderCase.d.ts +20 -0
- package/dist/components/RenderCase.d.ts.map +1 -0
- package/dist/components/RenderCase.js +31 -0
- package/dist/components/RenderIf.d.ts +10 -0
- package/dist/components/RenderIf.d.ts.map +1 -0
- package/dist/components/RenderIf.js +9 -0
- package/dist/components/SearchField.d.ts +22 -0
- package/dist/components/SearchField.d.ts.map +1 -0
- package/dist/components/SearchField.js +43 -0
- package/dist/components/SelectField.d.ts +31 -0
- package/dist/components/SelectField.d.ts.map +1 -0
- package/dist/components/SelectField.js +26 -0
- package/dist/components/SelectionField.d.ts +39 -0
- package/dist/components/SelectionField.d.ts.map +1 -0
- package/dist/components/SelectionField.js +105 -0
- package/dist/components/Sidebar.d.ts +104 -0
- package/dist/components/Sidebar.d.ts.map +1 -0
- package/dist/components/Sidebar.js +146 -0
- package/dist/components/StatCard.d.ts +16 -0
- package/dist/components/StatCard.d.ts.map +1 -0
- package/dist/components/StatCard.js +62 -0
- package/dist/components/Switch.d.ts +20 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +63 -0
- package/dist/components/Table.d.ts +65 -0
- package/dist/components/Table.d.ts.map +1 -0
- package/dist/components/Table.js +118 -0
- package/dist/components/TabsUnderlined.d.ts +23 -0
- package/dist/components/TabsUnderlined.d.ts.map +1 -0
- package/dist/components/TabsUnderlined.js +29 -0
- package/dist/components/TextField.d.ts +25 -0
- package/dist/components/TextField.d.ts.map +1 -0
- package/dist/components/TextField.js +71 -0
- package/dist/components/TextareaField.d.ts +14 -0
- package/dist/components/TextareaField.d.ts.map +1 -0
- package/dist/components/TextareaField.js +34 -0
- package/dist/components/ThemePreferencesSelector.d.ts +29 -0
- package/dist/components/ThemePreferencesSelector.d.ts.map +1 -0
- package/dist/components/ThemePreferencesSelector.js +37 -0
- package/dist/components/Tooltip.d.ts +13 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +40 -0
- package/dist/components/Workspace.d.ts +22 -0
- package/dist/components/Workspace.d.ts.map +1 -0
- package/dist/components/Workspace.js +33 -0
- package/dist/components/WorkspaceContext.d.ts +2 -0
- package/dist/components/WorkspaceContext.d.ts.map +1 -0
- package/dist/components/WorkspaceContext.js +2 -0
- package/dist/components/form-control-helpers.d.ts +24 -0
- package/dist/components/form-control-helpers.d.ts.map +1 -0
- package/dist/components/form-control-helpers.js +20 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/styles.css +21 -41
- package/dist/tailwind-preset.d.ts +23 -0
- package/dist/tailwind-preset.d.ts.map +1 -0
- package/dist/tailwind-preset.js +22 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +33 -0
- package/package.json +1 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import DatePicker, { registerLocale } from 'react-datepicker';
|
|
4
|
+
import { Calendar, CalendarClock } from 'lucide-react';
|
|
5
|
+
import { ptBR } from 'date-fns/locale';
|
|
6
|
+
import { cn } from '../utils/cn';
|
|
7
|
+
import { controlClasses } from './form-control-helpers';
|
|
8
|
+
import { FieldControl } from './FieldControl';
|
|
9
|
+
registerLocale('pt-BR', ptBR);
|
|
10
|
+
function toDateOnlyString(value) {
|
|
11
|
+
if (value === undefined)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (value === null || value === '')
|
|
14
|
+
return '';
|
|
15
|
+
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
16
|
+
return value;
|
|
17
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
18
|
+
if (Number.isNaN(date.getTime()))
|
|
19
|
+
return '';
|
|
20
|
+
const year = date.getFullYear();
|
|
21
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
22
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
23
|
+
return `${year}-${month}-${day}`;
|
|
24
|
+
}
|
|
25
|
+
function toDateTimeString(value) {
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (value === null || value === '')
|
|
29
|
+
return '';
|
|
30
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
31
|
+
if (Number.isNaN(date.getTime()))
|
|
32
|
+
return '';
|
|
33
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
34
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
35
|
+
}
|
|
36
|
+
function toTimeOnlyString(value) {
|
|
37
|
+
if (value === undefined)
|
|
38
|
+
return undefined;
|
|
39
|
+
if (value === null || value === '')
|
|
40
|
+
return '';
|
|
41
|
+
if (typeof value === 'string' && /^\d{2}:\d{2}$/.test(value))
|
|
42
|
+
return value;
|
|
43
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
44
|
+
if (Number.isNaN(date.getTime()))
|
|
45
|
+
return '';
|
|
46
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
47
|
+
return `${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
48
|
+
}
|
|
49
|
+
function toDateOnlyObject(value) {
|
|
50
|
+
const str = toDateOnlyString(value);
|
|
51
|
+
if (!str)
|
|
52
|
+
return null;
|
|
53
|
+
const [year, month, day] = str.split('-').map(Number);
|
|
54
|
+
const d = new Date(year, month - 1, day);
|
|
55
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
56
|
+
}
|
|
57
|
+
function toDateTimeObject(value) {
|
|
58
|
+
if (!value)
|
|
59
|
+
return null;
|
|
60
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
61
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
62
|
+
}
|
|
63
|
+
function toTimeOnlyObject(value) {
|
|
64
|
+
const str = toTimeOnlyString(value);
|
|
65
|
+
if (!str)
|
|
66
|
+
return null;
|
|
67
|
+
const [hours, minutes] = str.split(':').map(Number);
|
|
68
|
+
const d = new Date();
|
|
69
|
+
d.setHours(hours, minutes, 0, 0);
|
|
70
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
71
|
+
}
|
|
72
|
+
function toOptionalDate(value) {
|
|
73
|
+
if (typeof value !== 'string' || !value)
|
|
74
|
+
return undefined;
|
|
75
|
+
return toDateOnlyObject(value) ?? undefined;
|
|
76
|
+
}
|
|
77
|
+
function getDateFieldMode(mode, enableTime) {
|
|
78
|
+
if (mode)
|
|
79
|
+
return mode;
|
|
80
|
+
return enableTime ? 'dateTime' : 'date';
|
|
81
|
+
}
|
|
82
|
+
function toInputValueByMode(mode, value) {
|
|
83
|
+
if (mode === 'time')
|
|
84
|
+
return toTimeOnlyString(value);
|
|
85
|
+
if (mode === 'dateTime')
|
|
86
|
+
return toDateTimeString(value);
|
|
87
|
+
return toDateOnlyString(value);
|
|
88
|
+
}
|
|
89
|
+
function toDateObjectByMode(mode, value) {
|
|
90
|
+
if (mode === 'time')
|
|
91
|
+
return toTimeOnlyObject(value);
|
|
92
|
+
if (mode === 'dateTime')
|
|
93
|
+
return toDateTimeObject(value);
|
|
94
|
+
return toDateOnlyObject(value);
|
|
95
|
+
}
|
|
96
|
+
function assignRef(ref, value) {
|
|
97
|
+
if (!ref)
|
|
98
|
+
return;
|
|
99
|
+
if (typeof ref === 'function') {
|
|
100
|
+
ref(value);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
ref.current = value;
|
|
104
|
+
}
|
|
105
|
+
export const DateField = React.forwardRef(({ label, onChange, onBlur, inputRef, disabled, errorMessage, id, className, wrapperClassName, labelClassName, size = 'sm', roundedFull = false, noPortal = false, calendarClassName, mode, enableTime = false, timeIntervals = 5, value, name, placeholder, min, max, autoComplete = 'off', autoFocus, }, ref) => {
|
|
106
|
+
const sizeMap = {
|
|
107
|
+
sm: 'h-9 text-sm px-3 rounded-md',
|
|
108
|
+
md: 'h-12 text-sm px-4 rounded-md',
|
|
109
|
+
lg: 'h-14 text-base px-6 rounded-lg',
|
|
110
|
+
};
|
|
111
|
+
const sizeClass = sizeMap[size ?? 'sm'];
|
|
112
|
+
const hiddenInputRef = React.useRef(null);
|
|
113
|
+
const resolvedMode = getDateFieldMode(mode, enableTime);
|
|
114
|
+
const isTimeOnly = resolvedMode === 'time';
|
|
115
|
+
const isDateTime = resolvedMode === 'dateTime';
|
|
116
|
+
const isDateOnly = resolvedMode === 'date';
|
|
117
|
+
const normalizedValue = toInputValueByMode(resolvedMode, value);
|
|
118
|
+
const [selectedDate, setSelectedDate] = React.useState(() => toDateObjectByMode(resolvedMode, value));
|
|
119
|
+
React.useEffect(() => {
|
|
120
|
+
if (value !== undefined)
|
|
121
|
+
setSelectedDate(toDateObjectByMode(resolvedMode, value));
|
|
122
|
+
}, [value, resolvedMode]);
|
|
123
|
+
React.useEffect(() => {
|
|
124
|
+
if (hiddenInputRef.current && normalizedValue !== undefined) {
|
|
125
|
+
hiddenInputRef.current.value = normalizedValue;
|
|
126
|
+
}
|
|
127
|
+
}, [normalizedValue]);
|
|
128
|
+
const emitChange = (nextValue) => {
|
|
129
|
+
if (hiddenInputRef.current)
|
|
130
|
+
hiddenInputRef.current.value = nextValue;
|
|
131
|
+
if (!onChange)
|
|
132
|
+
return;
|
|
133
|
+
const syntheticEvent = {
|
|
134
|
+
target: { name, value: nextValue },
|
|
135
|
+
currentTarget: { name, value: nextValue },
|
|
136
|
+
type: 'change',
|
|
137
|
+
};
|
|
138
|
+
if (onChange.length === 1 && onChange.toString().includes('event')) {
|
|
139
|
+
onChange(syntheticEvent);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
onChange(nextValue);
|
|
143
|
+
};
|
|
144
|
+
const handleDateChange = (nextDate) => {
|
|
145
|
+
const resolved = Array.isArray(nextDate) ? (nextDate[0] ?? null) : nextDate;
|
|
146
|
+
setSelectedDate(resolved);
|
|
147
|
+
emitChange(toInputValueByMode(resolvedMode, resolved) ?? '');
|
|
148
|
+
};
|
|
149
|
+
return (_jsx(FieldControl, { label: label, id: id || name, wrapperClassName: wrapperClassName, labelClassName: labelClassName, errorMessage: errorMessage, roundedFull: roundedFull, size: size, disabled: disabled, children: ({ controlId, describedBy, errorMessage: controlError, disabled: controlDisabled }) => (_jsxs("div", { className: "relative", children: [_jsx("input", { type: "hidden", ref: (node) => {
|
|
150
|
+
hiddenInputRef.current = node;
|
|
151
|
+
assignRef(ref, node);
|
|
152
|
+
assignRef(inputRef, node);
|
|
153
|
+
}, name: name, disabled: controlDisabled, defaultValue: normalizedValue }), _jsx(DatePicker, { id: controlId, selected: selectedDate, onChange: handleDateChange, ...(!noPortal && { portalId: 'datepicker-portal' }), onBlur: (event) => {
|
|
154
|
+
if (!onBlur || !hiddenInputRef.current)
|
|
155
|
+
return;
|
|
156
|
+
const syntheticEvent = {
|
|
157
|
+
...event,
|
|
158
|
+
target: hiddenInputRef.current,
|
|
159
|
+
currentTarget: hiddenInputRef.current,
|
|
160
|
+
};
|
|
161
|
+
onBlur(syntheticEvent);
|
|
162
|
+
}, ...(isTimeOnly
|
|
163
|
+
? { showTimeSelect: true, showTimeSelectOnly: true, timeIntervals, dateFormat: 'HH:mm', timeFormat: 'HH:mm', timeCaption: 'Hora' }
|
|
164
|
+
: isDateTime
|
|
165
|
+
? { showTimeSelect: true, timeIntervals, dateFormat: 'dd/MM/yyyy HH:mm', timeFormat: 'HH:mm', timeCaption: 'Hora' }
|
|
166
|
+
: { dateFormat: 'dd/MM/yyyy', minDate: toOptionalDate(min), maxDate: toOptionalDate(max) }), locale: "pt-BR", placeholderText: placeholder ?? label, disabled: controlDisabled, showPopperArrow: false, popperClassName: "app-datepicker-popper", calendarClassName: cn('app-datepicker', calendarClassName), wrapperClassName: "w-full", formatWeekDay: (day) => day.slice(0, 3), ariaDescribedBy: describedBy, ariaInvalid: controlError ? 'true' : undefined, autoComplete: autoComplete, autoFocus: autoFocus, className: controlClasses({
|
|
167
|
+
errorMessage: controlError,
|
|
168
|
+
disabled: controlDisabled,
|
|
169
|
+
extra: cn(className, 'w-full cursor-pointer pr-10', sizeClass),
|
|
170
|
+
}) }), _jsx("div", { className: "pointer-events-none absolute top-1/2 right-3 flex -translate-y-1/2 items-center justify-center", children: isDateOnly ? _jsx(Calendar, { className: "text-foreground-muted h-4 w-4" }) : _jsx(CalendarClock, { className: "text-foreground-muted h-4 w-4" }) })] })) }));
|
|
171
|
+
});
|
|
172
|
+
DateField.displayName = 'DateField';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type FieldValues } from 'react-hook-form';
|
|
3
|
+
export interface DecimalFieldProps<TFieldValues extends FieldValues = FieldValues> extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'value' | 'onChange'> {
|
|
4
|
+
value?: number | null;
|
|
5
|
+
onChange?: ((value: number) => void) | React.ChangeEventHandler<HTMLInputElement>;
|
|
6
|
+
decimals?: number;
|
|
7
|
+
currency?: string | null;
|
|
8
|
+
locale?: string;
|
|
9
|
+
control?: unknown;
|
|
10
|
+
rules?: unknown;
|
|
11
|
+
label?: string;
|
|
12
|
+
errorMessage?: string;
|
|
13
|
+
wrapperClassName?: string;
|
|
14
|
+
labelClassName?: string;
|
|
15
|
+
roundedFull?: boolean;
|
|
16
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
17
|
+
labelPosition?: 'top' | 'right' | 'bottom' | 'left';
|
|
18
|
+
variant?: 'default' | 'neutral';
|
|
19
|
+
}
|
|
20
|
+
export declare const DecimalField: <TFieldValues extends FieldValues = FieldValues>(props: DecimalFieldProps<TFieldValues> & React.RefAttributes<HTMLInputElement>) => React.ReactElement;
|
|
21
|
+
//# sourceMappingURL=DecimalField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DecimalField.d.ts","sourceRoot":"","sources":["../../src/components/DecimalField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAGL,KAAK,WAAW,EAGjB,MAAM,iBAAiB,CAAC;AAMzB,MAAM,WAAW,iBAAiB,CAAC,YAAY,SAAS,WAAW,GAAG,WAAW,CAC/E,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IACxF,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AA+PD,eAAO,MAAM,YAAY,EAQnB,CAAC,YAAY,SAAS,WAAW,GAAG,WAAW,EACnD,KAAK,EAAE,iBAAiB,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAC3E,KAAK,CAAC,YAAY,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useController, } from 'react-hook-form';
|
|
4
|
+
import { cn } from '../utils/cn';
|
|
5
|
+
import { controlClasses } from './form-control-helpers';
|
|
6
|
+
import { FieldControl } from './FieldControl';
|
|
7
|
+
function assignInputRef(forwardedRef, inputRef, node) {
|
|
8
|
+
if (typeof inputRef === 'function')
|
|
9
|
+
inputRef(node);
|
|
10
|
+
else if (inputRef)
|
|
11
|
+
inputRef.current = node;
|
|
12
|
+
if (typeof forwardedRef === 'function') {
|
|
13
|
+
forwardedRef(node);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (forwardedRef)
|
|
17
|
+
forwardedRef.current = node;
|
|
18
|
+
}
|
|
19
|
+
const DecimalFieldBase = React.forwardRef(function DecimalFieldBase({ value, onChange, decimals = 2, currency = null, className = '', placeholder = '', id, label, errorMessage, wrapperClassName = '', labelClassName = '', labelPosition = 'top', disabled = false, locale = 'pt-BR', roundedFull = false, size = 'sm', name, onBlur, onKeyDown, inputName, inputValue, inputDisabled, inputOnBlur, inputRef, onValueChange, variant, ...props }, ref) {
|
|
20
|
+
const [digits, setDigits] = useState('');
|
|
21
|
+
const previousValueRef = useRef(undefined);
|
|
22
|
+
const resolvedValue = inputValue ?? value;
|
|
23
|
+
const resolvedName = inputName ?? name;
|
|
24
|
+
const resolvedDisabled = inputDisabled ?? disabled;
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (previousValueRef.current === resolvedValue)
|
|
27
|
+
return;
|
|
28
|
+
if (resolvedValue === null || resolvedValue === undefined || Number(resolvedValue) === 0) {
|
|
29
|
+
setDigits('');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const factor = Math.pow(10, decimals);
|
|
33
|
+
const integerValue = Math.round(Number(resolvedValue) * factor);
|
|
34
|
+
setDigits(String(integerValue));
|
|
35
|
+
}
|
|
36
|
+
previousValueRef.current = resolvedValue;
|
|
37
|
+
}, [resolvedValue, decimals]);
|
|
38
|
+
function notify(nextDigits, event) {
|
|
39
|
+
setDigits(nextDigits);
|
|
40
|
+
const factor = Math.pow(10, decimals);
|
|
41
|
+
const nextValue = nextDigits === '' ? 0 : Number(nextDigits) / factor;
|
|
42
|
+
previousValueRef.current = nextValue;
|
|
43
|
+
if (onValueChange) {
|
|
44
|
+
onValueChange(nextValue, event);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!onChange)
|
|
48
|
+
return;
|
|
49
|
+
if (event && onChange.length === 1 && event.nativeEvent) {
|
|
50
|
+
onChange(event);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
onChange(nextValue);
|
|
54
|
+
}
|
|
55
|
+
function formatDisplay(valueToFormat) {
|
|
56
|
+
if (valueToFormat === '')
|
|
57
|
+
return '';
|
|
58
|
+
const factor = Math.pow(10, decimals);
|
|
59
|
+
const numericValue = Number(valueToFormat) / factor;
|
|
60
|
+
return numericValue.toLocaleString(locale, {
|
|
61
|
+
minimumFractionDigits: decimals,
|
|
62
|
+
maximumFractionDigits: decimals,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function handleKeyDown(event) {
|
|
66
|
+
if (resolvedDisabled)
|
|
67
|
+
return;
|
|
68
|
+
const { key } = event;
|
|
69
|
+
if (key === 'Backspace' ||
|
|
70
|
+
key === 'Delete' ||
|
|
71
|
+
key === 'ArrowLeft' ||
|
|
72
|
+
key === 'ArrowRight' ||
|
|
73
|
+
key === 'Tab' ||
|
|
74
|
+
key === 'Enter') {
|
|
75
|
+
if (key === 'Backspace' || key === 'Delete') {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
notify(digits.slice(0, -1), undefined);
|
|
78
|
+
}
|
|
79
|
+
if (key === 'Enter')
|
|
80
|
+
onKeyDown?.(event);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (/^[0-9]$/.test(key)) {
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
notify(digits + key, undefined);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
}
|
|
90
|
+
function handlePaste(event) {
|
|
91
|
+
if (resolvedDisabled)
|
|
92
|
+
return;
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
const pasted = event.clipboardData.getData('text').replace(/\D/g, '');
|
|
95
|
+
if (!pasted)
|
|
96
|
+
return;
|
|
97
|
+
notify(digits + pasted, undefined);
|
|
98
|
+
}
|
|
99
|
+
function handleBlur(event) {
|
|
100
|
+
inputOnBlur?.(event);
|
|
101
|
+
onBlur?.(event);
|
|
102
|
+
}
|
|
103
|
+
function handleChange(event) {
|
|
104
|
+
notify(event.target.value.replace(/\D/g, ''), event);
|
|
105
|
+
}
|
|
106
|
+
const sizeMap = {
|
|
107
|
+
xs: 'h-7 text-xs px-2 rounded-md',
|
|
108
|
+
sm: 'h-9 text-sm px-3 rounded-md',
|
|
109
|
+
md: 'h-12 text-sm px-4 rounded-md',
|
|
110
|
+
lg: 'h-14 text-base px-6 rounded-lg',
|
|
111
|
+
};
|
|
112
|
+
return (_jsx(FieldControl, { label: label, id: id || resolvedName, labelClassName: labelClassName, labelPosition: labelPosition, wrapperClassName: wrapperClassName, errorMessage: errorMessage, roundedFull: roundedFull, size: size, disabled: resolvedDisabled, children: ({ controlId, describedBy, errorMessage: controlError, disabled: controlDisabled }) => (_jsxs("div", { className: "relative", children: [currency ? (_jsx("span", { className: "text-foreground-muted absolute top-1/2 left-3 -translate-y-1/2 text-sm", children: currency })) : null, _jsx("input", { ref: (node) => assignInputRef(ref, inputRef, node), inputMode: "numeric", ...props, id: controlId, name: resolvedName, disabled: controlDisabled, placeholder: placeholder ||
|
|
113
|
+
(0).toLocaleString(locale, {
|
|
114
|
+
minimumFractionDigits: decimals,
|
|
115
|
+
maximumFractionDigits: decimals,
|
|
116
|
+
}), value: formatDisplay(digits), onKeyDown: handleKeyDown, onPaste: handlePaste, onBlur: handleBlur, onChange: handleChange, "aria-label": props['aria-label'] ?? placeholder ?? label ?? 'campo numérico', "aria-invalid": !!controlError, "aria-describedby": describedBy, className: controlClasses({
|
|
117
|
+
errorMessage: controlError,
|
|
118
|
+
disabled: controlDisabled,
|
|
119
|
+
variant,
|
|
120
|
+
extra: cn(className, 'field-decimal text-right', currency ? 'pr-4 pl-12' : 'px-4', sizeMap[size ?? 'sm']),
|
|
121
|
+
}) })] })) }));
|
|
122
|
+
});
|
|
123
|
+
function HookFormDecimalField(props) {
|
|
124
|
+
const { control, rules, name, forwardedRef, variant, ...rest } = props;
|
|
125
|
+
const { field } = useController({
|
|
126
|
+
control: control,
|
|
127
|
+
name: name,
|
|
128
|
+
rules: rules,
|
|
129
|
+
});
|
|
130
|
+
return (_jsx(DecimalFieldBase, { ...rest, ref: forwardedRef, name: name, variant: variant, inputName: field.name, inputValue: Number(field.value ?? 0), inputDisabled: field.disabled, inputRef: field.ref, inputOnBlur: field.onBlur, onValueChange: field.onChange }));
|
|
131
|
+
}
|
|
132
|
+
export const DecimalField = React.forwardRef(function DecimalField(props, ref) {
|
|
133
|
+
if (props.control && props.name) {
|
|
134
|
+
return _jsx(HookFormDecimalField, { ...props, forwardedRef: ref });
|
|
135
|
+
}
|
|
136
|
+
return _jsx(DecimalFieldBase, { ...props, ref: ref });
|
|
137
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
2
|
+
export interface DismissiblePopoverProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
trigger: ReactNode;
|
|
6
|
+
content: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
contentClassName?: string;
|
|
9
|
+
containerRef?: RefObject<HTMLDivElement | null>;
|
|
10
|
+
closeDelay?: number;
|
|
11
|
+
animationDuration?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function DismissiblePopover({ open, onOpenChange, trigger, content, className, contentClassName, containerRef, closeDelay, animationDuration, }: DismissiblePopoverProps): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=DismissiblePopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DismissiblePopover.d.ts","sourceRoot":"","sources":["../../src/components/DismissiblePopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIpF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,SAAS,CAAC;IACnB,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,UAAiB,EACjB,iBAAuB,GACxB,EAAE,uBAAuB,+BA6EzB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
export function DismissiblePopover({ open, onOpenChange, trigger, content, className, contentClassName, containerRef, closeDelay = 1500, animationDuration = 180, }) {
|
|
5
|
+
const closeTimerRef = useRef(null);
|
|
6
|
+
const animationTimerRef = useRef(null);
|
|
7
|
+
const [contentVisible, setContentVisible] = useState(open);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (closeTimerRef.current !== null) {
|
|
10
|
+
window.clearTimeout(closeTimerRef.current);
|
|
11
|
+
closeTimerRef.current = null;
|
|
12
|
+
}
|
|
13
|
+
if (open) {
|
|
14
|
+
setContentVisible(true);
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
animationTimerRef.current = window.setTimeout(() => {
|
|
18
|
+
setContentVisible(false);
|
|
19
|
+
animationTimerRef.current = null;
|
|
20
|
+
}, animationDuration);
|
|
21
|
+
return () => {
|
|
22
|
+
if (animationTimerRef.current !== null) {
|
|
23
|
+
window.clearTimeout(animationTimerRef.current);
|
|
24
|
+
animationTimerRef.current = null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}, [animationDuration, open]);
|
|
28
|
+
useEffect(() => () => {
|
|
29
|
+
if (closeTimerRef.current !== null)
|
|
30
|
+
window.clearTimeout(closeTimerRef.current);
|
|
31
|
+
if (animationTimerRef.current !== null)
|
|
32
|
+
window.clearTimeout(animationTimerRef.current);
|
|
33
|
+
}, []);
|
|
34
|
+
function clearCloseTimer() {
|
|
35
|
+
if (closeTimerRef.current !== null) {
|
|
36
|
+
window.clearTimeout(closeTimerRef.current);
|
|
37
|
+
closeTimerRef.current = null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function handleMouseEnter() {
|
|
41
|
+
clearCloseTimer();
|
|
42
|
+
}
|
|
43
|
+
function handleMouseLeave() {
|
|
44
|
+
clearCloseTimer();
|
|
45
|
+
closeTimerRef.current = window.setTimeout(() => {
|
|
46
|
+
onOpenChange(false);
|
|
47
|
+
closeTimerRef.current = null;
|
|
48
|
+
}, closeDelay);
|
|
49
|
+
}
|
|
50
|
+
return (_jsxs("div", { ref: containerRef, className: cn('relative', className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleMouseEnter, children: [trigger, contentVisible ? (_jsx("div", { "data-state": open ? 'open' : 'closed', className: cn('transition-[opacity,transform] ease-out', open ? 'translate-x-0 opacity-100' : 'pointer-events-none translate-x-2 opacity-0', contentClassName), style: { transitionDuration: `${animationDuration}ms` }, children: content })) : null] }));
|
|
51
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
export type EmptyStateVariant = 'default' | 'compact';
|
|
3
|
+
export interface EmptyStateProps {
|
|
4
|
+
title?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
showIcon?: boolean;
|
|
8
|
+
variant?: EmptyStateVariant;
|
|
9
|
+
fill?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare function EmptyState({ title, description, icon, showIcon, variant, fill, className, style, children, }: EmptyStateProps): import("react").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=EmptyState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../src/components/EmptyState.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMzF,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAwB,EACxB,WAAW,EACX,IAA2B,EAC3B,QAAe,EACf,OAAmB,EACnB,IAAI,EACJ,SAAS,EACT,KAAK,EACL,QAAQ,GACT,EAAE,eAAe,+BA8CjB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cloneElement, isValidElement } from 'react';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { WorkspaceResultContext } from './WorkspaceContext';
|
|
5
|
+
import { useContext } from 'react';
|
|
6
|
+
export function EmptyState({ title = 'Nada por aqui.', description, icon = _jsx(DefaultEmptyIcon, {}), showIcon = true, variant = 'default', fill, className, style, children, }) {
|
|
7
|
+
const isCompact = variant === 'compact';
|
|
8
|
+
const workspaceFill = useContext(WorkspaceResultContext);
|
|
9
|
+
const resolvedFill = fill ?? workspaceFill;
|
|
10
|
+
const shouldFillWithMargin = resolvedFill;
|
|
11
|
+
const styledIcon = isValidElement(icon)
|
|
12
|
+
? cloneElement(icon, {
|
|
13
|
+
className: cn('h-10 w-10 text-foreground-muted', icon.props.className),
|
|
14
|
+
})
|
|
15
|
+
: icon;
|
|
16
|
+
return (_jsx("div", { className: cn('flex min-h-0 w-full items-center justify-center rounded-md border border-dashed border-[color-mix(in_srgb,var(--foreground-muted)_24%,transparent)] bg-surface text-center text-foreground-muted', !resolvedFill
|
|
17
|
+
? 'h-auto w-fit flex-none px-5 py-10'
|
|
18
|
+
: isCompact
|
|
19
|
+
? 'px-4 py-6'
|
|
20
|
+
: 'h-full flex-1 px-5 py-10', shouldFillWithMargin && 'm-3', className), "data-slot": "empty-state", style: {
|
|
21
|
+
...style,
|
|
22
|
+
...(shouldFillWithMargin
|
|
23
|
+
? {
|
|
24
|
+
width: 'calc(100% - 1.5rem)',
|
|
25
|
+
height: 'calc(100% - 1.5rem)',
|
|
26
|
+
}
|
|
27
|
+
: {}),
|
|
28
|
+
}, children: _jsxs("div", { className: cn('mx-auto grid justify-items-center', isCompact ? 'max-w-xs gap-1.5' : 'max-w-sm gap-2'), children: [showIcon && styledIcon ? (_jsx("div", { className: "text-foreground-muted mb-1 flex h-11 w-11 items-center justify-center", children: styledIcon })) : null, _jsx("strong", { className: "text-foreground text-sm font-semibold", children: title }), description ? _jsx("p", { className: "text-foreground-muted text-xs leading-5", children: description }) : null, children ? _jsx("div", { className: cn('mt-2 flex flex-wrap items-center justify-center gap-2', isCompact ? 'text-xs' : 'text-sm'), children: children }) : null] }) }));
|
|
29
|
+
}
|
|
30
|
+
function DefaultEmptyIcon() {
|
|
31
|
+
return (_jsx("svg", { "aria-hidden": "true", className: "h-10 w-10", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "1.8", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 8.75 6.2 5.4A2 2 0 0 1 7.82 4.6h8.36a2 2 0 0 1 1.62.8l2.45 3.35M3.75 8.75v6.9A3.75 3.75 0 0 0 7.5 19.4h9a3.75 3.75 0 0 0 3.75-3.75v-6.9M3.75 8.75h4.92a1.5 1.5 0 0 1 1.34.83l.28.56a1.5 1.5 0 0 0 1.34.83h.74a1.5 1.5 0 0 0 1.34-.83l.28-.56a1.5 1.5 0 0 1 1.34-.83h4.92" }) }));
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type FormControlRenderProps, type FormControlSize } from './form-control-helpers';
|
|
3
|
+
export interface FieldControlProps {
|
|
4
|
+
label?: string;
|
|
5
|
+
id?: string;
|
|
6
|
+
labelClassName?: string;
|
|
7
|
+
labelAction?: React.ReactNode;
|
|
8
|
+
wrapperClassName?: string;
|
|
9
|
+
errorMessage?: string | undefined;
|
|
10
|
+
hasValidation?: boolean;
|
|
11
|
+
roundedFull?: boolean;
|
|
12
|
+
size?: FormControlSize;
|
|
13
|
+
labelPosition?: 'top' | 'right' | 'bottom' | 'left';
|
|
14
|
+
/** Faz o campo preencher a altura disponivel do container (wrapper e controle crescem). */
|
|
15
|
+
stretch?: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
children?: React.ReactNode | ((props: FormControlRenderProps) => React.ReactNode);
|
|
18
|
+
}
|
|
19
|
+
export declare const FieldControl: React.FC<FieldControlProps>;
|
|
20
|
+
//# sourceMappingURL=FieldControl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldControl.d.ts","sourceRoot":"","sources":["../../src/components/FieldControl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,aAAa,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,sBAAsB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;CACnF;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA2HpD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { fieldWrapper, labelBase, } from './form-control-helpers';
|
|
5
|
+
import { FieldValidationError } from './FieldValidationError';
|
|
6
|
+
export const FieldControl = ({ label, id, wrapperClassName, labelClassName = '', labelAction, labelPosition = 'top', errorMessage, roundedFull = false, size = 'sm', stretch = false, disabled = false, hasValidation = false, children, }) => {
|
|
7
|
+
const generatedId = React.useId().replace(/:/g, '');
|
|
8
|
+
const componentId = id ?? `fc-${generatedId}`;
|
|
9
|
+
const errorId = `${componentId}-error`;
|
|
10
|
+
const describedBy = errorMessage ? errorId : undefined;
|
|
11
|
+
const scopeClass = 'fc-placeholder-scope';
|
|
12
|
+
const roundedClass = roundedFull ? 'fc-rounded-full' : '';
|
|
13
|
+
const isHorizontal = labelPosition === 'left' || labelPosition === 'right';
|
|
14
|
+
const labelSizeClassMap = {
|
|
15
|
+
xs: 'text-[length:var(--font-size-2xs)]',
|
|
16
|
+
sm: 'text-xs',
|
|
17
|
+
md: 'text-sm',
|
|
18
|
+
lg: 'text-base',
|
|
19
|
+
};
|
|
20
|
+
const mergedLabelClassName = cn(labelBase, 'font-medium transition-colors', isHorizontal && 'mb-0', errorMessage ? 'text-red-600 dark:text-red-400' : 'text-foreground-muted', disabled && 'cursor-not-allowed opacity-70', labelClassName, labelSizeClassMap[size ?? 'sm']);
|
|
21
|
+
let flexDirection = 'flex-col';
|
|
22
|
+
let labelOrder = 0;
|
|
23
|
+
let inputOrder = 1;
|
|
24
|
+
if (labelPosition === 'left') {
|
|
25
|
+
flexDirection = 'flex-row items-center';
|
|
26
|
+
labelOrder = 0;
|
|
27
|
+
inputOrder = 1;
|
|
28
|
+
}
|
|
29
|
+
else if (labelPosition === 'right') {
|
|
30
|
+
flexDirection = 'flex-row items-center';
|
|
31
|
+
labelOrder = 1;
|
|
32
|
+
inputOrder = 0;
|
|
33
|
+
}
|
|
34
|
+
else if (labelPosition === 'bottom') {
|
|
35
|
+
flexDirection = 'flex-col';
|
|
36
|
+
labelOrder = 1;
|
|
37
|
+
inputOrder = 0;
|
|
38
|
+
}
|
|
39
|
+
const renderProps = {
|
|
40
|
+
controlId: componentId,
|
|
41
|
+
errorId,
|
|
42
|
+
describedBy,
|
|
43
|
+
errorMessage,
|
|
44
|
+
disabled,
|
|
45
|
+
label,
|
|
46
|
+
roundedFull,
|
|
47
|
+
size,
|
|
48
|
+
};
|
|
49
|
+
const renderedChildren = typeof children === 'function' ? children(renderProps) : children;
|
|
50
|
+
const renderedLabel = label ? (_jsxs("div", { className: cn('flex items-center justify-between gap-2', isHorizontal && 'shrink-0'), style: { order: labelOrder }, children: [_jsx("label", { htmlFor: componentId, className: mergedLabelClassName, children: label }), labelAction] })) : null;
|
|
51
|
+
return (_jsxs("div", { className: cn(fieldWrapper, stretch && 'h-full min-h-0', wrapperClassName, scopeClass, roundedClass), "data-disabled": disabled || undefined, "data-invalid": !!errorMessage || undefined, children: [_jsx("style", { children: `
|
|
52
|
+
.${scopeClass} input,
|
|
53
|
+
.${scopeClass} textarea,
|
|
54
|
+
.${scopeClass} select { color: var(--foreground); }
|
|
55
|
+
.${scopeClass} input::placeholder,
|
|
56
|
+
.${scopeClass} textarea::placeholder,
|
|
57
|
+
.${scopeClass} select::placeholder { color: var(--muted-foreground); opacity: 0.34; }
|
|
58
|
+
.dark .${scopeClass} input::placeholder,
|
|
59
|
+
.dark .${scopeClass} textarea::placeholder,
|
|
60
|
+
.dark .${scopeClass} select::placeholder { color: var(--muted-foreground); opacity: 0.50; }
|
|
61
|
+
.${scopeClass} input::-webkit-input-placeholder,
|
|
62
|
+
.${scopeClass} textarea::-webkit-input-placeholder { color: var(--muted-foreground); opacity: 0.34; }
|
|
63
|
+
.dark .${scopeClass} input::-webkit-input-placeholder,
|
|
64
|
+
.dark .${scopeClass} textarea::-webkit-input-placeholder { color: var(--muted-foreground); opacity: 0.50; }
|
|
65
|
+
.${roundedClass} input,
|
|
66
|
+
.${roundedClass} textarea,
|
|
67
|
+
.${roundedClass} select { border-radius: var(--radius-full); padding: var(--space-1-5) var(--space-4); min-height: var(--space-8); }
|
|
68
|
+
.${roundedClass} input::placeholder,
|
|
69
|
+
.${roundedClass} textarea::placeholder,
|
|
70
|
+
.${roundedClass} select::placeholder { opacity: 0.5; }
|
|
71
|
+
` }), _jsxs("div", { className: cn('flex gap-2', flexDirection, stretch && 'min-h-0 flex-1'), children: [labelOrder === 0 && renderedLabel, _jsx("div", { style: { order: inputOrder }, className: cn(isHorizontal && 'flex-1', stretch && 'min-h-0 flex-1'), children: renderedChildren }), labelOrder === 1 && renderedLabel] }), _jsx(FieldValidationError, { id: errorId, message: errorMessage, hasValidation: hasValidation })] }));
|
|
72
|
+
};
|
|
73
|
+
FieldControl.displayName = 'FieldControl';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface FieldGroupProps {
|
|
3
|
+
title: string;
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
bordered?: boolean;
|
|
7
|
+
titleAlign?: 'left' | 'center' | 'right';
|
|
8
|
+
}
|
|
9
|
+
export declare function FieldGroup({ bordered, children, className, title, titleAlign }: FieldGroupProps): import("react").JSX.Element;
|
|
10
|
+
export declare const FormSection: typeof FieldGroup;
|
|
11
|
+
//# sourceMappingURL=FieldGroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldGroup.d.ts","sourceRoot":"","sources":["../../src/components/FieldGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC1C;AAQD,wBAAgB,UAAU,CAAC,EAAE,QAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,UAAmB,EAAE,EAAE,eAAe,+BAS/G;AAED,eAAO,MAAM,WAAW,mBAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../utils/cn';
|
|
3
|
+
const titleAlignClass = {
|
|
4
|
+
left: 'mr-auto',
|
|
5
|
+
center: 'mx-auto',
|
|
6
|
+
right: 'ml-auto',
|
|
7
|
+
};
|
|
8
|
+
export function FieldGroup({ bordered = true, children, className, title, titleAlign = 'left' }) {
|
|
9
|
+
return (_jsxs("fieldset", { className: cn('rounded-xl px-4 pb-4 pt-2', bordered && 'border-app-border border', className), children: [_jsx("legend", { className: cn('text-foreground-muted px-2 text-xs font-medium', titleAlignClass[titleAlign]), children: title }), children] }));
|
|
10
|
+
}
|
|
11
|
+
export const FormSection = FieldGroup;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FormControlSize } from './form-control-helpers';
|
|
3
|
+
export interface FieldSkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
hasLabel?: boolean;
|
|
6
|
+
labelPosition?: 'top' | 'right' | 'bottom' | 'left';
|
|
7
|
+
size?: FormControlSize;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare const FieldSkeleton: {
|
|
11
|
+
({ isLoading, hasLabel, labelPosition, size, className, children, ...divProps }: FieldSkeletonProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
|
|
12
|
+
displayName: string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=FieldSkeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldSkeleton.d.ts","sourceRoot":"","sources":["../../src/components/FieldSkeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAgBD,eAAO,MAAM,aAAa;qFAQvB,kBAAkB;;CAsCpB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../utils/cn';
|
|
3
|
+
const labelSizeClasses = {
|
|
4
|
+
xs: 'h-4 w-20',
|
|
5
|
+
sm: 'h-4 w-24',
|
|
6
|
+
md: 'h-5 w-32',
|
|
7
|
+
lg: 'h-6 w-36',
|
|
8
|
+
};
|
|
9
|
+
const controlSizeClasses = {
|
|
10
|
+
xs: 'h-7',
|
|
11
|
+
sm: 'h-9',
|
|
12
|
+
md: 'h-12',
|
|
13
|
+
lg: 'h-14',
|
|
14
|
+
};
|
|
15
|
+
export const FieldSkeleton = ({ isLoading, hasLabel = true, labelPosition = 'top', size = 'md', className, children, ...divProps }) => {
|
|
16
|
+
const isHorizontal = labelPosition === 'left' || labelPosition === 'right';
|
|
17
|
+
const content = (_jsxs(_Fragment, { children: [hasLabel && (_jsx("div", { className: cn('block rounded bg-[color-mix(in_srgb,var(--foreground-muted)_18%,var(--surface))] dark:bg-[color-mix(in_srgb,var(--foreground-muted)_30%,var(--surface))]', labelSizeClasses[size], isHorizontal ? 'mb-0 shrink-0' : 'mb-1') })), _jsx("div", { className: cn('w-full animate-pulse rounded-md bg-[color-mix(in_srgb,var(--foreground-muted)_16%,var(--surface))] dark:bg-[color-mix(in_srgb,var(--foreground-muted)_28%,var(--surface))]', controlSizeClasses[size]) })] }));
|
|
18
|
+
if (isLoading) {
|
|
19
|
+
return (_jsx("div", { className: cn(isHorizontal ? 'flex items-center gap-2' : 'flex flex-col gap-1', labelPosition === 'right' && 'flex-row-reverse', className), ...divProps, children: content }));
|
|
20
|
+
}
|
|
21
|
+
return children;
|
|
22
|
+
};
|
|
23
|
+
FieldSkeleton.displayName = 'FieldSkeleton';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface FieldValidationErrorProps {
|
|
2
|
+
id?: string;
|
|
3
|
+
message?: string | null;
|
|
4
|
+
hasValidation?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function FieldValidationError({ id, message, hasValidation }: FieldValidationErrorProps): import("react").JSX.Element | null;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=FieldValidationError.d.ts.map
|