laif-ds 0.2.64 → 0.2.66
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 +21 -10
- package/dist/agent-docs/components/AppCheckbox.md +225 -0
- package/dist/agent-docs/components/AppSelect.md +58 -21
- package/dist/agent-docs/components/Calendar.md +279 -222
- package/dist/agent-docs/components/DatePicker.md +247 -109
- package/dist/agent-docs/components-list.md +1 -0
- package/dist/components/ui/app-checkbox.js +154 -0
- package/dist/components/ui/app-select.js +172 -150
- package/dist/components/ui/app-tooltip.js +12 -12
- package/dist/components/ui/calendar.js +135 -105
- package/dist/components/ui/date-picker.js +69 -65
- package/dist/components/ui/dropdown-menu.js +82 -66
- package/dist/components/ui/tables/data-table/data-table-constants.js +35 -33
- package/dist/components/ui/tables/data-table/data-table.service.js +87 -87
- package/dist/components/ui/tooltip.js +21 -18
- package/dist/index.d.ts +67 -7
- package/dist/index.js +213 -202
- package/dist/node_modules/@radix-ui/react-dropdown-menu/dist/index.js +143 -131
- package/dist/styles.v3.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
# Laif Design System
|
|
2
2
|
|
|
3
|
-
npm
|
|
4
|
-
npm whoami (verifica se sei loggato con accoutn corretto)
|
|
5
|
-
yarn build (farà partire build per tailwindv3 e tailwindv4)
|
|
6
|
-
npm publish --access public
|
|
3
|
+

