design-react-kit 5.6.1 → 5.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -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/Header/Headers.cjs +1 -1
- package/dist/Header/Headers.cjs.map +1 -1
- package/dist/Header/Headers.js +3 -8
- package/dist/Header/Headers.js.map +1 -1
- package/dist/Input/Input.cjs +1 -1
- package/dist/Input/Input.cjs.map +1 -1
- package/dist/Input/Input.js +1 -2
- package/dist/Input/Input.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 +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 -4
- 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/Header/Headers.tsx +4 -13
- package/src/Input/Input.tsx +9 -11
- 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/Header/Headers.tsx
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import React, { FC, HTMLAttributes } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import { Sticky, StickyProvider } from 'react-stickup';
|
|
4
|
-
|
|
5
3
|
export interface HeadersProps extends HTMLAttributes<HTMLElement> {
|
|
6
4
|
/** Aggiunge un ombra per enfatizzare il componente rispetto alla pagina in cui è contenuto */
|
|
7
5
|
shadow?: boolean;
|
|
@@ -17,18 +15,11 @@ export const Headers: FC<HeadersProps> = ({ className, shadow = false, sticky =
|
|
|
17
15
|
'it-header-wrapper',
|
|
18
16
|
{
|
|
19
17
|
'it-shadow': shadow,
|
|
20
|
-
'it-header-sticky': sticky
|
|
18
|
+
'it-header-sticky': sticky,
|
|
19
|
+
'sticky-top': sticky
|
|
20
|
+
|
|
21
21
|
},
|
|
22
22
|
className
|
|
23
23
|
);
|
|
24
|
-
|
|
25
|
-
return <div className={classes} {...attributes} data-testid={testId}></div>;
|
|
26
|
-
}
|
|
27
|
-
return (
|
|
28
|
-
<StickyProvider>
|
|
29
|
-
<Sticky style={{ position: 'sticky', zIndex: 2 }} data-testid={testId}>
|
|
30
|
-
<div className={classes} {...attributes}></div>
|
|
31
|
-
</Sticky>
|
|
32
|
-
</StickyProvider>
|
|
33
|
-
);
|
|
24
|
+
return <div className={classes} {...attributes} data-testid={testId}></div>;
|
|
34
25
|
};
|
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;
|
|
@@ -356,16 +356,14 @@ export const Input = ({
|
|
|
356
356
|
|
|
357
357
|
if (indeterminateCheckboxInput) {
|
|
358
358
|
return (
|
|
359
|
-
<
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
/>
|
|
368
|
-
</InputContainer>
|
|
359
|
+
<Tag
|
|
360
|
+
{...rest}
|
|
361
|
+
{...extraAttributes}
|
|
362
|
+
{...sharedAttributes}
|
|
363
|
+
className={inputClasses}
|
|
364
|
+
data-testid={testId}
|
|
365
|
+
indeterminate={'true'}
|
|
366
|
+
/>
|
|
369
367
|
);
|
|
370
368
|
}
|
|
371
369
|
|
|
@@ -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 };
|