laif-ds 0.2.75 → 0.2.77

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.
@@ -11,8 +11,10 @@ Dynamic form component that integrates with React Hook Form to provide a configu
11
11
  ### AppFormItem
12
12
 
13
13
  ```ts
14
- export interface AppFormItem {
15
- label: string; // Field label
14
+ export type AppFormItem<TAsyncOption = unknown> = {
15
+ /** Field label displayed above the component. */
16
+ label: string;
17
+ /** The type of form component to render. */
16
18
  component:
17
19
  | "input"
18
20
  | "select"
@@ -24,29 +26,98 @@ export interface AppFormItem {
24
26
  | "switch"
25
27
  | "slider"
26
28
  | "async"
27
- | "async-multiple"; // Field type
28
- name: string; // Field name (used for form state and validation)
29
- inputType?: ComponentProps<"input">["type"]; // HTML input type for "input" component (e.g. "text", "email", "password", "number", "url", "search", "tel")
30
- defaultValue?: string | boolean | number | string[] | Date | number[]; // Initial value
31
- options?: AppSelectOption[]; // Options for select/multiselect/radio
32
- disabled?: boolean; // Disables the field
33
- placeholder?: string; // Placeholder text
34
- caption?: string; // Helper text below the field
35
- calendarRange?: [Date, Date]; // Date range for datepicker (enables range mode)
36
- min?: number; // Minimum value for slider
37
- max?: number; // Maximum value for slider
38
- step?: number; // Step value for slider
39
- fetcher?: (query?: string) => Promise<any[]>; // Async select data loader
40
- renderOptionItem?: (option: any) => React.ReactNode; // Customize render of async option
41
- resolveOptionValue?: (option: any) => string; // Value extractor for async option
42
- renderSelectedValue?: (option: any) => React.ReactNode; // Customize render of selected async option
43
- initialOptions?: any[]; // Optional cache for async select hydration
44
- notFound?: React.ReactNode; // Custom not found message for async select
45
- noResultsMessage?: string; // No results message for async select
46
- debounce?: number; // Debounce time for async select search
47
- clearable?: boolean; // Allow clearing async select value
48
- datePickerProps?: Partial<ComponentProps<typeof DatePicker>>; // Additional DatePicker props (locale, dateFormat, numberOfMonths, minDate, maxDate, etc.)
49
- }
29
+ | "async-multiple"
30
+ | "custom";
31
+ /** Field name used for React Hook Form state binding and validation. */
32
+ name: string;
33
+ /**
34
+ * HTML input type. Only applies when `component` is `"input"`.
35
+ * @example "text" | "email" | "password" | "number" | "url" | "search" | "tel"
36
+ */
37
+ inputType?: ComponentProps<"input">["type"];
38
+ /** Initial value for the field. */
39
+ defaultValue?: string | boolean | number | string[] | Date | number[];
40
+ /** Options list for `select`, `multiselect`, and `radio` components. */
41
+ options?: AppSelectOption[];
42
+ /** Disables the field, preventing user interaction. @default false */
43
+ disabled?: boolean;
44
+ /** Placeholder text shown when no value is selected or entered. */
45
+ placeholder?: string;
46
+ /** Helper text displayed below the field. */
47
+ caption?: string;
48
+ /**
49
+ * Enables range mode on the `datepicker` component when provided.
50
+ * The two dates define the selectable calendar boundaries.
51
+ */
52
+ calendarRange?: [Date, Date];
53
+ /** Minimum value for the `slider` component. @default 0 */
54
+ min?: number;
55
+ /** Maximum value for the `slider` component. @default 100 */
56
+ max?: number;
57
+ /** Step increment for the `slider` component. @default 1 */
58
+ step?: number;
59
+ /**
60
+ * Async data loader for `async` and `async-multiple` components.
61
+ * Called with the current search query; must return a promise of options.
62
+ */
63
+ fetcher?: (query?: string) => Promise<TAsyncOption[]>;
64
+ /**
65
+ * Custom render function for each option item in the async dropdown.
66
+ * Required for `async` and `async-multiple` components.
67
+ */
68
+ renderOptionItem?: (option: TAsyncOption) => React.ReactNode;
69
+ /**
70
+ * Extracts the unique string value from an async option object.
71
+ * Required for `async` and `async-multiple` components.
72
+ */
73
+ resolveOptionValue?: (option: TAsyncOption) => string;
74
+ /**
75
+ * Custom render function for the selected value chip/label.
76
+ * Required for `async` and `async-multiple` components.
77
+ */
78
+ renderSelectedValue?: (option: TAsyncOption) => React.ReactNode;
79
+ /**
80
+ * Pre-loaded options used to hydrate the async select on mount,
81
+ * avoiding an initial fetch when the value is already known.
82
+ */
83
+ initialOptions?: TAsyncOption[];
84
+ /** Custom node displayed when the async fetcher returns no results at all. */
85
+ notFound?: React.ReactNode;
86
+ /** Message shown when the async search query returns no matching results. */
87
+ noResultsMessage?: string;
88
+ /** Debounce delay in milliseconds for the async search input. @default 300 */
89
+ debounce?: number;
90
+ /** Allows the user to clear the selected value in the async select. @default false */
91
+ clearable?: boolean;
92
+ /** Extra props forwarded directly to the `DatePicker` component. */
93
+ datePickerProps?: Partial<DatePickerProps>;
94
+ /** Column span for the item in the grid. @default undefined (auto, or "full" for the last item) */
95
+ colSpan?: "1" | "2" | "3" | "full";
96
+ /** Icon on the left side. Only applies when `component` is `"input"`. */
97
+ iconLeft?: IconName;
98
+ /** Icon on the right side. Only applies when `component` is `"input"`. */
99
+ iconRight?: IconName;
100
+ /** Enables search/filter inside `select` and `multiselect` dropdowns. @default true */
101
+ searchable?: boolean;
102
+ /** Hides the label above the field. @default false */
103
+ hideLabel?: boolean;
104
+ /** Additional CSS class name applied to the item container div. */
105
+ className?: string;
106
+ /**
107
+ * Additional props forwarded to the underlying UI component.
108
+ * Strongly typed based on the chosen `component` value.
109
+ */
110
+ componentProps?: AppFormItemComponentProps[TComponent];
111
+ /**
112
+ * Custom render function for the component.
113
+ * Required when `component` is `"custom"`.
114
+ */
115
+ render?: (props: {
116
+ field: ControllerRenderProps<FieldValues, string>;
117
+ error?: string;
118
+ label: React.ReactNode;
119
+ }) => React.ReactNode;
120
+ };
50
121
  ```