|
|
7
4
|
|
|
8
|
-
##
|
|
5
|
+
## Install Laif DS on your project:
|
|
9
6
|
|
|
7
|
+
```sh
|
|
10
8
|
npm i @laif/ds
|
|
9
|
+
```
|
|
11
10
|
|
|
12
|
-
##
|
|
11
|
+
## Development mode
|
|
13
12
|
|
|
14
13
|
Per vedere i componenti con storybook:
|
|
15
14
|
|
|
16
|
-
```
|
|
15
|
+
```sh
|
|
17
16
|
yarn storybook
|
|
18
17
|
```
|
|
19
18
|
|
|
20
19
|
Il comando esegue due operazioni in sequenza: prima compila il CSS con tailwindcss v4 salvandolo in un file output.css, poi avvia Storybook che utilizza questo file CSS precompilato.
|
|
21
20
|
Questo approccio è necessario con Tailwind CSS v4 perché, a differenza delle versioni precedenti, v4 utilizza un'architettura "zero-runtime" che non si integra più direttamente con Storybook. La generazione separata del CSS è quindi la soluzione raccomandata per utilizzare Tailwind v4 con Storybook.
|
|
22
21
|
|
|
23
|
-
##
|
|
22
|
+
## Publish on NPM:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm login
|
|
26
|
+
|
|
27
|
+
npm whoami # verifica se sei loggato con account corretto
|
|
28
|
+
|
|
29
|
+
yarn build # farà partire build per tailwindv3 e tailwindv4
|
|
30
|
+
|
|
31
|
+
npm publish --access public
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## How stories work
|
|
24
35
|
|
|
25
36
|
Le stories in Storybook sono il modo in cui documentiamo e testiamo visivamente i nostri componenti. Ogni story rappresenta uno stato specifico di un componente.
|
|
26
37
|
|
|
@@ -82,7 +93,7 @@ export const Secondary: Story = {
|
|
|
82
93
|
// Altre stories...
|
|
83
94
|
```
|
|
84
95
|
|
|
85
|
-
###
|
|
96
|
+
### How to create a new story
|
|
86
97
|
|
|
87
98
|
1. Crea un nuovo file nella directory `src/components/stories/` con nome `nome-componente.stories.tsx`
|
|
88
99
|
2. Importa il componente e le dipendenze necessarie
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# AppCheckbox
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Enhanced checkbox group component with support for icons, descriptions, card layout, horizontal/vertical orientation, and comprehensive error handling. Built on top of the base Checkbox component with additional styling and features.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Types
|
|
10
|
+
|
|
11
|
+
### AppCheckboxOption
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
export interface AppCheckboxOption {
|
|
15
|
+
value: string; // Unique value for the option
|
|
16
|
+
label: string | React.ReactNode; // Display label (can be JSX)
|
|
17
|
+
description?: string | React.ReactNode; // Optional description text
|
|
18
|
+
disabled?: boolean; // Disables this specific option
|
|
19
|
+
icon?: IconName; // Optional icon name
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
| Prop | Type | Default | Description |
|
|
28
|
+
| ----------------- | ---------------------------- | ------------ | ----------------------------------------------- |
|
|
29
|
+
| `options` | `AppCheckboxOption[]` | **required** | Array of checkbox options |
|
|
30
|
+
| `value` | `string[]` | `undefined` | Controlled value (array of selected values) |
|
|
31
|
+
| `defaultValue` | `string[]` | `undefined` | Uncontrolled default value |
|
|
32
|
+
| `onValueChange` | `(value: string[]) => void` | `undefined` | Callback when value changes |
|
|
33
|
+
| `label` | `string \| React.ReactNode` | `undefined` | Label for the checkbox group |
|
|
34
|
+
| `description` | `string \| React.ReactNode` | `undefined` | Description text below label |
|
|
35
|
+
| `disabled` | `boolean` | `false` | Disables all options |
|
|
36
|
+
| `required` | `boolean` | `false` | Shows required asterisk |
|
|
37
|
+
| `name` | `string` | `undefined` | Form name attribute |
|
|
38
|
+
| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` | Layout orientation |
|
|
39
|
+
| `className` | `string` | `""` | Additional classes for checkbox group container |
|
|
40
|
+
| `wrpClassName` | `string` | `""` | Additional classes for outer wrapper |
|
|
41
|
+
| `optionClassName` | `string` | `""` | Additional classes for each option |
|
|
42
|
+
| `layout` | `"default" \| "card"` | `"default"` | Visual layout style |
|
|
43
|
+
| `error` | `string` | `undefined` | Error message to display |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Behavior
|
|
48
|
+
|
|
49
|
+
- **Controlled/Uncontrolled**: Supports both controlled (`value` + `onValueChange`) and uncontrolled (`defaultValue`) modes
|
|
50
|
+
- **Multiple Selection**: Users can select multiple options simultaneously
|
|
51
|
+
- **Icons**: Automatically renders icons when provided in options
|
|
52
|
+
- **Card Layout**: In card mode, options have border, shadow, and background styling
|
|
53
|
+
- **Error State**: Red text for label and error message display when `error` prop is provided
|
|
54
|
+
- **Disabled State**: Applies opacity and cursor changes to disabled options
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
### Basic Usage
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { AppCheckbox } from "laif-ds";
|
|
64
|
+
import { useState } from "react";
|
|
65
|
+
|
|
66
|
+
export function BasicCheckbox() {
|
|
67
|
+
const [value, setValue] = useState(["option1"]);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<AppCheckbox
|
|
71
|
+
label="Choose options"
|
|
72
|
+
options={[
|
|
73
|
+
{ value: "option1", label: "Option 1" },
|
|
74
|
+
{ value: "option2", label: "Option 2" },
|
|
75
|
+
{ value: "option3", label: "Option 3" },
|
|
76
|
+
]}
|
|
77
|
+
value={value}
|
|
78
|
+
onValueChange={setValue}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### With Icons and Descriptions
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { AppCheckbox } from "laif-ds";
|
|
88
|
+
import { useState } from "react";
|
|
89
|
+
|
|
90
|
+
export function CheckboxWithIcons() {
|
|
91
|
+
const [value, setValue] = useState(["email"]);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<AppCheckbox
|
|
95
|
+
label="Notification Preferences"
|
|
96
|
+
description="Choose how you want to receive notifications"
|
|
97
|
+
options={[
|
|
98
|
+
{
|
|
99
|
+
value: "email",
|
|
100
|
+
label: "Email",
|
|
101
|
+
description: "Receive notifications via email",
|
|
102
|
+
icon: "Mail",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
value: "sms",
|
|
106
|
+
label: "SMS",
|
|
107
|
+
description: "Receive notifications via text message",
|
|
108
|
+
icon: "MessageSquare",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
value: "push",
|
|
112
|
+
label: "Push",
|
|
113
|
+
description: "Receive push notifications",
|
|
114
|
+
icon: "Bell",
|
|
115
|
+
},
|
|
116
|
+
]}
|
|
117
|
+
value={value}
|
|
118
|
+
onValueChange={setValue}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Card Layout
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { AppCheckbox } from "laif-ds";
|
|
128
|
+
import { useState } from "react";
|
|
129
|
+
|
|
130
|
+
export function CardCheckbox() {
|
|
131
|
+
const [value, setValue] = useState(["feature1"]);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<AppCheckbox
|
|
135
|
+
label="Select features"
|
|
136
|
+
layout="card"
|
|
137
|
+
options={[
|
|
138
|
+
{
|
|
139
|
+
value: "feature1",
|
|
140
|
+
label: "Advanced Analytics",
|
|
141
|
+
description: "Detailed insights and reports",
|
|
142
|
+
icon: "BarChart",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
value: "feature2",
|
|
146
|
+
label: "Team Collaboration",
|
|
147
|
+
description: "Work together in real-time",
|
|
148
|
+
icon: "Users",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
value: "feature3",
|
|
152
|
+
label: "Priority Support",
|
|
153
|
+
description: "24/7 dedicated support",
|
|
154
|
+
icon: "Headphones",
|
|
155
|
+
},
|
|
156
|
+
]}
|
|
157
|
+
value={value}
|
|
158
|
+
onValueChange={setValue}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Horizontal Orientation
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { AppCheckbox } from "laif-ds";
|
|
168
|
+
import { useState } from "react";
|
|
169
|
+
|
|
170
|
+
export function HorizontalCheckbox() {
|
|
171
|
+
const [value, setValue] = useState(["small"]);
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<AppCheckbox
|
|
175
|
+
label="Available Sizes"
|
|
176
|
+
orientation="horizontal"
|
|
177
|
+
options={[
|
|
178
|
+
{ value: "small", label: "Small" },
|
|
179
|
+
{ value: "medium", label: "Medium" },
|
|
180
|
+
{ value: "large", label: "Large" },
|
|
181
|
+
]}
|
|
182
|
+
value={value}
|
|
183
|
+
onValueChange={setValue}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### With Error State
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { AppCheckbox } from "laif-ds";
|
|
193
|
+
import { useState } from "react";
|
|
194
|
+
|
|
195
|
+
export function CheckboxWithError() {
|
|
196
|
+
const [value, setValue] = useState<string[]>([]);
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<AppCheckbox
|
|
200
|
+
label="Terms and Conditions"
|
|
201
|
+
required
|
|
202
|
+
options={[
|
|
203
|
+
{ value: "terms", label: "I accept the terms and conditions" },
|
|
204
|
+
{ value: "privacy", label: "I accept the privacy policy" },
|
|
205
|
+
]}
|
|
206
|
+
value={value}
|
|
207
|
+
onValueChange={setValue}
|
|
208
|
+
error={
|
|
209
|
+
value.length === 0 ? "You must accept at least one option" : undefined
|
|
210
|
+
}
|
|
211
|
+
/>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Notes
|
|
219
|
+
|
|
220
|
+
- **JSX Labels**: Both `label` and option labels support JSX for custom rendering
|
|
221
|
+
- **Icon Support**: Uses the Icon component from laif-ds (Feather Icons)
|
|
222
|
+
- **Accessibility**: Includes proper ARIA attributes and keyboard navigation
|
|
223
|
+
- **Card Styling**: Card layout includes hover effects and focus states
|
|
224
|
+
- **Disabled Options**: Individual options can be disabled while keeping others enabled
|
|
225
|
+
- **Multiple Selection**: Unlike radio groups, checkboxes allow selecting multiple options
|
|
@@ -28,24 +28,27 @@ The component uses discriminated union types based on the `multiple` prop.
|
|
|
28
28
|
|
|
29
29
|
### Base Props (Common to both modes)
|
|
30
30
|
|
|
31
|
-
| Prop | Type | Default | Description
|
|
32
|
-
| -------------------- | ------------------------------ | ------------------------------------------------ |
|
|
33
|
-
| `options` | `AppSelectOption[]` | **required** | Array of selectable options
|
|
34
|
-
| `placeholder` | `string` | `"Seleziona..."` | Text shown in trigger when no selection
|
|
35
|
-
| `searchPlaceholder` | `string` | `"Cerca..."` | Placeholder for search input
|
|
36
|
-
| `emptyPlaceholder` | `string` | `"Nessun risultato"` | Text shown when no options match search
|
|
37
|
-
| `addItemPlaceholder` | `string` | `"Aggiungi"` | Text prefix for creating new items
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
| -------------------- | ------------------------------ | ------------------------------------------------ | ----------------------------------------------------------- |
|
|
33
|
+
| `options` | `AppSelectOption[]` | **required** | Array of selectable options |
|
|
34
|
+
| `placeholder` | `string` | `"Seleziona..."` | Text shown in trigger when no selection |
|
|
35
|
+
| `searchPlaceholder` | `string` | `"Cerca..."` | Placeholder for search input |
|
|
36
|
+
| `emptyPlaceholder` | `string` | `"Nessun risultato"` | Text shown when no options match search |
|
|
37
|
+
| `addItemPlaceholder` | `string` | `"Aggiungi"` | Text prefix for creating new items |
|
|
38
|
+
| `noGroupLabel` | `string` | `"Nessun gruppo"` | Label shown for options without a group |
|
|
39
|
+
| `itemCountMessage` | `(selected: number) => string` | `(n) => "${n} elementi selezionati"` | Message function for selected count display |
|
|
40
|
+
| `maxSelectedMessage` | `(max: number) => string` | `(m) => "Puoi selezionare fino a ${m} elementi"` | Message shown when max selection reached |
|
|
41
|
+
| `label` | `string \| React.ReactNode` | `undefined` | Label displayed above the select |
|
|
42
|
+
| `labelClassName` | `string` | `""` | Additional Tailwind classes for the label |
|
|
43
|
+
| `className` | `string` | `""` | Additional Tailwind classes for the trigger |
|
|
44
|
+
| `wrpClassName` | `string` | `""` | Additional Tailwind classes for the wrapper |
|
|
45
|
+
| `searchable` | `boolean` | `false` | Enables search/filter functionality |
|
|
46
|
+
| `creatable` | `boolean` | `false` | Allows creating new options from search input |
|
|
47
|
+
| `disabled` | `boolean` | `false` | Disables the entire select component |
|
|
48
|
+
| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Size variant affecting height and text size |
|
|
49
|
+
| `onClear` | `() => void` | `undefined` | Callback fired when clear button is clicked |
|
|
50
|
+
| `id` | `string` | `undefined` | HTML id attribute for the trigger (useful for testing) |
|
|
51
|
+
| `data-testid` | `string` | `undefined` | Test identifier attribute for E2E testing (e.g. Playwright) |
|
|
49
52
|
|
|
50
53
|
### Single Select Props
|
|
51
54
|
|
|
@@ -55,6 +58,7 @@ export type SingleSelectProps = BaseProps & {
|
|
|
55
58
|
value?: string | number; // Controlled value
|
|
56
59
|
defaultValue?: string | number; // Uncontrolled default value
|
|
57
60
|
onValueChange?: (value: string | number | undefined) => void; // Value change callback
|
|
61
|
+
renderValue?: (option: AppSelectOption) => React.ReactNode; // Custom render for selected value
|
|
58
62
|
isSingleSelectClearable?: boolean; // Shows clear button (default: false)
|
|
59
63
|
};
|
|
60
64
|
```
|
|
@@ -67,6 +71,7 @@ export type MultiSelectProps = BaseProps & {
|
|
|
67
71
|
value?: (string | number)[]; // Controlled values array
|
|
68
72
|
defaultValue?: (string | number)[]; // Uncontrolled default values
|
|
69
73
|
onValueChange?: (value: (string | number)[]) => void; // Value change callback
|
|
74
|
+
renderValue?: (option: AppSelectOption) => React.ReactNode; // Custom render for selected values
|
|
70
75
|
maxSelected?: number; // Maximum number of selectable items
|
|
71
76
|
showChipsInsteadOfCount?: boolean; // Display chips instead of count (default: false)
|
|
72
77
|
};
|
|
@@ -146,8 +151,8 @@ When options have a `group` property:
|
|
|
146
151
|
|
|
147
152
|
- Options are automatically grouped under headings
|
|
148
153
|
- Groups are rendered in the order they appear in the options array
|
|
149
|
-
-
|
|
150
|
-
-
|
|
154
|
+
- Options without a group value (empty string, undefined, or missing) appear under the `noGroupLabel` heading
|
|
155
|
+
- Grouping is based on the `group` property of `AppSelectOption`
|
|
151
156
|
|
|
152
157
|
### Max Selection Limit
|
|
153
158
|
|
|
@@ -270,7 +275,6 @@ export function GroupedSelect() {
|
|
|
270
275
|
onValueChange={setValues}
|
|
271
276
|
placeholder="Select up to 2 technologies"
|
|
272
277
|
label="Tech Stack"
|
|
273
|
-
groupBy="group"
|
|
274
278
|
maxSelected={2}
|
|
275
279
|
searchable
|
|
276
280
|
/>
|
|
@@ -416,6 +420,37 @@ export function SelectWithDisabled() {
|
|
|
416
420
|
}
|
|
417
421
|
```
|
|
418
422
|
|
|
423
|
+
### Custom Render Value
|
|
424
|
+
|
|
425
|
+
```tsx
|
|
426
|
+
import { AppSelect, AppSelectOption } from "laif-ds";
|
|
427
|
+
import { Badge } from "laif-ds";
|
|
428
|
+
import { useState } from "react";
|
|
429
|
+
|
|
430
|
+
const options = [
|
|
431
|
+
{ value: "react", label: "React" },
|
|
432
|
+
{ value: "vue", label: "Vue" },
|
|
433
|
+
{ value: "angular", label: "Angular" },
|
|
434
|
+
];
|
|
435
|
+
|
|
436
|
+
export function CustomRenderSelect() {
|
|
437
|
+
const [value, setValue] = useState<string | number | undefined>("react");
|
|
438
|
+
|
|
439
|
+
return (
|
|
440
|
+
<AppSelect
|
|
441
|
+
options={options}
|
|
442
|
+
value={value}
|
|
443
|
+
onValueChange={setValue}
|
|
444
|
+
placeholder="Select a framework"
|
|
445
|
+
label="Framework"
|
|
446
|
+
renderValue={(option: AppSelectOption) => (
|
|
447
|
+
<Badge variant="success">{option.label}</Badge>
|
|
448
|
+
)}
|
|
449
|
+
/>
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
419
454
|
---
|
|
420
455
|
|
|
421
456
|
## Notes
|
|
@@ -425,3 +460,5 @@ export function SelectWithDisabled() {
|
|
|
425
460
|
- **Keyboard Navigation**: Full keyboard support via Command component
|
|
426
461
|
- **Accessibility**: Proper ARIA attributes and focus management
|
|
427
462
|
- **Performance**: Efficient rendering with useMemo for computed values
|
|
463
|
+
- **Custom Rendering**: Use `renderValue` prop to customize how selected options appear in the trigger
|
|
464
|
+
- **Controlled Component Detection**: Uses `props.hasOwnProperty('value')` to determine if component is controlled, ensuring stable behavior even when value is `undefined`
|