@axzydev/axzy_ui_system 1.2.9 → 1.2.12
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 +6 -0
- package/dist/index.cjs +313 -242
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +142 -6
- package/dist/index.d.ts +142 -6
- package/dist/index.js +313 -242
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/snippets/axzy-ui-system.code-snippets +547 -0
- package/src/App.tsx +37 -34
- package/src/components/avatar/avatar.props.ts +12 -1
- package/src/components/avatar/avatar.stories.tsx +19 -0
- package/src/components/avatar/avatar.tsx +27 -4
- package/src/components/calendar/calendar.tsx +1 -1
- package/src/components/card/card.tsx +11 -8
- package/src/components/confirm-dialog/confirm-dialog.tsx +1 -1
- package/src/components/data-table/dataTable.props.ts +10 -0
- package/src/components/data-table/dataTable.tsx +27 -16
- package/src/components/date-picker/datePicker.tsx +1 -1
- package/src/components/dialog/dialog.tsx +3 -2
- package/src/components/divider/divider.tsx +1 -1
- package/src/components/drawer/drawer.tsx +1 -1
- package/src/components/dropfile/dropfile.props.ts +6 -0
- package/src/components/dropfile/dropfile.tsx +65 -30
- package/src/components/form-builder/fieldRenderer.tsx +3 -3
- package/src/components/input/input.tsx +7 -7
- package/src/components/layout/layout.tsx +1 -1
- package/src/components/loader/loader.tsx +1 -1
- package/src/components/navbar/navbar.tsx +10 -10
- package/src/components/pagination/pagination.tsx +11 -11
- package/src/components/popover/popover.tsx +1 -1
- package/src/components/search-select/search-select.tsx +11 -11
- package/src/components/searchTable/components/EditableCell.tsx +1 -1
- package/src/components/searchTable/components/PaginationControls.tsx +2 -2
- package/src/components/searchTable/components/PaginationInfo.tsx +1 -1
- package/src/components/searchTable/components/SearchAndSortBar.tsx +1 -1
- package/src/components/searchTable/components/SearchInput.tsx +1 -1
- package/src/components/searchTable/components/SortButton.tsx +3 -3
- package/src/components/searchTable/components/TableHeader.tsx +1 -1
- package/src/components/searchTable/components/TableRow.tsx +4 -4
- package/src/components/searchTable/searchTable.tsx +2 -2
- package/src/components/select/select.tsx +8 -10
- package/src/components/sidebar/sidebar.tsx +29 -29
- package/src/components/slider/slider.tsx +3 -3
- package/src/components/stepper/stepper.props.ts +4 -0
- package/src/components/stepper/stepper.tsx +5 -5
- package/src/components/table/table.props.ts +21 -3
- package/src/components/table/table.tsx +27 -16
- package/src/components/tabs/tabs.tsx +4 -4
- package/src/components/textarea/textarea.tsx +3 -3
- package/src/components/theme-provider/themeProvider.props.ts +21 -3
- package/src/components/theme-provider/themeProvider.tsx +32 -32
- package/src/components/time-picker/timePicker.tsx +5 -5
- package/src/components/toast/toast.tsx +1 -1
- package/src/components/tooltip/tooltip.tsx +1 -1
- package/src/components/topbar/topbar.tsx +7 -7
- package/src/dev.css +1 -1
- package/src/hooks/useClickOutside.ts +8 -0
- package/src/hooks/useTableState.ts +5 -2
- package/src/index.css +24 -1
- package/src/showcases/HomeShowcase.tsx +95 -3
- package/src/theme/theme.ts +38 -17
- package/src/types/field.types.ts +70 -7
- package/src/utils/styles.ts +5 -5
package/src/theme/theme.ts
CHANGED
|
@@ -160,7 +160,7 @@ export const components = {
|
|
|
160
160
|
hover: semanticColors.primary[600],
|
|
161
161
|
active: semanticColors.primary[700],
|
|
162
162
|
focus: `0 0 0 2px ${semanticColors.primary[200]}`,
|
|
163
|
-
borderRadius: '
|
|
163
|
+
borderRadius: 'var(--radius-md)',
|
|
164
164
|
padding: '0.5rem 1rem',
|
|
165
165
|
fontSize: '0.875rem',
|
|
166
166
|
fontWeight: '600',
|
|
@@ -172,7 +172,7 @@ export const components = {
|
|
|
172
172
|
color: '#ffffff',
|
|
173
173
|
hover: semanticColors.secondary[600],
|
|
174
174
|
focus: `0 0 0 2px ${semanticColors.secondary[200]}`,
|
|
175
|
-
borderRadius: '
|
|
175
|
+
borderRadius: 'var(--radius-md)',
|
|
176
176
|
padding: '0.5rem 1rem',
|
|
177
177
|
fontSize: '0.875rem',
|
|
178
178
|
fontWeight: '600',
|
|
@@ -183,7 +183,7 @@ export const components = {
|
|
|
183
183
|
color: '#ffffff',
|
|
184
184
|
hover: semanticColors.success[600],
|
|
185
185
|
focus: `0 0 0 2px ${semanticColors.success[200]}`,
|
|
186
|
-
borderRadius: '
|
|
186
|
+
borderRadius: 'var(--radius-md)',
|
|
187
187
|
},
|
|
188
188
|
|
|
189
189
|
danger: {
|
|
@@ -191,14 +191,14 @@ export const components = {
|
|
|
191
191
|
color: '#ffffff',
|
|
192
192
|
hover: semanticColors.danger[600],
|
|
193
193
|
focus: `0 0 0 2px ${semanticColors.danger[200]}`,
|
|
194
|
-
borderRadius: '
|
|
194
|
+
borderRadius: 'var(--radius-md)',
|
|
195
195
|
},
|
|
196
196
|
|
|
197
197
|
error: {
|
|
198
198
|
backgroundColor: semanticColors.danger[500],
|
|
199
199
|
color: '#ffffff',
|
|
200
200
|
hover: semanticColors.danger[600],
|
|
201
|
-
borderRadius: '
|
|
201
|
+
borderRadius: 'var(--radius-md)',
|
|
202
202
|
},
|
|
203
203
|
|
|
204
204
|
warning: {
|
|
@@ -206,7 +206,7 @@ export const components = {
|
|
|
206
206
|
color: '#ffffff',
|
|
207
207
|
hover: semanticColors.warning[600],
|
|
208
208
|
focus: `0 0 0 2px ${semanticColors.warning[200]}`,
|
|
209
|
-
borderRadius: '
|
|
209
|
+
borderRadius: 'var(--radius-md)',
|
|
210
210
|
},
|
|
211
211
|
|
|
212
212
|
info: {
|
|
@@ -214,7 +214,7 @@ export const components = {
|
|
|
214
214
|
color: '#ffffff',
|
|
215
215
|
hover: semanticColors.info[600],
|
|
216
216
|
focus: `0 0 0 2px ${semanticColors.info[200]}`,
|
|
217
|
-
borderRadius: '
|
|
217
|
+
borderRadius: 'var(--radius-md)',
|
|
218
218
|
},
|
|
219
219
|
|
|
220
220
|
purple: {
|
|
@@ -222,7 +222,7 @@ export const components = {
|
|
|
222
222
|
color: '#ffffff',
|
|
223
223
|
hover: semanticColors.purple[600],
|
|
224
224
|
focus: `0 0 0 2px ${semanticColors.purple[200]}`,
|
|
225
|
-
borderRadius: '
|
|
225
|
+
borderRadius: 'var(--radius-md)',
|
|
226
226
|
},
|
|
227
227
|
|
|
228
228
|
outline: {
|
|
@@ -231,7 +231,7 @@ export const components = {
|
|
|
231
231
|
borderColor: semanticColors.primary[600],
|
|
232
232
|
borderWidth: '2px',
|
|
233
233
|
hover: semanticColors.primary[50],
|
|
234
|
-
borderRadius: '
|
|
234
|
+
borderRadius: 'var(--radius-md)',
|
|
235
235
|
},
|
|
236
236
|
},
|
|
237
237
|
|
|
@@ -291,19 +291,19 @@ export const components = {
|
|
|
291
291
|
|
|
292
292
|
card: {
|
|
293
293
|
backgroundColor: 'var(--card-bg, #ffffff)',
|
|
294
|
-
borderRadius: '
|
|
294
|
+
borderRadius: 'var(--radius-2xl)',
|
|
295
295
|
borderColor: `var(--card-border, ${semanticColors.gray[200]})`,
|
|
296
296
|
borderWidth: '1px',
|
|
297
|
-
shadow: 'var(--card-shadow,
|
|
297
|
+
shadow: 'var(--card-shadow, var(--shadow-md))',
|
|
298
298
|
hover: {
|
|
299
|
-
shadow: 'var(--card-shadow-hover,
|
|
299
|
+
shadow: 'var(--card-shadow-hover, var(--shadow-lg))',
|
|
300
300
|
},
|
|
301
301
|
header: {
|
|
302
302
|
backgroundColor: `var(--card-header-bg, ${semanticColors.gray[50]})`,
|
|
303
303
|
borderBottom: `1px solid var(--card-header-border, var(--color-secondary-200))`,
|
|
304
304
|
padding: '1rem 1.5rem',
|
|
305
|
-
borderTopLeftRadius: '
|
|
306
|
-
borderTopRightRadius: '
|
|
305
|
+
borderTopLeftRadius: 'var(--radius-2xl)',
|
|
306
|
+
borderTopRightRadius: 'var(--radius-2xl)',
|
|
307
307
|
},
|
|
308
308
|
body: {
|
|
309
309
|
padding: '1.5rem',
|
|
@@ -313,7 +313,7 @@ export const components = {
|
|
|
313
313
|
input: {
|
|
314
314
|
backgroundColor: 'var(--input-bg, #ffffff)',
|
|
315
315
|
borderColor: `var(--input-border, ${semanticColors.gray[300]})`,
|
|
316
|
-
borderRadius: '
|
|
316
|
+
borderRadius: 'var(--radius-md)',
|
|
317
317
|
padding: '0.5rem 0.75rem',
|
|
318
318
|
fontSize: '0.875rem',
|
|
319
319
|
focus: {
|
|
@@ -382,8 +382,8 @@ export const components = {
|
|
|
382
382
|
},
|
|
383
383
|
content: {
|
|
384
384
|
backgroundColor: 'var(--modal-bg, #ffffff)',
|
|
385
|
-
borderRadius: '
|
|
386
|
-
shadow: 'var(--modal-shadow,
|
|
385
|
+
borderRadius: 'var(--radius-2xl)',
|
|
386
|
+
shadow: 'var(--modal-shadow, var(--shadow-xl))',
|
|
387
387
|
},
|
|
388
388
|
header: {
|
|
389
389
|
padding: '1.5rem 1.5rem 0.5rem 1.5rem',
|
|
@@ -452,6 +452,26 @@ export const typography = {
|
|
|
452
452
|
},
|
|
453
453
|
};
|
|
454
454
|
|
|
455
|
+
/**
|
|
456
|
+
* 4.5. Escala de Z-Index (capas de UI global)
|
|
457
|
+
* Fuente de verdad documentada para las clases z-[N] usadas en overlays fixed/absolute.
|
|
458
|
+
* Tailwind JIT requiere clases estáticas en el JSX, así que los componentes aplican
|
|
459
|
+
* el valor literal correspondiente, pero SIEMPRE debe coincidir con esta escala.
|
|
460
|
+
* Orden ascendente = se pinta más arriba.
|
|
461
|
+
*/
|
|
462
|
+
export const zIndex = {
|
|
463
|
+
/** Barras sticky (ITTopbar) y overlays de navegación (sidebar/aside móvil). */
|
|
464
|
+
navOverlay: 40,
|
|
465
|
+
/** Paneles deslizantes (ITDrawer). */
|
|
466
|
+
drawer: 50,
|
|
467
|
+
/** Diálogos modales (ITDialog, ITConfirmDialog). */
|
|
468
|
+
modal: 60,
|
|
469
|
+
/** UI flotante contextual: dropdowns, ITPopover, ITTooltip, ITDatePicker/ITTimePicker. */
|
|
470
|
+
floating: 70,
|
|
471
|
+
/** Notificaciones globales (ITToast) — siempre por encima de todo lo demás. */
|
|
472
|
+
toast: 80,
|
|
473
|
+
} as const;
|
|
474
|
+
|
|
455
475
|
/**
|
|
456
476
|
* 5. Theme final exportado
|
|
457
477
|
*/
|
|
@@ -459,5 +479,6 @@ export const theme = {
|
|
|
459
479
|
palette,
|
|
460
480
|
colors: semanticColors,
|
|
461
481
|
typography,
|
|
482
|
+
zIndex,
|
|
462
483
|
...components,
|
|
463
484
|
};
|
package/src/types/field.types.ts
CHANGED
|
@@ -2,26 +2,47 @@ import React from "react";
|
|
|
2
2
|
import * as Yup from "yup";
|
|
3
3
|
|
|
4
4
|
// Legacy FieldConfig (kept for backward compatibility during migration)
|
|
5
|
+
/** @deprecated Legacy (V1) field definition consumed by `ITFormBuilder`'s `fields` prop. Prefer `FieldConfigV2` via the `config` prop for new forms. */
|
|
5
6
|
export interface FieldConfig {
|
|
7
|
+
/** Field name, matches the key in Formik's `values`/`errors`/`touched` objects. */
|
|
6
8
|
name: string;
|
|
9
|
+
/** Label text rendered above the field. */
|
|
7
10
|
label: string;
|
|
11
|
+
/** Input type. @default "text" */
|
|
8
12
|
type?: "text" | "select" | "date" | "password" | "number";
|
|
13
|
+
/** Formats a numeric field with thousands separators/currency styling as the user types. @default false */
|
|
9
14
|
currencyFormat?: boolean;
|
|
15
|
+
/** Placeholder text shown when the field is empty. */
|
|
10
16
|
placeholder?: string;
|
|
17
|
+
/** Disables the field. @default false */
|
|
11
18
|
disabled?: boolean;
|
|
19
|
+
/** Marks the field as required (shows an asterisk and enables the built-in required message). @default false */
|
|
12
20
|
required?: boolean;
|
|
21
|
+
/** Yup schema used to validate this field. */
|
|
13
22
|
validation?: Yup.AnySchema;
|
|
23
|
+
/** Grid column span (1-12), or `[sm, md, lg]` breakpoint-specific spans. */
|
|
14
24
|
column?: number | number[];
|
|
25
|
+
/** Options for `type: "select"`. */
|
|
15
26
|
options?: { value: string; label: string }[];
|
|
27
|
+
/** Icon element rendered on the right side of the field. */
|
|
16
28
|
rightIcon?: React.ReactNode;
|
|
29
|
+
/** Icon element rendered on the left side of the field. */
|
|
17
30
|
leftIcon?: React.ReactNode;
|
|
31
|
+
/** Key read from each option object as its value. @default "value" */
|
|
18
32
|
valueField?: string;
|
|
33
|
+
/** Shows a live character-count hint below the field. @default false */
|
|
19
34
|
showHintLength?: boolean;
|
|
35
|
+
/** Key read from each option object as its display label. @default "label" */
|
|
20
36
|
labelField?: string;
|
|
37
|
+
/** Maximum character length allowed. */
|
|
21
38
|
maxLength?: number;
|
|
39
|
+
/** Minimum character length required. */
|
|
22
40
|
minLength?: number;
|
|
41
|
+
/** Number of visible text rows for a multi-line field. */
|
|
23
42
|
rows?: number;
|
|
43
|
+
/** Applies number formatting (thousand separators) as the user types. @default false */
|
|
24
44
|
formatNumber?: boolean;
|
|
45
|
+
/** Custom side-effect fired on change, in addition to the normal Formik update. Receives the new value and Formik's `setFieldValue`. */
|
|
25
46
|
onChangeAction?: (value: any, setFieldValue: any) => void;
|
|
26
47
|
}
|
|
27
48
|
|
|
@@ -29,6 +50,7 @@ export interface FieldConfig {
|
|
|
29
50
|
// V2: ENTERPRISE FORM BUILDER ARCHITECTURE
|
|
30
51
|
// -------------------------------------------------------------
|
|
31
52
|
|
|
53
|
+
/** Supported field kinds for `FieldConfigV2`. */
|
|
32
54
|
export type FieldTypeV2 =
|
|
33
55
|
| "text"
|
|
34
56
|
| "number"
|
|
@@ -43,61 +65,102 @@ export type FieldTypeV2 =
|
|
|
43
65
|
| "section" // For grouping fields or wizard steps
|
|
44
66
|
| "custom"; // For inversion of control (injecting external components)
|
|
45
67
|
|
|
68
|
+
/** Form state/helpers passed into `dynamicProps`, `renderWhen`, and `onChangeAction` callbacks for `FieldConfigV2`. */
|
|
46
69
|
export interface FieldContextV2 {
|
|
70
|
+
/** Current values for every field in the form, keyed by field `name`. */
|
|
47
71
|
values: Record<string, any>;
|
|
72
|
+
/** Programmatically sets a field's value (mirrors Formik's `setFieldValue`). */
|
|
48
73
|
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;
|
|
74
|
+
/** Programmatically sets a field-level error message. */
|
|
49
75
|
setFieldError: (field: string, error: string) => void;
|
|
76
|
+
/** Programmatically marks a field as touched, e.g. to surface its validation error. */
|
|
50
77
|
setFieldTouched: (field: string, touched?: boolean, shouldValidate?: boolean) => void;
|
|
51
78
|
}
|
|
52
79
|
|
|
80
|
+
/**
|
|
81
|
+
* V2 field definition consumed by `ITFormBuilder`'s `config` prop. Supports
|
|
82
|
+
* conditional rendering/props, nested sections and repeatable arrays, async
|
|
83
|
+
* options, and custom-component injection.
|
|
84
|
+
*/
|
|
53
85
|
export interface FieldConfigV2 {
|
|
86
|
+
/** Field name, matches the key in Formik's `values`/`errors`/`touched` objects. For `type: "array"`/`"section"`, this is the key under which the nested `fields` values are grouped. */
|
|
54
87
|
name: string;
|
|
88
|
+
/** Label text rendered above the field (or as the section/array heading). */
|
|
55
89
|
label?: string;
|
|
90
|
+
/** Field kind. Determines which input is rendered and which of the props below apply. */
|
|
56
91
|
type: FieldTypeV2;
|
|
57
|
-
|
|
92
|
+
|
|
58
93
|
// 1. Layout & Structure
|
|
94
|
+
/** Grid column span (1-12), or an object with per-breakpoint spans (`sm`/`md`/`lg`/`xl`). */
|
|
59
95
|
column?: number | { sm?: number; md?: number; lg?: number; xl?: number };
|
|
96
|
+
/** Nested field definitions. Required when `type` is `"array"` (the repeatable item shape) or `"section"` (the grouped fields). */
|
|
60
97
|
fields?: FieldConfigV2[]; // REQUIRED if type is "array" or "section"
|
|
98
|
+
/** For `type: "section"`, allows the section to be collapsed/expanded by the user. @default false */
|
|
61
99
|
collapsible?: boolean; // Optional for "section", default false
|
|
100
|
+
/** For a `collapsible` section, whether it starts collapsed. @default false */
|
|
62
101
|
defaultCollapsed?: boolean;
|
|
63
|
-
|
|
102
|
+
|
|
64
103
|
// 2. Rules Engine & Dynamic Behavior
|
|
104
|
+
/** Sibling field names this field depends on; changes to any of them re-evaluate `renderWhen`/`dynamicProps`. */
|
|
65
105
|
dependsOn?: string[]; // Array of sibling field names to listen to for re-evaluation
|
|
106
|
+
/** Determines whether this field is rendered (and included in submission) based on current form values. Re-evaluated when any field in `dependsOn` changes. Field is shown when omitted. */
|
|
66
107
|
renderWhen?: (values: Record<string, any>) => boolean; // If false, field isn't rendered or submitted
|
|
108
|
+
/** Computes a partial override of this field's own config from current form values (e.g. make it `required` once another field exceeds a threshold). Re-evaluated when any field in `dependsOn` changes. */
|
|
67
109
|
dynamicProps?: (values: Record<string, any>) => Partial<FieldConfigV2>; // E.g: if A > 100, make this required
|
|
68
|
-
|
|
110
|
+
|
|
69
111
|
// 3. Advanced Validations
|
|
112
|
+
/** Yup schema used to validate this field. */
|
|
70
113
|
validation?: Yup.AnySchema;
|
|
114
|
+
/** Async validator (e.g. a uniqueness check against an API). Return an error string when invalid, or `null`/`undefined` when valid. */
|
|
71
115
|
asyncValidation?: (value: any, values: Record<string, any>) => Promise<string | null | undefined>; // Returns error string if invalid
|
|
72
|
-
|
|
116
|
+
|
|
73
117
|
// 4. Base Props
|
|
118
|
+
/** Initial value used when the form is first initialized/reset. */
|
|
74
119
|
defaultValue?: any;
|
|
120
|
+
/** Placeholder text shown when the field is empty. */
|
|
75
121
|
placeholder?: string;
|
|
122
|
+
/** Disables the field, either statically or computed from current form values. @default false */
|
|
76
123
|
disabled?: boolean | ((values: Record<string, any>) => boolean);
|
|
124
|
+
/** Renders the field as read-only (visible but not editable). @default false */
|
|
77
125
|
readOnly?: boolean;
|
|
126
|
+
/** Marks the field as required, either statically or computed from current form values. @default false */
|
|
78
127
|
required?: boolean | ((values: Record<string, any>) => boolean);
|
|
79
|
-
|
|
128
|
+
|
|
80
129
|
// 5. Data Support (Sync & Async)
|
|
130
|
+
/** Options for `"select"`/`"radio"` fields: a static array, or an async loader function called once the field mounts. */
|
|
81
131
|
options?:
|
|
82
132
|
| { value: string | number; label: string }[]
|
|
83
133
|
| (() => Promise<{ value: string | number; label: string }[]>);
|
|
134
|
+
/** Key read from each option object as its value. @default "value" */
|
|
84
135
|
valueField?: string;
|
|
136
|
+
/** Key read from each option object as its display label. @default "label" */
|
|
85
137
|
labelField?: string;
|
|
86
|
-
|
|
138
|
+
|
|
87
139
|
// 6. Extensibility & UI
|
|
140
|
+
/** Icon element rendered on the left side of the field. */
|
|
88
141
|
leftIcon?: React.ReactNode;
|
|
142
|
+
/** Icon element rendered on the right side of the field. */
|
|
89
143
|
rightIcon?: React.ReactNode;
|
|
144
|
+
/** Custom component rendered instead of a built-in input when `type` is `"custom"`. */
|
|
90
145
|
component?: React.ComponentType<any>; // Custom component for type === "custom"
|
|
146
|
+
/** Additional CSS class applied to the field's container. */
|
|
91
147
|
className?: string; // Custom container class
|
|
92
|
-
|
|
148
|
+
|
|
93
149
|
// Legacy specific overrides
|
|
150
|
+
/** Formats a numeric field with thousands separators/currency styling as the user types. @default false */
|
|
94
151
|
currencyFormat?: boolean;
|
|
152
|
+
/** Shows a live character-count hint below the field. @default false */
|
|
95
153
|
showHintLength?: boolean;
|
|
154
|
+
/** Maximum character length allowed. */
|
|
96
155
|
maxLength?: number;
|
|
156
|
+
/** Minimum character length required. */
|
|
97
157
|
minLength?: number;
|
|
158
|
+
/** Number of visible text rows for a multi-line field. */
|
|
98
159
|
rows?: number;
|
|
160
|
+
/** Applies number formatting (thousand separators) as the user types. @default false */
|
|
99
161
|
formatNumber?: boolean;
|
|
100
162
|
|
|
101
163
|
// Lifecycle hook
|
|
164
|
+
/** Custom side-effect fired whenever this field's value changes. Receives the new value and the shared `FieldContextV2` helpers. */
|
|
102
165
|
onChangeAction?: (val: any, context: FieldContextV2) => void | Promise<void>;
|
|
103
166
|
}
|
package/src/utils/styles.ts
CHANGED
|
@@ -9,20 +9,20 @@ export function inputContainer(hasError?: boolean, disabled?: boolean) {
|
|
|
9
9
|
"w-full border border-solid transition-all duration-200 rounded-lg px-3 py-2 text-sm",
|
|
10
10
|
"focus:outline-none focus:ring-2",
|
|
11
11
|
hasError
|
|
12
|
-
? "border-
|
|
13
|
-
: "border-
|
|
14
|
-
disabled && "opacity-50 cursor-not-allowed bg-
|
|
12
|
+
? "border-danger-500 ring-danger-100"
|
|
13
|
+
: "border-secondary-300 focus:border-primary-500 focus:ring-primary-100",
|
|
14
|
+
disabled && "opacity-50 cursor-not-allowed bg-secondary-100"
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function inputLabel(error?: boolean) {
|
|
19
19
|
return clsx(
|
|
20
20
|
"text-sm font-medium",
|
|
21
|
-
error ? "text-
|
|
21
|
+
error ? "text-danger-500" : "text-secondary-700 dark:text-secondary-300"
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const inputError = "text-
|
|
25
|
+
export const inputError = "text-danger-500 text-xs mt-1";
|
|
26
26
|
|
|
27
27
|
export function inputWrapper(className?: string) {
|
|
28
28
|
return clsx("flex flex-col gap-1.5", className);
|