51
122
 
52
123
  ### Submit Button Inside vs Outside
@@ -103,12 +174,12 @@ export function SubmitInsideVsOutside() {
103
174
 
104
175
  | Prop | Type | Default | Description |
105
176
  | ------------------ | --------------------- | ------------ | -------------------------------------------------------- |
106
- | `items` | `AppFormItem[]` | **required** | Array of form field configurations |
107
- | `form` | `UseFormReturn<any>` | **required** | React Hook Form instance |
177
+ | `items` | `AppFormItem[]` | **required** | Array of field configurations |
178
+ | `form` | `UseFormReturn<any>` | **required** | React Hook Form instance returned by `useForm` |
108
179
  | `cols` | `"1" \| "2" \| "3"` | `"2"` | Number of grid columns |
109
- | `submitText` | `string` | `"Invia"` | Text for submit button |
110
- | `onSubmit` | `(data: any) => void` | `undefined` | Form submission callback |
111
- | `isSubmitting` | `boolean` | `false` | Shows loading state on submit button |
180
+ | `submitText` | `string` | `"Invia"` | Text label for the internal submit button |
181
+ | `onSubmit` | `(data: any) => void` | `undefined` | Callback fired with validated form data on submission |
182
+ | `isSubmitting` | `boolean` | `false` | Shows loading spinner on the submit button |
112
183
  | `showSubmitButton` | `boolean` | `false` | Renders an internal submit button at the end of the form |
113
184
 
114
185
  ---
@@ -117,9 +188,9 @@ export function SubmitInsideVsOutside() {
117
188
 
118
189
  - **React Hook Form Integration**: Uses `Controller` from React Hook Form for each field
119
190
  - **Validation Display**: Shows validation errors inline with each field
120
- - **Grid Layout**: Automatically arranges fields in a responsive grid based on `cols` prop
191
+ - **Grid Layout**: Automatically arranges fields in a responsive grid based on `cols` prop. Use `colSpan` on items for fine-grained control.
121
192
  - **Submit Button**: Rendered only when `showSubmitButton` is `true`. When shown, it is disabled when the form is invalid or pristine. Otherwise, manage submit externally with `form.handleSubmit(...)`.
122
- - **Last Field Spanning**: The last field automatically spans full width
193
+ - **Last Field Spanning**: The last field automatically spans full width unless `colSpan` is explicitly set.
123
194
  - **Error Highlighting**: Fields with errors get red border styling
124
195
 
125
196
  ---
@@ -128,360 +199,102 @@ export function SubmitInsideVsOutside() {
128
199
 
129
200
  ### input
130
201
 
131
- Standard text input field
132
-
133
- Standard text input field. When `component: "input"`, you can use the `inputType` property to control the underlying HTML input type (e.g. `"text"`, `"email"`, `"password"`, `"number"`, `"url"`).
134
-
135
- For a complete showcase of different input types, see the Storybook story `UI/AppForm/DifferentInputTypes`.
202
+ Standard text input field. Supports `iconLeft` and `iconRight`.
136
203
 
137
- ### textarea
204
+ When `component: "input"`, use the `inputType` property to control the underlying HTML input type (e.g. `"text"`, `"email"`, `"password"`, `"number"`, `"url"`).
138
205
 
139
- Multi-line text area
206
+ ### select / multiselect
140
207
 
141
- ### select
208
+ Single or multiple selection dropdown using `AppSelect`. Supports `searchable: true`.
142
209
 
143
- Single selection dropdown using AppSelect
210
+ ### custom
144
211
 
145
- ### multiselect
212
+ Allows rendering any arbitrary content within the form grid. Requires the `render` function.
146
213
 
147
- Multiple selection dropdown using AppSelect with `multiple` prop
214
+ ```tsx
215
+ {
216
+ label: "Custom Section",
217
+ component: "custom",
218
+ name: "customInfo",
219
+ render: ({ field, error, label }) => (
220
+ <div className="p-4 border rounded">
221
+ {label}
222
+ <input {...field} className="border p-2" />
223
+ {error && <span className="text-red-500">{error}</span>}
224
+ </div>
225
+ ),
226
+ colSpan: "full"
227
+ }
228
+ ```
148
229
 
149
230
  ### async / async-multiple
150
231
 
151
- Use `AsyncSelect` for server-side driven selects. `async` gestisce un valore singolo, `async-multiple` un array di stringhe. Richiede i seguenti prop sull'item:
152
-
153
- - `fetcher`: funzione che restituisce `Promise<Option[]>`
154
- - `renderOptionItem`, `resolveOptionValue`, `renderSelectedValue`: per gestire il rendering e la selezione
155
- - `initialOptions` (opzionale ma consigliata) per idratare i valori preimpostati
156
- - `defaultValue` va impostato nei `defaultValues` di React Hook Form
232
+ Use `AsyncSelect` for server-side driven selects. `async` handles a single string value, `async-multiple` an array of strings.
157
233
 
158
- Esempio:
159
-
160
- ```tsx
161
- const items: AppFormItem[] = [
162
- {
163
- component: "async",
164
- name: "business",
165
- label: "Business (async)",
166
- placeholder: "Seleziona un business",
167
- fetcher: mockAsyncSelectFetcher,
168
- initialOptions: asyncSelectMockUsers,
169
- renderOptionItem: (user) => (
170
- <div>
171
- <strong>{user.name}</strong>
172
- <span className="text-muted-foreground text-xs">{user.email}</span>
173
- </div>
174
- ),
175
- resolveOptionValue: (user) => user.id,
176
- renderSelectedValue: (user) => user.name,
177
- },
178
- {
179
- component: "async-multiple",
180
- name: "team",
181
- label: "Team (async)",
182
- placeholder: "Seleziona i membri",
183
- fetcher: mockAsyncSelectFetcher,
184
- initialOptions: asyncSelectMockUsers,
185
- renderOptionItem: (user) => user.name,
186
- resolveOptionValue: (user) => user.id,
187
- renderSelectedValue: (user) => user.name,
188
- },
189
- ];
234
+ Required props for both: `fetcher`, `renderOptionItem`, `resolveOptionValue`, `renderSelectedValue`.
190
235
 
191
- const form = useForm({
192
- defaultValues: {
193
- business: asyncSelectMockUsers[0]?.id ?? "",
194
- team: asyncSelectMockUsers.slice(0, 2).map((u) => u.id),
195
- },
196
- });
197
- ```
236
+ ### datepicker
198
237
 
199
- Ricorda che il fetch parte solo quando il menu è aperto; eventuali valori iniziali devono essere già presenti in `initialOptions`.
238
+ Date picker component with optional range selection via `calendarRange`. Pass `datePickerProps` for locale, format, or other `DatePicker` customisation.
200
239
 
201
- ### datepicker
240
+ ### radio / checkbox / switch / slider
202
241
 
203
- Date picker component with optional range selection via `calendarRange`. Use `datePickerProps` to customize the DatePicker behavior such as locale, date format, number of months displayed, min/max dates, etc.
242
+ Standard form components for various input types.
204
243
 
205
- **Available datePickerProps options:**
244
+ ---
206
245
 
207
- - `locale`: Locale object from `date-fns/locale` (e.g., `enUS`, `it`, `fr`)
208
- - `dateFormat`: Date format string (e.g., `"MM/dd/yyyy"`, `"dd/MM/yyyy"`)
209
- - `numberOfMonths`: Number of months to display in the calendar
210
- - `minDate`: Minimum selectable date
211
- - `maxDate`: Maximum selectable date
212
- - `firstDate`: First available date (disables dates before)
213
- - `lastDate`: Last available date (disables dates after)
214
- - `availableDates`: Array of specific dates that are selectable
215
- - `showTime`: Show time picker columns (HH, MM)
216
- - `withSeconds`: Show seconds column in the time picker (requires `showTime`)
217
- - `minuteStep`: Minute step interval for the time picker
218
- - `secondStep`: Second step interval for the time picker
219
- - And other DatePicker props
246
+ ## Examples
220
247
 
221
- **Example with English locale:**
248
+ ### Grid and Icons Example
222
249
 
223
250
  ```tsx
224
- import { enUS } from "date-fns/locale";
225
-
226
251
  const items: AppFormItem[] = [
227
252
  {
228
- label: "Appointment Date",
229
- component: "datepicker",
230
- name: "appointmentDate",
231
- placeholder: "Pick a date",
232
- datePickerProps: {
233
- locale: enUS,
234
- dateFormat: "MM/dd/yyyy HH:mm",
235
- showTime: true,
236
- },
253
+ label: "First Name",
254
+ component: "input",
255
+ name: "firstName",
256
+ colSpan: "1",
237
257
  },
238
258
  {
239
- label: "Event Date Range",
240
- component: "datepicker",
241
- name: "eventRange",
242
- placeholder: "Select date range",
243
- calendarRange: [new Date(), new Date()],
244
- datePickerProps: {
245
- locale: enUS,
246
- dateFormat: "MM/dd/yyyy",
247
- numberOfMonths: 2,
248
- },
259
+ label: "Last Name",
260
+ component: "input",
261
+ name: "lastName",
262
+ colSpan: "1",
263
+ },
264
+ {
265
+ label: "Email",
266
+ component: "input",
267
+ name: "email",
268
+ iconLeft: "Mail",
269
+ colSpan: "full",
270
+ },
271
+ {
272
+ label: "Department",
273
+ component: "select",
274
+ name: "dept",
275
+ options: [
276
+ /* ... */
277
+ ],
278
+ colSpan: "full",
249
279
  },
250
280
  ];
251
- ```
252
-
253
- ### radio
254
-
255
- Radio button group with options
256
-
257
- ### checkbox
258
-
259
- Single checkbox with label
260
-
261
- ### switch
262
-
263
- Toggle switch with label and optional caption
264
-
265
- ### slider
266
-
267
- Range slider with min/max/step configuration
268
-
269
- ---
270
-
271
- ## Examples
272
-
273
- ### Basic Form
274
-
275
- ```tsx
276
- import { AppForm } from "laif-ds";
277
- import { useForm } from "react-hook-form";
278
-
279
- export function BasicForm() {
280
- const form = useForm();
281
281
 
282
- return (
283
- <AppForm
284
- form={form}
285
- items={[
286
- {
287
- label: "Name",
288
- component: "input",
289
- name: "name",
290
- placeholder: "Enter your name",
291
- },
292
- {
293
- label: "Email",
294
- component: "input",
295
- name: "email",
296
- inputType: "email",
297
- placeholder: "Enter your email",
298
- },
299
- {
300
- label: "Message",
301
- component: "textarea",
302
- name: "message",
303
- placeholder: "Enter your message",
304
- },
305
- ]}
306
- onSubmit={(data) => console.log(data)}
307
- />
308
- );
309
- }
282
+ return <AppForm form={form} items={items} cols="2" showSubmitButton />;
310
283
  ```
311
284
 
312
- ### Full Feature Form
313
-
314
- ```tsx
315
- import { AppForm } from "laif-ds";
316
- import { useForm } from "react-hook-form";
317
- import { zodResolver } from "@hookform/resolvers/zod";
318
- import { z } from "zod";
319
-
320
- const schema = z.object({
321
- name: z.string().min(1, "Name is required"),
322
- category: z.string(),
323
- isActive: z.boolean(),
324
- priority: z.number(),
325
- });
326
-
327
- export function FullFeatureForm() {
328
- const form = useForm({
329
- resolver: zodResolver(schema),
330
- defaultValues: {
331
- name: "",
332
- category: "",
333
- isActive: false,
334
- priority: 5,
335
- },
336
- });
337
-
338
- return (
339
- <AppForm
340
- form={form}
341
- cols="2"
342
- items={[
343
- {
344
- label: "Name",
345
- component: "input",
346
- name: "name",
347
- placeholder: "Enter name",
348
- },
349
- {
350
- label: "Category",
351
- component: "select",
352
- name: "category",
353
- options: [
354
- { value: "tech", label: "Technology" },
355
- { value: "design", label: "Design" },
356
- { value: "marketing", label: "Marketing" },
357
- ],
358
- },
359
- {
360
- label: "Active",
361
- component: "switch",
362
- name: "isActive",
363
- caption: "Enable this option",
364
- },
365
- {
366
- label: "Priority",
367
- component: "slider",
368
- name: "priority",
369
- min: 1,
370
- max: 10,
371
- step: 1,
372
- },
373
- ]}
374
- submitText="Save"
375
- onSubmit={(data) => console.log(data)}
376
- />
377
- );
378
- }
379
- ```
285
+ ### Advanced componentProps
380
286
 
381
- ### With Date Range
287
+ Use `componentProps` to pass specific properties to the underlying UI components that are not exposed directly in `AppFormItem`.
382
288
 
383
289
  ```tsx
384
- import { AppForm } from "laif-ds";
385
- import { useForm } from "react-hook-form";
386
-
387
- export function DateRangeForm() {
388
- const form = useForm();
389
- const startDate = new Date();
390
- const endDate = new Date();
391
- endDate.setMonth(endDate.getMonth() + 1);
392
-
393
- return (
394
- <AppForm
395
- form={form}
396
- items={[
397
- {
398
- label: "Date Range",
399
- component: "datepicker",
400
- name: "dateRange",
401
- calendarRange: [startDate, endDate],
402
- },
403
- ]}
404
- onSubmit={(data) => console.log(data)}
405
- />
406
- );
407
- }
408
- ```
409
-
410
- ### External Form Control
411
-
412
- You can access the form instance to programmatically control values, watch changes, and reset the form:
413
-
414
- ```tsx
415
- import { AppForm, Button } from "laif-ds";
416
- import { useForm } from "react-hook-form";
417
- import { useState, useEffect } from "react";
418
-
419
- export function ExternalControlForm() {
420
- const [formValues, setFormValues] = useState({});
421
- const [watchedValues, setWatchedValues] = useState({});
422
-
423
- const form = useForm({
424
- defaultValues: {
425
- name: "",
426
- email: "",
427
- },
428
- });
429
-
430
- const { watch, setValue, reset } = form;
431
-
432
- // Watch specific fields
433
- const nameValue = watch("name");
434
- const emailValue = watch("email");
435
-
436
- // Auto-fill handler
437
- const handleAutoFill = () => {
438
- setValue("name", "Mario Rossi");
439
- setValue("email", "mario@example.com");
440
- };
441
-
442
- // Reset handler
443
- const handleReset = () => {
444
- reset();
445
- setFormValues({});
446
- setWatchedValues({});
447
- };
448
-
449
- // Watch all form values
450
- useEffect(() => {
451
- const subscription = watch((values) => {
452
- setWatchedValues(values);
453
- });
454
- return () => subscription.unsubscribe();
455
- }, [watch]);
456
-
457
- return (
458
- <div>
459
- <div className="mb-4 flex gap-2">
460
- <Button type="button" variant="outline" onClick={handleAutoFill}>
461
- Auto-fill
462
- </Button>
463
- <Button type="button" variant="outline" onClick={handleReset}>
464
- Reset
465
- </Button>
466
- </div>
467
-
468
- <AppForm
469
- form={form}
470
- items={[
471
- { label: "Name", component: "input", name: "name" },
472
- { label: "Email", component: "input", name: "email" },
473
- ]}
474
- onSubmit={(data) => setFormValues(data)}
475
- showSubmitButton
476
- />
477
-
478
- <div className="mt-4">
479
- <p>Name: {nameValue || "(empty)"}</p>
480
- <p>Email: {emailValue || "(empty)"}</p>
481
- <pre>{JSON.stringify(watchedValues, null, 2)}</pre>
482
- </div>
483
- </div>
484
- );
290
+ {
291
+ label: "Bio",
292
+ component: "textarea",
293
+ name: "bio",
294
+ componentProps: {
295
+ rows: 10,
296
+ className: "resize-none"
297
+ }
485
298
  }
486
299
  ```
487
300
 
@@ -490,7 +303,5 @@ export function ExternalControlForm() {
490
303
  ## Notes
491
304
 
492
305
  - **React Hook Form Required**: This component requires React Hook Form to be installed and configured
493
- - **Validation**: Use React Hook Form's resolver (e.g., Zod, Yup) for validation
494
306
  - **Grid Layout**: The grid uses Tailwind's grid system with `grid-cols-{n}` classes
495
- - **Submit Button**: Use `showSubmitButton` to render the internal submit button at the end of the form, or provide your own external submit control.
496
- - **Error Display**: Errors appear inline above each field and as border highlighting
307
+ - **Type Safety**: `componentProps` is strictly typed based on the `component` chosen.
@@ -32,6 +32,7 @@ Powerful table built on TanStack Table v8. Supports client-side and server-side
32
32
  | `disableAutoPageSize` | `boolean` | `false` | Disable auto pageSize (still updates pageIndex). |
33
33
  | `id` | `string` | `undefined` | Test/accessibility hook for the root element. |
34
34
  | `data-testid` | `string` | `undefined` | Test identifier forwarded to the root element. |
35
+ | `rowClassName` | `string \| ((row) => string)` | `undefined` | Add custom CSS classes to table rows based on row data or state. |
35
36
 
36
37
  ---
37
38
 
@@ -56,6 +57,8 @@ type ColumnMeta = {
56
57
  searchable?: boolean;
57
58
  pinned?: "left" | "right";
58
59
  listOptions?: { value: string; label: string }[];
60
+ cellClassName?: string | ((value: any, row: TData) => string);
61
+ headerClassName?: string;
59
62
  };
60
63
  ```
61
64
 
@@ -20,7 +20,7 @@ Drag-and-drop uploader with keyboard activation, file type filtering, limits (co
20
20
  | `maxTotalSize` | `number` (bytes) | `undefined` | Maximum total size of selected files. |
21
21
  | `maxFiles` | `number` | `undefined` | Maximum number of files (when `multiple` is true). |
22
22
 
23
- `AcceptItem` includes: `pdf | doc | docx | xls | xlsx | ppt | pptx | txt | csv | jpg | jpeg | png | gif | image | video | audio`.
23
+ `AcceptItem` includes: `pdf | doc | docx | xls | xlsx | ppt | pptx | txt | csv | jpg | jpeg | png | gif | image | video | audio | zip | rar | 7z | tar | gz | tgz`.
24
24
 
25
25
  ---
26
26
 
@@ -68,6 +68,12 @@ const exts: AcceptItem[] = [
68
68
  "image",
69
69
  "video",
70
70
  "audio",
71
+ "zip",
72
+ "rar",
73
+ "7z",
74
+ "tar",
75
+ "gz",
76
+ "tgz",
71
77
  ];
72
78
 
73
79
  export function MultiUploader() {
@@ -46,6 +46,7 @@ This document provides a complete mapping of all components available in the lai
46
46
  ### Layout & Structure Components
47
47
 
48
48
  - **Accordion** - Collapsible content panels for organizing information hierarchically
49
+ - **AppCard** - Enhanced card component with variant styles, semantic states, size control, and loading skeleton support
49
50
  - **AppSidebar** - Application sidebar navigation component
50
51
  - **AppStepper** - Step-by-step progress indicator for multi-step processes
51
52
  - **AspectRatio** - Container that maintains a specific aspect ratio for responsive layouts
@@ -85,6 +86,7 @@ This document provides a complete mapping of all components available in the lai
85
86
  - **Pagination** - Page navigation component for paginated content
86
87
  - **Table** - Basic table component with styling
87
88
  - **TableSkeleton** - Loading skeleton for table components
89
+ - **TruncatedCell** - Text display component with automatic truncation detection and popover preview
88
90
  - **Typo** - Typography component for consistent text styling
89
91
 
90
92
  ### Content & Media Components