design-react-kit 5.6.0 → 5.7.0
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/CHANGELOG.md +27 -0
- package/dist/Accordion/AccordionBody.cjs +1 -1
- package/dist/Accordion/AccordionBody.cjs.map +1 -1
- package/dist/Accordion/AccordionBody.js +31 -21
- package/dist/Accordion/AccordionBody.js.map +1 -1
- package/dist/Accordion/AccordionHeader.cjs +1 -1
- package/dist/Accordion/AccordionHeader.cjs.map +1 -1
- package/dist/Accordion/AccordionHeader.js +1 -1
- package/dist/Accordion/AccordionHeader.js.map +1 -1
- package/dist/Autocomplete/Autocomplete.cjs +1 -3
- package/dist/Autocomplete/Autocomplete.cjs.map +1 -1
- package/dist/Autocomplete/Autocomplete.js +27 -4
- package/dist/Autocomplete/Autocomplete.js.map +1 -1
- package/dist/Carousel/Carousel.cjs +2 -0
- package/dist/Carousel/Carousel.cjs.map +1 -0
- package/dist/Carousel/Carousel.js +193 -0
- package/dist/Carousel/Carousel.js.map +1 -0
- package/dist/Carousel/CarouselSlide.cjs +2 -0
- package/dist/Carousel/CarouselSlide.cjs.map +1 -0
- package/dist/Carousel/CarouselSlide.js +8 -0
- package/dist/Carousel/CarouselSlide.js.map +1 -0
- package/dist/Input/Input.cjs +1 -1
- package/dist/Input/Input.cjs.map +1 -1
- package/dist/Input/Input.js +3 -9
- package/dist/Input/Input.js.map +1 -1
- package/dist/Input/TextArea.cjs +1 -1
- package/dist/Input/TextArea.cjs.map +1 -1
- package/dist/Input/utils.cjs +1 -1
- package/dist/Input/utils.cjs.map +1 -1
- package/dist/Input/utils.js +2 -4
- package/dist/Input/utils.js.map +1 -1
- package/dist/Rating/Rating.cjs +1 -1
- package/dist/Rating/Rating.cjs.map +1 -1
- package/dist/Transfer/BacktransferButton.cjs +2 -0
- package/dist/Transfer/BacktransferButton.cjs.map +1 -0
- package/dist/Transfer/BacktransferButton.js +20 -0
- package/dist/Transfer/BacktransferButton.js.map +1 -0
- package/dist/Transfer/Item.cjs +2 -0
- package/dist/Transfer/Item.cjs.map +1 -0
- package/dist/Transfer/Item.js +15 -0
- package/dist/Transfer/Item.js.map +1 -0
- package/dist/Transfer/ResetButton.cjs +2 -0
- package/dist/Transfer/ResetButton.cjs.map +1 -0
- package/dist/Transfer/ResetButton.js +16 -0
- package/dist/Transfer/ResetButton.js.map +1 -0
- package/dist/Transfer/SelectAllCheckbox.cjs +2 -0
- package/dist/Transfer/SelectAllCheckbox.cjs.map +1 -0
- package/dist/Transfer/SelectAllCheckbox.js +11 -0
- package/dist/Transfer/SelectAllCheckbox.js.map +1 -0
- package/dist/Transfer/Source.cjs +2 -0
- package/dist/Transfer/Source.cjs.map +1 -0
- package/dist/Transfer/Source.js +61 -0
- package/dist/Transfer/Source.js.map +1 -0
- package/dist/Transfer/Target.cjs +2 -0
- package/dist/Transfer/Target.cjs.map +1 -0
- package/dist/Transfer/Target.js +60 -0
- package/dist/Transfer/Target.js.map +1 -0
- package/dist/Transfer/Transfer.cjs +2 -0
- package/dist/Transfer/Transfer.cjs.map +1 -0
- package/dist/Transfer/Transfer.js +21 -0
- package/dist/Transfer/Transfer.js.map +1 -0
- package/dist/Transfer/TransferButton.cjs +2 -0
- package/dist/Transfer/TransferButton.cjs.map +1 -0
- package/dist/Transfer/TransferButton.js +20 -0
- package/dist/Transfer/TransferButton.js.map +1 -0
- package/dist/Transfer/useTransferContext.cjs +2 -0
- package/dist/Transfer/useTransferContext.cjs.map +1 -0
- package/dist/Transfer/useTransferContext.js +63 -0
- package/dist/Transfer/useTransferContext.js.map +1 -0
- package/dist/Video/Video.cjs +2 -0
- package/dist/Video/Video.cjs.map +1 -0
- package/dist/Video/Video.js +99 -0
- package/dist/Video/Video.js.map +1 -0
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/types/Autocomplete/Autocomplete.d.ts +10 -5
- package/dist/types/Carousel/Carousel.d.ts +7 -0
- package/dist/types/Carousel/CarouselSlide.d.ts +2 -0
- package/dist/types/Input/Input.d.ts +2 -4
- package/dist/types/Input/utils.d.ts +1 -1
- package/dist/types/Transfer/BacktransferButton.d.ts +3 -0
- package/dist/types/Transfer/Item.d.ts +12 -0
- package/dist/types/Transfer/ResetButton.d.ts +3 -0
- package/dist/types/Transfer/SelectAllCheckbox.d.ts +10 -0
- package/dist/types/Transfer/Source.d.ts +9 -0
- package/dist/types/Transfer/Target.d.ts +9 -0
- package/dist/types/Transfer/Transfer.d.ts +40 -0
- package/dist/types/Transfer/TransferButton.d.ts +3 -0
- package/dist/types/Transfer/useTransferContext.d.ts +49 -0
- package/dist/types/Video/Video.d.ts +58 -0
- package/dist/types/index.d.ts +6 -0
- package/package.json +6 -3
- package/src/Accordion/AccordionBody.tsx +32 -22
- package/src/Accordion/AccordionHeader.tsx +0 -1
- package/src/Autocomplete/Autocomplete.tsx +69 -18
- package/src/Carousel/Carousel.tsx +210 -0
- package/src/Carousel/CarouselSlide.tsx +14 -0
- package/src/Input/Input.tsx +10 -19
- package/src/Input/utils.tsx +3 -5
- package/src/Transfer/BacktransferButton.tsx +33 -0
- package/src/Transfer/Item.tsx +33 -0
- package/src/Transfer/ResetButton.tsx +28 -0
- package/src/Transfer/SelectAllCheckbox.tsx +30 -0
- package/src/Transfer/Source.tsx +89 -0
- package/src/Transfer/Target.tsx +87 -0
- package/src/Transfer/Transfer.tsx +31 -0
- package/src/Transfer/TransferButton.tsx +33 -0
- package/src/Transfer/useTransferContext.tsx +110 -0
- package/src/Video/Video.tsx +205 -0
- package/src/index.ts +6 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
|
|
4
|
+
import {Splide, SplideProps} from '@splidejs/react-splide'
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
const CONFIG_DEFAULT: any = {
|
|
8
|
+
slideFocus: false,
|
|
9
|
+
rewind: true,
|
|
10
|
+
perMove: 1,
|
|
11
|
+
i18n: {
|
|
12
|
+
prev: 'Slide precedente',
|
|
13
|
+
next: 'Slide successiva',
|
|
14
|
+
first: 'Vai alla prima slide',
|
|
15
|
+
last: 'Vai all’ultima slide',
|
|
16
|
+
slideX: 'Vai alla slide %s',
|
|
17
|
+
pageX: 'Vai a pagina %s',
|
|
18
|
+
play: 'Attiva autoplay',
|
|
19
|
+
pause: 'Pausa autoplay',
|
|
20
|
+
carousel: 'Carosello',
|
|
21
|
+
select: 'Seleziona una slide da mostrare',
|
|
22
|
+
slide: 'slide',
|
|
23
|
+
slideLabel: '%s di %s',
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
const CONFIGS: any= {
|
|
29
|
+
'landscape-three-cols': {
|
|
30
|
+
type: 'slide',
|
|
31
|
+
perPage: 3,
|
|
32
|
+
gap: 24,
|
|
33
|
+
padding: { left: 0, right: 0 },
|
|
34
|
+
arrows: false,
|
|
35
|
+
breakpoints: {
|
|
36
|
+
768: {
|
|
37
|
+
perPage: 1,
|
|
38
|
+
gap: 24,
|
|
39
|
+
padding: { left: 0, right: 0 },
|
|
40
|
+
arrows: false,
|
|
41
|
+
},
|
|
42
|
+
992: {
|
|
43
|
+
perPage: 2,
|
|
44
|
+
gap: 24,
|
|
45
|
+
padding: { left: 40, right: 40 },
|
|
46
|
+
arrows: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
'landscape-three-cols-arrows': {
|
|
51
|
+
type: 'slide',
|
|
52
|
+
perPage: 3,
|
|
53
|
+
gap: 24,
|
|
54
|
+
padding: { left: 0, right: 0 },
|
|
55
|
+
arrows: true,
|
|
56
|
+
breakpoints: {
|
|
57
|
+
768: {
|
|
58
|
+
perPage: 1,
|
|
59
|
+
gap: 24,
|
|
60
|
+
padding: { left: 40, right: 40 },
|
|
61
|
+
arrows: true,
|
|
62
|
+
},
|
|
63
|
+
992: {
|
|
64
|
+
perPage: 2,
|
|
65
|
+
gap: 24,
|
|
66
|
+
padding: { left: 40, right: 40 },
|
|
67
|
+
arrows: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
'big-image': {
|
|
72
|
+
type: 'loop',
|
|
73
|
+
perPage: 1,
|
|
74
|
+
gap: 48,
|
|
75
|
+
padding: { left: 320, right: 320 },
|
|
76
|
+
arrows: false,
|
|
77
|
+
breakpoints: {
|
|
78
|
+
768: {
|
|
79
|
+
perPage: 1,
|
|
80
|
+
gap: 0,
|
|
81
|
+
padding: { left: 0, right: 0 },
|
|
82
|
+
arrows: false,
|
|
83
|
+
},
|
|
84
|
+
992: {
|
|
85
|
+
perPage: 1,
|
|
86
|
+
gap: 24,
|
|
87
|
+
padding: { left: 160, right: 160 },
|
|
88
|
+
arrows: false,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
'standard-image': {
|
|
93
|
+
type: 'loop',
|
|
94
|
+
perPage: 3,
|
|
95
|
+
gap: 24,
|
|
96
|
+
padding: { left: 48, right: 48 },
|
|
97
|
+
arrows: false,
|
|
98
|
+
breakpoints: {
|
|
99
|
+
768: {
|
|
100
|
+
perPage: 1,
|
|
101
|
+
gap: 24,
|
|
102
|
+
padding: { left: 40, right: 40 },
|
|
103
|
+
arrows: false,
|
|
104
|
+
},
|
|
105
|
+
992: {
|
|
106
|
+
perPage: 2,
|
|
107
|
+
gap: 24,
|
|
108
|
+
padding: { left: 48, right: 48 },
|
|
109
|
+
arrows: false,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
'landscape': {
|
|
114
|
+
type: 'slide',
|
|
115
|
+
perPage: 1,
|
|
116
|
+
gap: 24,
|
|
117
|
+
padding: { left: 0, right: 0 },
|
|
118
|
+
arrows: false,
|
|
119
|
+
breakpoints: {
|
|
120
|
+
768: {
|
|
121
|
+
perPage: 1,
|
|
122
|
+
gap: 24,
|
|
123
|
+
padding: { left: 0, right: 0 },
|
|
124
|
+
arrows: false,
|
|
125
|
+
},
|
|
126
|
+
992: {
|
|
127
|
+
perPage: 1,
|
|
128
|
+
gap: 24,
|
|
129
|
+
padding: { left: 24, right: 24 },
|
|
130
|
+
arrows: false,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
'calendar-wrapper': {
|
|
135
|
+
type: 'slide',
|
|
136
|
+
perPage: 4,
|
|
137
|
+
gap: 0,
|
|
138
|
+
padding: { left: 0, right: 0 },
|
|
139
|
+
arrows: false,
|
|
140
|
+
breakpoints: {
|
|
141
|
+
560: {
|
|
142
|
+
perPage: 1,
|
|
143
|
+
gap: 0,
|
|
144
|
+
padding: { left: 24, right: 24 },
|
|
145
|
+
arrows: false,
|
|
146
|
+
},
|
|
147
|
+
768: {
|
|
148
|
+
perPage: 2,
|
|
149
|
+
gap: 0,
|
|
150
|
+
padding: { left: 0, right: 0 },
|
|
151
|
+
arrows: false,
|
|
152
|
+
},
|
|
153
|
+
992: {
|
|
154
|
+
perPage: 3,
|
|
155
|
+
gap: 0,
|
|
156
|
+
padding: { left: 0, right: 0 },
|
|
157
|
+
arrows: false,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
164
|
+
const EXTRA_CLASSES: any= {
|
|
165
|
+
'landscape-three-cols': [
|
|
166
|
+
'it-carousel-landscape-abstract-three-cols'
|
|
167
|
+
],
|
|
168
|
+
'landscape-three-cols-arrows': [
|
|
169
|
+
'it-carousel-landscape-abstract-three-cols-arrow-visible'
|
|
170
|
+
],
|
|
171
|
+
'big-image': [
|
|
172
|
+
'it-carousel-landscape-abstract-three-cols',
|
|
173
|
+
'it-full-carousel',
|
|
174
|
+
'it-big-img'
|
|
175
|
+
],
|
|
176
|
+
'standard-image': [
|
|
177
|
+
'it-carousel-landscape-abstract-three-cols',
|
|
178
|
+
'it-full-carousel',
|
|
179
|
+
'it-standard-image'
|
|
180
|
+
],
|
|
181
|
+
'landscape': [
|
|
182
|
+
'it-carousel-landscape-abstract'
|
|
183
|
+
],
|
|
184
|
+
'calendar-wrapper': [
|
|
185
|
+
'it-calendar-wrapper'
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface CarouselProps extends SplideProps {
|
|
190
|
+
type: string;
|
|
191
|
+
children?: React.ReactNode;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Splide wrapper
|
|
195
|
+
export const Carousel: FC<CarouselProps> = ({
|
|
196
|
+
className = '',
|
|
197
|
+
type,
|
|
198
|
+
children,
|
|
199
|
+
...attributes
|
|
200
|
+
}) => {
|
|
201
|
+
let conf = Object.assign({}, CONFIG_DEFAULT)
|
|
202
|
+
if (['big-image', 'standard-image'].includes(type)){
|
|
203
|
+
conf = Object.assign({}, conf, CONFIGS['landscape-three-cols'])
|
|
204
|
+
}
|
|
205
|
+
conf = Object.assign({}, conf, CONFIGS[type])
|
|
206
|
+
return <Splide
|
|
207
|
+
{...attributes}
|
|
208
|
+
className={classNames('it-carousel-wrapper', className, ...EXTRA_CLASSES[type])}
|
|
209
|
+
options={conf}>{children}</Splide>;
|
|
210
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {SplideSlide} from '@splidejs/react-splide'
|
|
3
|
+
|
|
4
|
+
// Splide wrapper
|
|
5
|
+
export const CarouselSlide: React.FC<JSX.IntrinsicElements['li']> = ({
|
|
6
|
+
children,
|
|
7
|
+
}) => {
|
|
8
|
+
|
|
9
|
+
return <SplideSlide>
|
|
10
|
+
<div className='it-single-slide-wrapper'>
|
|
11
|
+
{children}
|
|
12
|
+
</div>
|
|
13
|
+
</SplideSlide>;
|
|
14
|
+
};
|
package/src/Input/Input.tsx
CHANGED
|
@@ -62,7 +62,7 @@ export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
62
62
|
decrementLabel?: string | ReactNode;
|
|
63
63
|
/** Testo di esempio da utilizzare per il campo. */
|
|
64
64
|
placeholder?: string;
|
|
65
|
-
/** Testo di validazione per l'elemento del
|
|
65
|
+
/** Testo di validazione per l'elemento del modulo form. */
|
|
66
66
|
validationText?: string;
|
|
67
67
|
/** Testo di aiuto per l'elemento del moduleo form. Richiede che il componente `Input` abbia la prop `id` impostata. */
|
|
68
68
|
infoText?: string;
|
|
@@ -77,8 +77,6 @@ export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
77
77
|
innerRef?: Ref<HTMLInputElement>;
|
|
78
78
|
/** Utilizzare per mostrare testo statico non modificabile. */
|
|
79
79
|
plaintext?: boolean;
|
|
80
|
-
/** Utilizzare per mostrare un elemento addon a fianco (prima o dopo) il campo input all'interno del componente */
|
|
81
|
-
addon?: boolean;
|
|
82
80
|
/** Utilizzare per mostrare un elemento un simbolo attivando la proprietà addon nel campo input all'interno del componente */
|
|
83
81
|
addonText?: string;
|
|
84
82
|
/** Oggetto contenente la nuova mappatura per le classi CSS. */
|
|
@@ -118,7 +116,6 @@ export const Input = ({
|
|
|
118
116
|
cssModule,
|
|
119
117
|
type = 'text',
|
|
120
118
|
tag,
|
|
121
|
-
addon,
|
|
122
119
|
addonText,
|
|
123
120
|
static: staticInput,
|
|
124
121
|
plaintext,
|
|
@@ -173,13 +170,11 @@ export const Input = ({
|
|
|
173
170
|
let { bsSize, valid, ...rest } = attributes;
|
|
174
171
|
|
|
175
172
|
const Tag = getTag({ tag, plaintext, staticInput, type });
|
|
176
|
-
addon = addonText != null ? true : addon;
|
|
177
173
|
const formControlClass = getFormControlClass(
|
|
178
174
|
{
|
|
179
175
|
plaintext,
|
|
180
176
|
staticInput,
|
|
181
177
|
type,
|
|
182
|
-
addon,
|
|
183
178
|
normalized
|
|
184
179
|
},
|
|
185
180
|
cssModule
|
|
@@ -304,10 +299,8 @@ export const Input = ({
|
|
|
304
299
|
};
|
|
305
300
|
|
|
306
301
|
if (['currency', 'percentage', 'adaptive', 'number'].includes(type)) {
|
|
307
|
-
if (containerProps.extraLabelClass) {
|
|
302
|
+
if (containerProps.extraLabelClass && ['currency', 'percentage'].includes(type)) {
|
|
308
303
|
containerProps.extraLabelClass = containerProps.extraLabelClass + ' input-symbol-label';
|
|
309
|
-
} else {
|
|
310
|
-
containerProps.extraLabelClass = 'input-symbol-label';
|
|
311
304
|
}
|
|
312
305
|
return (
|
|
313
306
|
<InputContainer {...containerProps}>
|
|
@@ -363,16 +356,14 @@ export const Input = ({
|
|
|
363
356
|
|
|
364
357
|
if (indeterminateCheckboxInput) {
|
|
365
358
|
return (
|
|
366
|
-
<
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
/>
|
|
375
|
-
</InputContainer>
|
|
359
|
+
<Tag
|
|
360
|
+
{...rest}
|
|
361
|
+
{...extraAttributes}
|
|
362
|
+
{...sharedAttributes}
|
|
363
|
+
className={inputClasses}
|
|
364
|
+
data-testid={testId}
|
|
365
|
+
indeterminate={'true'}
|
|
366
|
+
/>
|
|
376
367
|
);
|
|
377
368
|
}
|
|
378
369
|
|
package/src/Input/utils.tsx
CHANGED
|
@@ -8,9 +8,9 @@ type ValidationProps = Pick<InputProps, 'valid'>;
|
|
|
8
8
|
type TypeProps = Pick<InputProps, 'plaintext' | 'type'> & {
|
|
9
9
|
staticInput?: boolean;
|
|
10
10
|
};
|
|
11
|
-
type FormControlProps = Pick<InputProps, '
|
|
11
|
+
type FormControlProps = Pick<InputProps, 'normalized'> & TypeProps;
|
|
12
12
|
|
|
13
|
-
function getFormControlClassInternal({ plaintext, staticInput, type = 'text',
|
|
13
|
+
function getFormControlClassInternal({ plaintext, staticInput, type = 'text', normalized }: FormControlProps) {
|
|
14
14
|
const formControlClass = 'form-control';
|
|
15
15
|
if (plaintext || staticInput || normalized) {
|
|
16
16
|
return `${formControlClass}-plaintext`;
|
|
@@ -19,9 +19,7 @@ function getFormControlClassInternal({ plaintext, staticInput, type = 'text', ad
|
|
|
19
19
|
return `${formControlClass}-file`;
|
|
20
20
|
}
|
|
21
21
|
if (['radio', 'checkbox'].indexOf(type) > -1) {
|
|
22
|
-
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
22
|
+
return null;
|
|
25
23
|
}
|
|
26
24
|
return formControlClass;
|
|
27
25
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Icon } from '../Icon/Icon';
|
|
3
|
+
import { useTransferContext } from './useTransferContext';
|
|
4
|
+
|
|
5
|
+
const BacktransferButton = () => {
|
|
6
|
+
const { targetCandidates, sourceItems, targetItems, setSourceItems, setTargetItems, setTargetCandidates } =
|
|
7
|
+
useTransferContext();
|
|
8
|
+
const handleTransfer: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
const newTargetItems = targetItems.filter((item) => !targetCandidates.includes(item.id));
|
|
11
|
+
const newSourceItems = sourceItems.concat(targetItems.filter((item) => targetCandidates.includes(item.id)));
|
|
12
|
+
setSourceItems({ items: newSourceItems });
|
|
13
|
+
setTargetItems({ items: newTargetItems });
|
|
14
|
+
setTargetCandidates([]);
|
|
15
|
+
};
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<a
|
|
19
|
+
className={`backtransfer ${targetCandidates.length > 0 ? 'active' : ''}`}
|
|
20
|
+
href='#'
|
|
21
|
+
role='button'
|
|
22
|
+
aria-label='Sposta indietro'
|
|
23
|
+
onClick={handleTransfer}
|
|
24
|
+
data-testid='backtransfer-button'
|
|
25
|
+
>
|
|
26
|
+
<Icon icon='it-arrow-left' />
|
|
27
|
+
</a>
|
|
28
|
+
<span className='visually-hidden'>Etichetta per freccia sinistra</span>
|
|
29
|
+
</>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { BacktransferButton };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormGroup, Input, Label } from '..';
|
|
3
|
+
|
|
4
|
+
const Item = ({ id, children }: { id: string; children: React.ReactNode }) => {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
{id} - {children}
|
|
8
|
+
</>
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const InternalItem = ({
|
|
13
|
+
id,
|
|
14
|
+
checked,
|
|
15
|
+
children,
|
|
16
|
+
onChange
|
|
17
|
+
}: {
|
|
18
|
+
id: string;
|
|
19
|
+
checked?: boolean;
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<FormGroup check>
|
|
25
|
+
<Input checked={checked} onChange={onChange} id={id} type='checkbox' />
|
|
26
|
+
<Label for={id} check>
|
|
27
|
+
{children}
|
|
28
|
+
</Label>
|
|
29
|
+
</FormGroup>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { InternalItem, Item };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Icon } from '../Icon/Icon';
|
|
3
|
+
import { useTransferContext } from './useTransferContext';
|
|
4
|
+
|
|
5
|
+
const ResetButton = () => {
|
|
6
|
+
const { reset, isChanged } = useTransferContext();
|
|
7
|
+
const handleReset: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
|
|
8
|
+
e.preventDefault();
|
|
9
|
+
reset();
|
|
10
|
+
};
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<a
|
|
14
|
+
className={`reset ${isChanged ? 'active' : ''}`}
|
|
15
|
+
href='#'
|
|
16
|
+
role='button'
|
|
17
|
+
aria-label='Reset'
|
|
18
|
+
onClick={handleReset}
|
|
19
|
+
data-testid='reset-button'
|
|
20
|
+
>
|
|
21
|
+
<Icon icon='it-restore' />
|
|
22
|
+
</a>
|
|
23
|
+
<span className='visually-hidden'>Etichetta per icona di reset</span>
|
|
24
|
+
</>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { ResetButton };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormGroup, Input, Label } from '..';
|
|
3
|
+
|
|
4
|
+
const SelectAllCheckbox = ({
|
|
5
|
+
className,
|
|
6
|
+
description,
|
|
7
|
+
checked,
|
|
8
|
+
id,
|
|
9
|
+
onChange,
|
|
10
|
+
children
|
|
11
|
+
}: {
|
|
12
|
+
className?: string;
|
|
13
|
+
id: string;
|
|
14
|
+
checked?: boolean;
|
|
15
|
+
onChange: React.ChangeEventHandler<HTMLInputElement>;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
description?: string;
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<FormGroup check>
|
|
21
|
+
<Input className={className} checked={checked} onChange={onChange} id={id} type='checkbox' />
|
|
22
|
+
<Label for={id} check>
|
|
23
|
+
{children}
|
|
24
|
+
{description && <span className='descr'>{description}</span>}
|
|
25
|
+
</Label>
|
|
26
|
+
</FormGroup>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export { SelectAllCheckbox };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { InternalItem, Item } from './Item';
|
|
3
|
+
import { SelectAllCheckbox } from './SelectAllCheckbox';
|
|
4
|
+
import { useTransferContext } from './useTransferContext';
|
|
5
|
+
|
|
6
|
+
const SourceItem = ({ id, children }: { id: string; children: React.ReactNode }) => {
|
|
7
|
+
const { sourceCandidates, setSourceCandidates } = useTransferContext();
|
|
8
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
9
|
+
if (e.target.checked) {
|
|
10
|
+
setSourceCandidates([...new Set([...sourceCandidates, e.target.id])]);
|
|
11
|
+
} else {
|
|
12
|
+
setSourceCandidates(sourceCandidates.filter((item) => item !== e.target.id));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isChecked = sourceCandidates.includes(id);
|
|
16
|
+
return (
|
|
17
|
+
<InternalItem checked={isChecked} id={id} onChange={handleChange}>
|
|
18
|
+
{children}
|
|
19
|
+
</InternalItem>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const Source: React.FC<{ children?: React.ReactNode }> & {
|
|
24
|
+
Header: React.FC<{ children?: React.ReactNode }>;
|
|
25
|
+
} = ({ children }) => {
|
|
26
|
+
const { sourceItems, setSourceItems } = useTransferContext();
|
|
27
|
+
const otherComponents: React.ReactNode[] = [];
|
|
28
|
+
const childrenSource = React.Children.map(children, (child) => {
|
|
29
|
+
if (React.isValidElement(child) && child.type === Item) {
|
|
30
|
+
const { id, children } = child.props;
|
|
31
|
+
return { id, content: children };
|
|
32
|
+
}
|
|
33
|
+
otherComponents.push(child);
|
|
34
|
+
return null;
|
|
35
|
+
})?.filter((item) => item !== null);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!childrenSource) return;
|
|
39
|
+
setSourceItems({ items: childrenSource, setOriginals: true });
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className='it-transfer-wrapper source' data-testid='transfer-source'>
|
|
44
|
+
{otherComponents}
|
|
45
|
+
{sourceItems.map(({ id, content }) => (
|
|
46
|
+
<SourceItem key={id} id={id}>
|
|
47
|
+
{content}
|
|
48
|
+
</SourceItem>
|
|
49
|
+
))}
|
|
50
|
+
|
|
51
|
+
<br />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
Source.Header = ({ children }: { children?: React.ReactNode }) => {
|
|
57
|
+
const { sourceItems, sourceCandidates, setSourceCandidates } = useTransferContext();
|
|
58
|
+
|
|
59
|
+
const getStatus = () => {
|
|
60
|
+
if (sourceCandidates.length === 0) {
|
|
61
|
+
return { checked: false };
|
|
62
|
+
}
|
|
63
|
+
if (sourceItems.every((item) => sourceCandidates.includes(item.id))) {
|
|
64
|
+
return { checked: true };
|
|
65
|
+
}
|
|
66
|
+
return { checked: false, className: 'semi-checked' };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div className='transfer-header' data-testid='transfer-source-header'>
|
|
71
|
+
<SelectAllCheckbox
|
|
72
|
+
{...getStatus()}
|
|
73
|
+
onChange={(e) => {
|
|
74
|
+
if (e.target.checked) {
|
|
75
|
+
setSourceCandidates([...new Set(sourceItems.map((item) => item.id))]);
|
|
76
|
+
} else {
|
|
77
|
+
setSourceCandidates([]);
|
|
78
|
+
}
|
|
79
|
+
}}
|
|
80
|
+
id='transfer-source-header'
|
|
81
|
+
description={children ? 'Source' : undefined}
|
|
82
|
+
>
|
|
83
|
+
{children ? children : 'Source'}
|
|
84
|
+
</SelectAllCheckbox>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { Source };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { InternalItem, Item } from './Item';
|
|
3
|
+
import { SelectAllCheckbox } from './SelectAllCheckbox';
|
|
4
|
+
import { useTransferContext } from './useTransferContext';
|
|
5
|
+
|
|
6
|
+
const TargetItem = ({ id, children }: { id: string; children: React.ReactNode }) => {
|
|
7
|
+
const { targetCandidates, setTargetCandidates } = useTransferContext();
|
|
8
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
9
|
+
if (e.target.checked) {
|
|
10
|
+
setTargetCandidates([...new Set([...targetCandidates, e.target.id])]);
|
|
11
|
+
} else {
|
|
12
|
+
setTargetCandidates(targetCandidates.filter((item) => item !== e.target.id));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isChecked = targetCandidates.includes(id);
|
|
16
|
+
return (
|
|
17
|
+
<InternalItem checked={isChecked} id={id} onChange={handleChange}>
|
|
18
|
+
{children}
|
|
19
|
+
</InternalItem>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const Target: React.FC<{ children?: React.ReactNode }> & {
|
|
24
|
+
Header: React.FC<{ children?: React.ReactNode }>;
|
|
25
|
+
} = ({ children }) => {
|
|
26
|
+
const { targetItems, setTargetItems } = useTransferContext();
|
|
27
|
+
const otherComponents: React.ReactNode[] = [];
|
|
28
|
+
const childrenTarget = React.Children.map(children, (child) => {
|
|
29
|
+
if (React.isValidElement(child) && child.type === Item) {
|
|
30
|
+
const { id, children } = child.props;
|
|
31
|
+
return { id, content: children };
|
|
32
|
+
}
|
|
33
|
+
otherComponents.push(child);
|
|
34
|
+
return null;
|
|
35
|
+
})?.filter((item) => item !== null);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!childrenTarget) return;
|
|
39
|
+
setTargetItems({ items: childrenTarget, setOriginals: true });
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className='it-transfer-wrapper target' data-testid='transfer-target'>
|
|
44
|
+
{otherComponents}
|
|
45
|
+
{targetItems.map(({ id, content }) => (
|
|
46
|
+
<TargetItem key={id} id={id}>
|
|
47
|
+
{content}
|
|
48
|
+
</TargetItem>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
Target.Header = ({ children }: { children?: React.ReactNode }) => {
|
|
55
|
+
const { targetItems, targetCandidates, setTargetCandidates } = useTransferContext();
|
|
56
|
+
|
|
57
|
+
const getStatus = () => {
|
|
58
|
+
if (targetCandidates.length === 0) {
|
|
59
|
+
return { checked: false };
|
|
60
|
+
}
|
|
61
|
+
if (targetItems.every((item) => targetCandidates.includes(item.id))) {
|
|
62
|
+
return { checked: true };
|
|
63
|
+
}
|
|
64
|
+
return { checked: false, className: 'semi-checked' };
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className='transfer-header' data-testid='transfer-target-header'>
|
|
69
|
+
<SelectAllCheckbox
|
|
70
|
+
{...getStatus()}
|
|
71
|
+
onChange={(e) => {
|
|
72
|
+
if (e.target.checked) {
|
|
73
|
+
setTargetCandidates([...new Set(targetItems.map((item) => item.id))]);
|
|
74
|
+
} else {
|
|
75
|
+
setTargetCandidates([]);
|
|
76
|
+
}
|
|
77
|
+
}}
|
|
78
|
+
id='transfer-target-header'
|
|
79
|
+
description={children ? 'Target' : undefined}
|
|
80
|
+
>
|
|
81
|
+
{children ? children : 'Target'}
|
|
82
|
+
</SelectAllCheckbox>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { Target };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BacktransferButton } from './BacktransferButton';
|
|
3
|
+
import { Item } from './Item';
|
|
4
|
+
import { ResetButton } from './ResetButton';
|
|
5
|
+
import { Source } from './Source';
|
|
6
|
+
import { Target } from './Target';
|
|
7
|
+
import { TransferButton } from './TransferButton';
|
|
8
|
+
import { TransferContextProvider, useTransfer } from './useTransferContext';
|
|
9
|
+
|
|
10
|
+
const Transfer = ({ children }: { children: React.ReactNode }) => {
|
|
11
|
+
return (
|
|
12
|
+
<TransferContextProvider>
|
|
13
|
+
<div data-testid='test-id-transfer'>{children}</div>
|
|
14
|
+
</TransferContextProvider>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Transfer.Source = Source;
|
|
19
|
+
Transfer.Target = Target;
|
|
20
|
+
|
|
21
|
+
Transfer.Item = Item;
|
|
22
|
+
|
|
23
|
+
Transfer.TransferButton = TransferButton;
|
|
24
|
+
|
|
25
|
+
Transfer.BacktransferButton = BacktransferButton;
|
|
26
|
+
|
|
27
|
+
Transfer.ResetButton = ResetButton;
|
|
28
|
+
|
|
29
|
+
Transfer.useTransfer = useTransfer;
|
|
30
|
+
|
|
31
|
+
export { Transfer };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Icon } from '../Icon/Icon';
|
|
3
|
+
import { useTransferContext } from './useTransferContext';
|
|
4
|
+
|
|
5
|
+
const TransferButton = () => {
|
|
6
|
+
const { sourceCandidates, sourceItems, targetItems, setSourceItems, setTargetItems, setSourceCandidates } =
|
|
7
|
+
useTransferContext();
|
|
8
|
+
const handleTransfer: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
const newSourceItems = sourceItems.filter((item) => !sourceCandidates.includes(item.id));
|
|
11
|
+
const newTargetItems = targetItems.concat(sourceItems.filter((item) => sourceCandidates.includes(item.id)));
|
|
12
|
+
setSourceItems({ items: newSourceItems });
|
|
13
|
+
setTargetItems({ items: newTargetItems });
|
|
14
|
+
setSourceCandidates([]);
|
|
15
|
+
};
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<a
|
|
19
|
+
data-testid='transfer-button'
|
|
20
|
+
className={`transfer ${sourceCandidates.length > 0 ? 'active' : ''}`}
|
|
21
|
+
href='#'
|
|
22
|
+
role='button'
|
|
23
|
+
aria-label='Sposta avanti'
|
|
24
|
+
onClick={handleTransfer}
|
|
25
|
+
>
|
|
26
|
+
<Icon icon='it-arrow-right' />
|
|
27
|
+
</a>
|
|
28
|
+
<span className='visually-hidden'>Etichetta per freccia destra</span>
|
|
29
|
+
</>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { TransferButton };
|