@ultraviolet/ui 1.10.1 → 1.11.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/dist/index.d.ts +48 -13
- package/dist/src/components/ActionBar/index.js +0 -2
- package/dist/src/components/CheckboxGroup/index.js +129 -0
- package/dist/src/components/Modal/Dialog.js +63 -2
- package/dist/src/components/Modal/Disclosure.js +8 -1
- package/dist/src/components/Modal/Modal.js +4 -1
- package/dist/src/components/Toggle/index.js +4 -2
- package/dist/src/components/ToggleGroup/index.js +121 -0
- package/dist/src/index.js +2 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -24,11 +24,10 @@ type ActionBarProps = {
|
|
|
24
24
|
*/
|
|
25
25
|
rank?: number;
|
|
26
26
|
role?: string;
|
|
27
|
-
'aria-modal'?: 'true' | 'false';
|
|
28
27
|
className?: string;
|
|
29
28
|
'data-testid'?: string;
|
|
30
29
|
};
|
|
31
|
-
declare const ActionBar: ({ children, role, rank,
|
|
30
|
+
declare const ActionBar: ({ children, role, rank, className, "data-testid": dataTestId, }: ActionBarProps) => react.ReactPortal;
|
|
32
31
|
|
|
33
32
|
type ScreenSize = keyof typeof consoleLightTheme.screens;
|
|
34
33
|
type SCWUITheme = typeof consoleLightTheme;
|
|
@@ -1453,6 +1452,25 @@ type NoticeProps = {
|
|
|
1453
1452
|
};
|
|
1454
1453
|
declare const Notice: ({ children, className, "data-testid": dataTestId, }: NoticeProps) => _emotion_react_jsx_runtime.JSX.Element;
|
|
1455
1454
|
|
|
1455
|
+
type CheckboxGroupCheckboxProps = Omit<ComponentProps<typeof Checkbox>, 'onChange' | 'checked' | 'required'> & {
|
|
1456
|
+
value: string;
|
|
1457
|
+
};
|
|
1458
|
+
declare const CheckboxGroupCheckbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
|
|
1459
|
+
type CheckboxGroupProps = {
|
|
1460
|
+
legend: string;
|
|
1461
|
+
value?: string[];
|
|
1462
|
+
className?: string;
|
|
1463
|
+
helper?: ReactNode;
|
|
1464
|
+
error?: ReactNode;
|
|
1465
|
+
direction?: 'row' | 'column';
|
|
1466
|
+
children: ReactNode;
|
|
1467
|
+
required?: boolean;
|
|
1468
|
+
} & Required<Pick<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'name'>> & Pick<InputHTMLAttributes<HTMLInputElement>, 'required'>;
|
|
1469
|
+
declare const CheckboxGroup: {
|
|
1470
|
+
({ legend, value, className, helper, error, direction, children, onChange, name, required, }: CheckboxGroupProps): _emotion_react_jsx_runtime.JSX.Element;
|
|
1471
|
+
Checkbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
|
|
1472
|
+
};
|
|
1473
|
+
|
|
1456
1474
|
declare const containerSizes: {
|
|
1457
1475
|
large: number;
|
|
1458
1476
|
medium: number;
|
|
@@ -2285,25 +2303,42 @@ type ToastContainerProps = {
|
|
|
2285
2303
|
};
|
|
2286
2304
|
declare const ToastContainer: ({ newestOnTop, limit, position, "data-testid": dataTestId, }: ToastContainerProps) => _emotion_react_jsx_runtime.JSX.Element;
|
|
2287
2305
|
|
|
2288
|
-
|
|
2289
|
-
id?: string;
|
|
2290
|
-
checked?: boolean;
|
|
2306
|
+
declare const Toggle: react.ForwardRefExoticComponent<{
|
|
2307
|
+
id?: string | undefined;
|
|
2308
|
+
checked?: boolean | undefined;
|
|
2291
2309
|
name: string;
|
|
2292
|
-
tooltip?: string;
|
|
2310
|
+
tooltip?: string | undefined;
|
|
2293
2311
|
/**
|
|
2294
2312
|
* If `onChange` is given component will work as a controlled component if not it will work as an uncontrolled component.
|
|
2295
2313
|
*/
|
|
2296
|
-
onChange?: ChangeEventHandler<HTMLInputElement
|
|
2297
|
-
size?:
|
|
2298
|
-
labelPosition?:
|
|
2314
|
+
onChange?: ChangeEventHandler<HTMLInputElement> | undefined;
|
|
2315
|
+
size?: "large" | "small" | undefined;
|
|
2316
|
+
labelPosition?: "left" | "right" | undefined;
|
|
2299
2317
|
label?: ReactNode;
|
|
2300
2318
|
helper?: ReactNode;
|
|
2301
|
-
disabled?: boolean;
|
|
2319
|
+
disabled?: boolean | undefined;
|
|
2320
|
+
className?: string | undefined;
|
|
2321
|
+
required?: boolean | undefined;
|
|
2322
|
+
'data-testid'?: string | undefined;
|
|
2323
|
+
} & Pick<InputHTMLAttributes<HTMLInputElement>, "value"> & react.RefAttributes<HTMLInputElement>>;
|
|
2324
|
+
|
|
2325
|
+
type ToggleGroupToggleProps = Omit<ComponentProps<typeof Toggle>, 'onChange' | 'checked' | 'required'> & {
|
|
2326
|
+
value: string;
|
|
2327
|
+
};
|
|
2328
|
+
type ToggleGroupProps = {
|
|
2329
|
+
legend: string;
|
|
2330
|
+
value?: string[];
|
|
2302
2331
|
className?: string;
|
|
2332
|
+
helper?: ReactNode;
|
|
2333
|
+
error?: ReactNode;
|
|
2334
|
+
direction?: 'row' | 'column';
|
|
2335
|
+
children: ReactNode;
|
|
2303
2336
|
required?: boolean;
|
|
2304
|
-
|
|
2337
|
+
} & Required<Pick<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'name'>> & Pick<InputHTMLAttributes<HTMLInputElement>, 'required'>;
|
|
2338
|
+
declare const ToggleGroup: {
|
|
2339
|
+
({ legend, value, className, helper, error, direction, children, onChange, name, required, }: ToggleGroupProps): _emotion_react_jsx_runtime.JSX.Element;
|
|
2340
|
+
Toggle: ({ disabled, name, value, label, helper, className, "data-testid": dataTestId, }: ToggleGroupToggleProps) => _emotion_react_jsx_runtime.JSX.Element;
|
|
2305
2341
|
};
|
|
2306
|
-
declare const Toggle: react.ForwardRefExoticComponent<ToggleProps & react.RefAttributes<HTMLInputElement>>;
|
|
2307
2342
|
|
|
2308
2343
|
type TooltipProps = Pick<ComponentProps<typeof Popup>, 'id' | 'children' | 'maxWidth' | 'placement' | 'text' | 'className' | 'visible' | 'innerRef' | 'role' | 'data-testid' | 'containerFullWidth'>;
|
|
2309
2344
|
declare const Tooltip: react.ForwardRefExoticComponent<TooltipProps & react.RefAttributes<HTMLDivElement>>;
|
|
@@ -2396,4 +2431,4 @@ declare const down: (size: ScreenSize, rules: string) => string;
|
|
|
2396
2431
|
|
|
2397
2432
|
declare const normalize: () => string;
|
|
2398
2433
|
|
|
2399
|
-
export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CopyButton, DateInput, EmptyState, Expandable, LineChart, Link, List, Loader, Menu, Meter, Modal, Notice, NumberInput, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, ProgressBar, Radio, RadioGroup, Row, SCWUITheme, SelectInput, SelectableCard, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextInput, TimeInput, ToastContainer, Toggle, Tooltip, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, ping, pulse, quickScaleDown, scaleBack, scaleDown, scaleForward, scaleUp, sketchIn, sketchOut, slideDownLarge, slideFromBottom, slideFromLeft, slideFromRight, slideFromTop, slideToBottom, slideToLeft, slideToRight, slideToTop, slideUpLarge, toast, unfoldIn, unfoldOut, up, zoomIn, zoomOut };
|
|
2434
|
+
export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CheckboxGroup, CheckboxGroupCheckbox, CopyButton, DateInput, EmptyState, Expandable, LineChart, Link, List, Loader, Menu, Meter, Modal, Notice, NumberInput, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, ProgressBar, Radio, RadioGroup, Row, type SCWUITheme, SelectInput, SelectableCard, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextInput, TimeInput, ToastContainer, Toggle, ToggleGroup, Tooltip, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, ping, pulse, quickScaleDown, scaleBack, scaleDown, scaleForward, scaleUp, sketchIn, sketchOut, slideDownLarge, slideFromBottom, slideFromLeft, slideFromRight, slideFromTop, slideToBottom, slideToLeft, slideToRight, slideToTop, slideUpLarge, toast, unfoldIn, unfoldOut, up, zoomIn, zoomOut };
|
|
@@ -33,14 +33,12 @@ const ActionBar = _ref5 => {
|
|
|
33
33
|
children,
|
|
34
34
|
role = 'dialog',
|
|
35
35
|
rank = 0,
|
|
36
|
-
'aria-modal': ariaModal = 'true',
|
|
37
36
|
className,
|
|
38
37
|
'data-testid': dataTestId
|
|
39
38
|
} = _ref5;
|
|
40
39
|
return /*#__PURE__*/createPortal(jsx(StyledDiv, {
|
|
41
40
|
rank: rank,
|
|
42
41
|
role: role,
|
|
43
|
-
"aria-modal": ariaModal,
|
|
44
42
|
className: className,
|
|
45
43
|
"data-testid": dataTestId,
|
|
46
44
|
children: children
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import _styled from '@emotion/styled/base';
|
|
2
|
+
import { Icon } from '@ultraviolet/icons';
|
|
3
|
+
import { useContext, useMemo, createContext } from 'react';
|
|
4
|
+
import { Checkbox } from '../Checkbox/index.js';
|
|
5
|
+
import { Stack } from '../Stack/index.js';
|
|
6
|
+
import { Text } from '../Text/index.js';
|
|
7
|
+
import { jsx, jsxs } from '@emotion/react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
|
|
10
|
+
const CheckboxGroupContext = /*#__PURE__*/createContext(undefined);
|
|
11
|
+
const CheckboxGroupCheckbox = _ref => {
|
|
12
|
+
let {
|
|
13
|
+
onFocus,
|
|
14
|
+
onBlur,
|
|
15
|
+
disabled,
|
|
16
|
+
error,
|
|
17
|
+
name,
|
|
18
|
+
value,
|
|
19
|
+
children,
|
|
20
|
+
helper,
|
|
21
|
+
className,
|
|
22
|
+
autoFocus,
|
|
23
|
+
'data-testid': dataTestId
|
|
24
|
+
} = _ref;
|
|
25
|
+
const context = useContext(CheckboxGroupContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('CheckboxGroup.Checkbox can only be used inside a CheckboxGroup');
|
|
28
|
+
}
|
|
29
|
+
const {
|
|
30
|
+
groupName,
|
|
31
|
+
onChange,
|
|
32
|
+
groupValues
|
|
33
|
+
} = context;
|
|
34
|
+
const checkboxName = `${groupName}.${name ?? ''}`;
|
|
35
|
+
const checkboxValue = `${value}`;
|
|
36
|
+
return jsx(Checkbox, {
|
|
37
|
+
onChange: onChange,
|
|
38
|
+
checked: groupValues?.includes(checkboxValue),
|
|
39
|
+
onFocus: onFocus,
|
|
40
|
+
onBlur: onBlur,
|
|
41
|
+
disabled: disabled,
|
|
42
|
+
error: error,
|
|
43
|
+
name: checkboxName,
|
|
44
|
+
value: checkboxValue,
|
|
45
|
+
helper: helper,
|
|
46
|
+
className: className,
|
|
47
|
+
autoFocus: autoFocus,
|
|
48
|
+
"data-testid": dataTestId,
|
|
49
|
+
children: children
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const FieldSet = /*#__PURE__*/_styled("fieldset", {
|
|
53
|
+
target: "e1k5uyng1"
|
|
54
|
+
})(process.env.NODE_ENV === "production" ? {
|
|
55
|
+
name: "7o2an9",
|
|
56
|
+
styles: "border:none;padding:0;margin:0"
|
|
57
|
+
} : {
|
|
58
|
+
name: "7o2an9",
|
|
59
|
+
styles: "border:none;padding:0;margin:0",
|
|
60
|
+
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
|
|
61
|
+
});
|
|
62
|
+
const StyledRequiredIcon = /*#__PURE__*/_styled(Icon, {
|
|
63
|
+
target: "e1k5uyng0"
|
|
64
|
+
})(process.env.NODE_ENV === "production" ? {
|
|
65
|
+
name: "1nglpc5",
|
|
66
|
+
styles: "vertical-align:super"
|
|
67
|
+
} : {
|
|
68
|
+
name: "1nglpc5",
|
|
69
|
+
styles: "vertical-align:super",
|
|
70
|
+
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
|
|
71
|
+
});
|
|
72
|
+
const CheckboxGroup = _ref2 => {
|
|
73
|
+
let {
|
|
74
|
+
legend,
|
|
75
|
+
value,
|
|
76
|
+
className,
|
|
77
|
+
helper,
|
|
78
|
+
error,
|
|
79
|
+
direction = 'column',
|
|
80
|
+
children,
|
|
81
|
+
onChange,
|
|
82
|
+
name,
|
|
83
|
+
required = false
|
|
84
|
+
} = _ref2;
|
|
85
|
+
const contextValue = useMemo(() => ({
|
|
86
|
+
groupName: name,
|
|
87
|
+
groupValues: value ?? [],
|
|
88
|
+
onChange
|
|
89
|
+
}), [name, value, onChange]);
|
|
90
|
+
return jsx(CheckboxGroupContext.Provider, {
|
|
91
|
+
value: contextValue,
|
|
92
|
+
children: jsxs(Stack, {
|
|
93
|
+
gap: 1,
|
|
94
|
+
children: [jsx(FieldSet, {
|
|
95
|
+
className: className,
|
|
96
|
+
children: jsxs(Stack, {
|
|
97
|
+
gap: 1.5,
|
|
98
|
+
children: [jsxs(Text, {
|
|
99
|
+
as: "legend",
|
|
100
|
+
variant: "bodyStrong",
|
|
101
|
+
children: [legend, "\xA0", required ? jsx(StyledRequiredIcon, {
|
|
102
|
+
name: "asterisk",
|
|
103
|
+
color: "danger",
|
|
104
|
+
size: 8
|
|
105
|
+
}) : null]
|
|
106
|
+
}), jsx(Stack, {
|
|
107
|
+
gap: direction === 'column' ? 1 : 2,
|
|
108
|
+
direction: direction,
|
|
109
|
+
children: children
|
|
110
|
+
})]
|
|
111
|
+
})
|
|
112
|
+
}), helper ? jsx(Text, {
|
|
113
|
+
as: "p",
|
|
114
|
+
variant: "bodySmall",
|
|
115
|
+
prominence: "weak",
|
|
116
|
+
children: helper
|
|
117
|
+
}) : null, error ? jsx(Text, {
|
|
118
|
+
as: "p",
|
|
119
|
+
variant: "bodySmall",
|
|
120
|
+
sentiment: "danger",
|
|
121
|
+
prominence: "weak",
|
|
122
|
+
children: error
|
|
123
|
+
}) : null]
|
|
124
|
+
})
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
CheckboxGroup.Checkbox = CheckboxGroupCheckbox;
|
|
128
|
+
|
|
129
|
+
export { CheckboxGroup, CheckboxGroupCheckbox };
|
|
@@ -73,6 +73,7 @@ const Dialog = _ref9 => {
|
|
|
73
73
|
backdropCss
|
|
74
74
|
} = _ref9;
|
|
75
75
|
const containerRef = useRef(document.createElement('div'));
|
|
76
|
+
const dialogRef = useRef(null);
|
|
76
77
|
const onCloseRef = useRef(onClose);
|
|
77
78
|
|
|
78
79
|
// Portal to put the modal in
|
|
@@ -80,6 +81,7 @@ const Dialog = _ref9 => {
|
|
|
80
81
|
const element = containerRef.current;
|
|
81
82
|
if (open) {
|
|
82
83
|
document.body.appendChild(element);
|
|
84
|
+
dialogRef.current?.focus();
|
|
83
85
|
}
|
|
84
86
|
return () => {
|
|
85
87
|
if (document.body.contains(element)) {
|
|
@@ -97,14 +99,26 @@ const Dialog = _ref9 => {
|
|
|
97
99
|
useEffect(() => {
|
|
98
100
|
const handleEscPress = event => {
|
|
99
101
|
if (event.key === 'Escape' && hideOnEsc) {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
event.stopPropagation();
|
|
100
104
|
onCloseRef.current();
|
|
101
105
|
}
|
|
102
106
|
};
|
|
103
107
|
if (open) {
|
|
104
|
-
document.addEventListener('keyup', handleEscPress
|
|
108
|
+
document.body.addEventListener('keyup', handleEscPress, {
|
|
109
|
+
capture: true
|
|
110
|
+
});
|
|
111
|
+
document.body.addEventListener('keydown', handleEscPress, {
|
|
112
|
+
capture: true
|
|
113
|
+
});
|
|
105
114
|
}
|
|
106
115
|
return () => {
|
|
107
|
-
document.removeEventListener('keyup', handleEscPress
|
|
116
|
+
document.body.removeEventListener('keyup', handleEscPress, {
|
|
117
|
+
capture: true
|
|
118
|
+
});
|
|
119
|
+
document.body.removeEventListener('keydown', handleEscPress, {
|
|
120
|
+
capture: true
|
|
121
|
+
});
|
|
108
122
|
};
|
|
109
123
|
}, [open, onCloseRef, hideOnEsc]);
|
|
110
124
|
|
|
@@ -117,6 +131,11 @@ const Dialog = _ref9 => {
|
|
|
117
131
|
}
|
|
118
132
|
}, [preventBodyScroll, open]);
|
|
119
133
|
|
|
134
|
+
// Stop focus to prevent unexpected body loose focus
|
|
135
|
+
const stopFocus = useCallback(event => {
|
|
136
|
+
event.stopPropagation();
|
|
137
|
+
}, []);
|
|
138
|
+
|
|
120
139
|
// Stop click to prevent unexpected dialog close
|
|
121
140
|
const stopClick = useCallback(event => {
|
|
122
141
|
event.stopPropagation();
|
|
@@ -126,15 +145,53 @@ const Dialog = _ref9 => {
|
|
|
126
145
|
const stopKeyUp = useCallback(event => {
|
|
127
146
|
event.stopPropagation();
|
|
128
147
|
}, []);
|
|
148
|
+
|
|
149
|
+
// Enable focus trap inside the modal
|
|
150
|
+
const handleFocusTrap = useCallback(event => {
|
|
151
|
+
event.stopPropagation();
|
|
152
|
+
if (event.key === 'Escape') {
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const isTabPressed = event.key === 'Tab';
|
|
157
|
+
if (!isTabPressed) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const focusableEls = dialogRef.current?.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled])') ?? [];
|
|
161
|
+
|
|
162
|
+
// Handle case when no interactive element are within the modal (including close icon)
|
|
163
|
+
if (focusableEls.length === 0) {
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
}
|
|
166
|
+
const firstFocusableEl = focusableEls[0];
|
|
167
|
+
const lastFocusableEl = focusableEls[focusableEls.length - 1];
|
|
168
|
+
if (event.shiftKey) {
|
|
169
|
+
if (document.activeElement === firstFocusableEl) {
|
|
170
|
+
lastFocusableEl.focus();
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
}
|
|
173
|
+
} else if (document.activeElement === lastFocusableEl) {
|
|
174
|
+
firstFocusableEl.focus();
|
|
175
|
+
event.preventDefault();
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
|
|
179
|
+
// Prevent default behaviour on Escape
|
|
180
|
+
const stopCancel = event => {
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
event.stopPropagation();
|
|
183
|
+
};
|
|
129
184
|
return /*#__PURE__*/createPortal(jsx(StyledBackdrop, {
|
|
130
185
|
"data-open": open,
|
|
131
186
|
onClick: hideOnClickOutside ? onClose : undefined,
|
|
132
187
|
className: backdropClassName,
|
|
133
188
|
css: backdropCss,
|
|
134
189
|
"data-testid": dataTestId ? `${dataTestId}-backdrop` : undefined,
|
|
190
|
+
onFocus: stopFocus,
|
|
135
191
|
children: jsx(StyledDialog, {
|
|
136
192
|
css: dialogCss,
|
|
137
193
|
onKeyUp: stopKeyUp,
|
|
194
|
+
onKeyDown: handleFocusTrap,
|
|
138
195
|
className: className,
|
|
139
196
|
id: id,
|
|
140
197
|
"data-testid": dataTestId,
|
|
@@ -143,6 +200,10 @@ const Dialog = _ref9 => {
|
|
|
143
200
|
"data-size": size,
|
|
144
201
|
open: open,
|
|
145
202
|
onClick: stopClick,
|
|
203
|
+
onCancel: stopCancel,
|
|
204
|
+
onClose: stopCancel,
|
|
205
|
+
"aria-modal": true,
|
|
206
|
+
ref: dialogRef,
|
|
146
207
|
children: open ? children : null
|
|
147
208
|
})
|
|
148
209
|
}), containerRef.current);
|
|
@@ -17,6 +17,11 @@ const Disclosure = _ref => {
|
|
|
17
17
|
element?.removeEventListener('click', handleOpen);
|
|
18
18
|
};
|
|
19
19
|
}, [handleOpen, disclosureRef]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!visible) {
|
|
22
|
+
disclosureRef.current?.focus();
|
|
23
|
+
}
|
|
24
|
+
}, [visible, disclosureRef]);
|
|
20
25
|
if (typeof disclosure === 'function') {
|
|
21
26
|
return disclosure({
|
|
22
27
|
visible,
|
|
@@ -30,7 +35,9 @@ const Disclosure = _ref => {
|
|
|
30
35
|
if ( /*#__PURE__*/isValidElement(disclosure)) {
|
|
31
36
|
return /*#__PURE__*/cloneElement(disclosure, {
|
|
32
37
|
...disclosure.props,
|
|
33
|
-
ref: disclosureRef
|
|
38
|
+
ref: disclosureRef,
|
|
39
|
+
'aria-controls': id,
|
|
40
|
+
'aria-haspopup': 'dialog'
|
|
34
41
|
});
|
|
35
42
|
}
|
|
36
43
|
return null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _styled from '@emotion/styled/base';
|
|
2
|
-
import { useState, useId, useCallback } from 'react';
|
|
2
|
+
import { useState, useId, useCallback, useEffect } from 'react';
|
|
3
3
|
import { Button } from '../Button/index.js';
|
|
4
4
|
import { Dialog } from './Dialog.js';
|
|
5
5
|
import { Disclosure } from './Disclosure.js';
|
|
@@ -61,6 +61,9 @@ const Modal = _ref3 => {
|
|
|
61
61
|
}, []);
|
|
62
62
|
const finalId = id ?? controlId;
|
|
63
63
|
const finalSize = size ?? width;
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
setVisible(opened);
|
|
66
|
+
}, [opened]);
|
|
64
67
|
return jsxs(Fragment, {
|
|
65
68
|
children: [jsx(Disclosure, {
|
|
66
69
|
id: finalId,
|
|
@@ -167,7 +167,8 @@ const Toggle = /*#__PURE__*/forwardRef((_ref23, ref) => {
|
|
|
167
167
|
helper,
|
|
168
168
|
required,
|
|
169
169
|
className,
|
|
170
|
-
'data-testid': dataTestId
|
|
170
|
+
'data-testid': dataTestId,
|
|
171
|
+
value
|
|
171
172
|
} = _ref23;
|
|
172
173
|
const [state, setState] = useState(checked);
|
|
173
174
|
const uniqueId = useId();
|
|
@@ -212,7 +213,8 @@ const Toggle = /*#__PURE__*/forwardRef((_ref23, ref) => {
|
|
|
212
213
|
name: name,
|
|
213
214
|
onChange: onLocalChange,
|
|
214
215
|
type: "checkbox",
|
|
215
|
-
ref: ref
|
|
216
|
+
ref: ref,
|
|
217
|
+
value: value
|
|
216
218
|
})
|
|
217
219
|
})]
|
|
218
220
|
})
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import _styled from '@emotion/styled/base';
|
|
2
|
+
import { Icon } from '@ultraviolet/icons';
|
|
3
|
+
import { useMemo, createContext, useContext } from 'react';
|
|
4
|
+
import { Stack } from '../Stack/index.js';
|
|
5
|
+
import { Text } from '../Text/index.js';
|
|
6
|
+
import { Toggle } from '../Toggle/index.js';
|
|
7
|
+
import { jsx, jsxs } from '@emotion/react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
|
|
10
|
+
const ToggleGroupContext = /*#__PURE__*/createContext(undefined);
|
|
11
|
+
const ToggleGroupToggle = _ref => {
|
|
12
|
+
let {
|
|
13
|
+
disabled,
|
|
14
|
+
name,
|
|
15
|
+
value,
|
|
16
|
+
label,
|
|
17
|
+
helper,
|
|
18
|
+
className,
|
|
19
|
+
'data-testid': dataTestId
|
|
20
|
+
} = _ref;
|
|
21
|
+
const context = useContext(ToggleGroupContext);
|
|
22
|
+
if (!context) {
|
|
23
|
+
throw new Error('ToggleGroup.Toggle can only be used inside a ToggleGroup');
|
|
24
|
+
}
|
|
25
|
+
const {
|
|
26
|
+
groupName,
|
|
27
|
+
onChange,
|
|
28
|
+
groupValues
|
|
29
|
+
} = context;
|
|
30
|
+
const ToggleName = `${groupName}.${name}`;
|
|
31
|
+
const ToggleValue = `${value}`;
|
|
32
|
+
return jsx(Toggle, {
|
|
33
|
+
onChange: onChange,
|
|
34
|
+
checked: groupValues?.includes(ToggleValue),
|
|
35
|
+
disabled: disabled,
|
|
36
|
+
name: ToggleName,
|
|
37
|
+
value: ToggleValue,
|
|
38
|
+
helper: helper,
|
|
39
|
+
className: className,
|
|
40
|
+
"data-testid": dataTestId,
|
|
41
|
+
label: label
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const FieldSet = /*#__PURE__*/_styled("fieldset", {
|
|
45
|
+
target: "e1qvneex1"
|
|
46
|
+
})(process.env.NODE_ENV === "production" ? {
|
|
47
|
+
name: "7o2an9",
|
|
48
|
+
styles: "border:none;padding:0;margin:0"
|
|
49
|
+
} : {
|
|
50
|
+
name: "7o2an9",
|
|
51
|
+
styles: "border:none;padding:0;margin:0",
|
|
52
|
+
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
|
|
53
|
+
});
|
|
54
|
+
const StyledRequiredIcon = /*#__PURE__*/_styled(Icon, {
|
|
55
|
+
target: "e1qvneex0"
|
|
56
|
+
})(process.env.NODE_ENV === "production" ? {
|
|
57
|
+
name: "1nglpc5",
|
|
58
|
+
styles: "vertical-align:super"
|
|
59
|
+
} : {
|
|
60
|
+
name: "1nglpc5",
|
|
61
|
+
styles: "vertical-align:super",
|
|
62
|
+
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
|
|
63
|
+
});
|
|
64
|
+
const ToggleGroup = _ref2 => {
|
|
65
|
+
let {
|
|
66
|
+
legend,
|
|
67
|
+
value,
|
|
68
|
+
className,
|
|
69
|
+
helper,
|
|
70
|
+
error,
|
|
71
|
+
direction = 'column',
|
|
72
|
+
children,
|
|
73
|
+
onChange,
|
|
74
|
+
name,
|
|
75
|
+
required = false
|
|
76
|
+
} = _ref2;
|
|
77
|
+
const contextValue = useMemo(() => ({
|
|
78
|
+
groupName: name,
|
|
79
|
+
groupValues: value ?? [],
|
|
80
|
+
onChange
|
|
81
|
+
}), [name, value, onChange]);
|
|
82
|
+
return jsx(ToggleGroupContext.Provider, {
|
|
83
|
+
value: contextValue,
|
|
84
|
+
children: jsxs(Stack, {
|
|
85
|
+
gap: 1,
|
|
86
|
+
children: [jsx(FieldSet, {
|
|
87
|
+
className: className,
|
|
88
|
+
children: jsxs(Stack, {
|
|
89
|
+
gap: 1.5,
|
|
90
|
+
children: [jsxs(Text, {
|
|
91
|
+
as: "legend",
|
|
92
|
+
variant: "bodyStrong",
|
|
93
|
+
children: [legend, "\xA0", required ? jsx(StyledRequiredIcon, {
|
|
94
|
+
name: "asterisk",
|
|
95
|
+
color: "danger",
|
|
96
|
+
size: 8
|
|
97
|
+
}) : null]
|
|
98
|
+
}), jsx(Stack, {
|
|
99
|
+
gap: 2,
|
|
100
|
+
direction: direction,
|
|
101
|
+
children: children
|
|
102
|
+
})]
|
|
103
|
+
})
|
|
104
|
+
}), helper ? jsx(Text, {
|
|
105
|
+
as: "p",
|
|
106
|
+
variant: "bodySmall",
|
|
107
|
+
prominence: "weak",
|
|
108
|
+
children: helper
|
|
109
|
+
}) : null, error ? jsx(Text, {
|
|
110
|
+
as: "p",
|
|
111
|
+
variant: "bodySmall",
|
|
112
|
+
sentiment: "danger",
|
|
113
|
+
prominence: "weak",
|
|
114
|
+
children: error
|
|
115
|
+
}) : null]
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
ToggleGroup.Toggle = ToggleGroupToggle;
|
|
120
|
+
|
|
121
|
+
export { ToggleGroup, ToggleGroupToggle };
|
package/dist/src/index.js
CHANGED
|
@@ -30,6 +30,7 @@ export { Menu } from './components/Menu/index.js';
|
|
|
30
30
|
export { Meter } from './components/Meter/Meter.js';
|
|
31
31
|
export { Modal } from './components/Modal/Modal.js';
|
|
32
32
|
export { Notice } from './components/Notice/index.js';
|
|
33
|
+
export { CheckboxGroup, CheckboxGroupCheckbox } from './components/CheckboxGroup/index.js';
|
|
33
34
|
export { NumberInput } from './components/NumberInput/index.js';
|
|
34
35
|
export { Pagination } from './components/Pagination/index.js';
|
|
35
36
|
export { PasswordCheck } from './components/PasswordCheck/index.js';
|
|
@@ -59,6 +60,7 @@ export { TextInput } from './components/TextInput/index.js';
|
|
|
59
60
|
export { TimeInput } from './components/TimeInput/index.js';
|
|
60
61
|
export { ToastContainer, toast } from './components/Toaster/index.js';
|
|
61
62
|
export { Toggle } from './components/Toggle/index.js';
|
|
63
|
+
export { ToggleGroup } from './components/ToggleGroup/index.js';
|
|
62
64
|
export { Tooltip } from './components/Tooltip/index.js';
|
|
63
65
|
export { VerificationCode } from './components/VerificationCode/index.js';
|
|
64
66
|
export { RadioGroup } from './components/RadioGroup/index.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultraviolet/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"description": "Ultraviolet UI",
|
|
5
5
|
"homepage": "https://github.com/scaleway/ultraviolet#readme",
|
|
6
6
|
"repository": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react-dom": "18.2.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@babel/core": "7.22.
|
|
42
|
+
"@babel/core": "7.22.15",
|
|
43
43
|
"@emotion/babel-plugin": "11.11.0",
|
|
44
44
|
"@emotion/react": "11.11.1",
|
|
45
45
|
"@emotion/styled": "11.11.0",
|
|
@@ -68,6 +68,6 @@
|
|
|
68
68
|
"react-use-clipboard": "1.0.9",
|
|
69
69
|
"reakit": "1.3.11",
|
|
70
70
|
"@ultraviolet/themes": "1.2.1",
|
|
71
|
-
"@ultraviolet/icons": "
|
|
71
|
+
"@ultraviolet/icons": "2.0.0"
|
|
72
72
|
}
|
|
73
73
|
}
|