@indico-data/design-system 3.17.0 → 3.19.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/lib/components/floatUI/FloatUI.d.ts +1 -1
- package/lib/components/floatUI/types.d.ts +2 -0
- package/lib/components/forms/date/datePicker/types.d.ts +7 -0
- package/lib/components/forms/date/iconTriggerDatePicker/IconTriggerDatePicker.d.ts +3 -0
- package/lib/components/forms/date/iconTriggerDatePicker/types.d.ts +5 -0
- package/lib/components/forms/date/inputDatePicker/SingleInputDatePicker.d.ts +2 -1
- package/lib/components/forms/date/inputDateRangePicker/InputDateRangePicker.d.ts +3 -0
- package/lib/components/forms/date/inputDateRangePicker/types.d.ts +7 -0
- package/lib/components/forms/date/inputDateTimePicker/SingleInputDateTimePicker.d.ts +2 -1
- package/lib/components/forms/select/Select.d.ts +3 -1
- package/lib/components/forms/select/types.d.ts +10 -0
- package/lib/components/forms/subcomponents/Label.d.ts +4 -0
- package/lib/components/forms/subcomponents/types.d.ts +5 -0
- package/lib/components/forms/timePicker/TimePicker.d.ts +4 -1
- package/lib/components/forms/timePicker/types.d.ts +5 -0
- package/lib/components/modal/ConfirmationModal.d.ts +1 -1
- package/lib/components/modal/Modal.d.ts +1 -1
- package/lib/components/modal/Modal.stories.d.ts +4 -0
- package/lib/components/modal/types.d.ts +19 -5
- package/lib/components/pagination/Pagination.d.ts +1 -1
- package/lib/components/pagination/index.d.ts +1 -0
- package/lib/components/pagination/types.d.ts +13 -0
- package/lib/components/stepper/Stepper.d.ts +1 -1
- package/lib/components/stepper/components/BackNavigation.d.ts +2 -1
- package/lib/components/stepper/components/NextNavigation.d.ts +3 -1
- package/lib/components/stepper/types.d.ts +11 -0
- package/lib/components/table/LoadingComponent.d.ts +5 -1
- package/lib/components/table/components/HorizontalStickyHeader.d.ts +4 -1
- package/lib/components/table/hooks/usePinnedColumnsManager.d.ts +2 -2
- package/lib/components/table/types.d.ts +18 -0
- package/lib/components/table/utils/processColumns.d.ts +2 -2
- package/lib/components/tanstackTable/TankstackTable.types.d.ts +19 -2
- package/lib/components/tanstackTable/TanstackTable.d.ts +1 -1
- package/lib/components/tanstackTable/components/NoResults/NoResults.d.ts +2 -1
- package/lib/components/tanstackTable/components/TablePagination/TablePagination.d.ts +3 -1
- package/lib/index.d.ts +146 -24
- package/lib/index.esm.js +135 -63
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +135 -63
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/button/Button.tsx +4 -18
- package/src/components/button/__tests__/Button.test.tsx +30 -28
- package/src/components/floatUI/FloatUI.stories.tsx +14 -0
- package/src/components/floatUI/FloatUI.tsx +5 -0
- package/src/components/floatUI/types.ts +2 -0
- package/src/components/forms/date/datePicker/DatePicker.stories.tsx +10 -0
- package/src/components/forms/date/datePicker/DatePicker.tsx +9 -2
- package/src/components/forms/date/datePicker/types.ts +8 -0
- package/src/components/forms/date/iconTriggerDatePicker/IconTriggerDatePicker.stories.tsx +10 -0
- package/src/components/forms/date/iconTriggerDatePicker/IconTriggerDatePicker.tsx +12 -1
- package/src/components/forms/date/iconTriggerDatePicker/types.ts +5 -0
- package/src/components/forms/date/inputDatePicker/SingleInputDatePicker.tsx +4 -3
- package/src/components/forms/date/inputDatePicker/__tests__/SingleInputDatePicker.test.tsx +2 -0
- package/src/components/forms/date/inputDateRangePicker/InputDateRangePicker.stories.tsx +10 -0
- package/src/components/forms/date/inputDateRangePicker/InputDateRangePicker.tsx +14 -2
- package/src/components/forms/date/inputDateRangePicker/types.ts +7 -0
- package/src/components/forms/date/inputDateTimePicker/SingleInputDateTimePicker.tsx +3 -2
- package/src/components/forms/input/Input.tsx +1 -0
- package/src/components/forms/numberInput/NumberInput.tsx +1 -0
- package/src/components/forms/passwordInput/PasswordInput.tsx +7 -1
- package/src/components/forms/select/Select.stories.tsx +6 -5
- package/src/components/forms/select/Select.tsx +15 -1
- package/src/components/forms/select/types.ts +11 -0
- package/src/components/forms/subcomponents/Label.tsx +20 -3
- package/src/components/forms/subcomponents/types.ts +5 -0
- package/src/components/forms/textarea/Textarea.tsx +1 -0
- package/src/components/forms/timePicker/TimePicker.stories.tsx +10 -0
- package/src/components/forms/timePicker/TimePicker.tsx +10 -1
- package/src/components/forms/timePicker/types.ts +5 -0
- package/src/components/modal/ConfirmationModal.tsx +19 -14
- package/src/components/modal/Modal.stories.tsx +53 -22
- package/src/components/modal/Modal.tsx +8 -2
- package/src/components/modal/types.ts +21 -5
- package/src/components/pagination/Pagination.stories.tsx +11 -0
- package/src/components/pagination/Pagination.tsx +14 -5
- package/src/components/pagination/index.ts +1 -0
- package/src/components/pagination/types.ts +14 -0
- package/src/components/stepper/Stepper.stories.tsx +11 -0
- package/src/components/stepper/Stepper.tsx +16 -2
- package/src/components/stepper/components/BackNavigation.tsx +5 -3
- package/src/components/stepper/components/NextNavigation.tsx +15 -5
- package/src/components/stepper/types.ts +12 -0
- package/src/components/table/LoadingComponent.tsx +6 -2
- package/src/components/table/Table.stories.tsx +10 -0
- package/src/components/table/Table.tsx +12 -2
- package/src/components/table/components/HorizontalStickyHeader.tsx +12 -1
- package/src/components/table/hooks/usePinnedColumnsManager.ts +3 -2
- package/src/components/table/types.ts +20 -0
- package/src/components/table/utils/processColumns.tsx +3 -1
- package/src/components/tanstackTable/TankstackTable.types.ts +20 -2
- package/src/components/tanstackTable/TanstackTable.stories.tsx +8 -6
- package/src/components/tanstackTable/TanstackTable.tsx +21 -11
- package/src/components/tanstackTable/components/NoResults/NoResults.tsx +9 -3
- package/src/components/tanstackTable/components/TablePagination/TablePagination.tsx +4 -1
- package/src/index.ts +1 -1
- package/src/storybook/formArgTypes.ts +10 -0
- package/src/storybookDocs/Permafrost.mdx +8 -0
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import ReactSelect, { Props as ReactSelectProps, components, OptionProps } from 'react-select';
|
|
4
|
-
import { SelectOption } from './types';
|
|
4
|
+
import { SelectOption, SelectText } from './types';
|
|
5
5
|
import { withLabel } from '../subcomponents/Label';
|
|
6
6
|
|
|
7
|
+
const DEFAULT_TEXT: Required<SelectText> = {
|
|
8
|
+
placeholder: 'Select...',
|
|
9
|
+
noOptions: 'No options',
|
|
10
|
+
loading: 'Loading...',
|
|
11
|
+
required: '(required)',
|
|
12
|
+
};
|
|
13
|
+
|
|
7
14
|
export interface SelectProps<OptionType extends SelectOption> extends ReactSelectProps<OptionType> {
|
|
8
15
|
/** Options for the select component */
|
|
9
16
|
options: OptionType[];
|
|
@@ -19,6 +26,8 @@ export interface SelectProps<OptionType extends SelectOption> extends ReactSelec
|
|
|
19
26
|
classNamePrefix?: string;
|
|
20
27
|
/** Event handler for when the selected value changes */
|
|
21
28
|
onChange?: (newValue: any, actionMeta: any) => void;
|
|
29
|
+
/** Customizable display text. */
|
|
30
|
+
text?: SelectText;
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
const OptionComponent = <OptionType extends SelectOption>({
|
|
@@ -43,10 +52,12 @@ const Select = React.forwardRef(
|
|
|
43
52
|
label,
|
|
44
53
|
hasHiddenLabel,
|
|
45
54
|
name,
|
|
55
|
+
text: textProp,
|
|
46
56
|
...props
|
|
47
57
|
}: SelectProps<OptionType>,
|
|
48
58
|
ref: React.Ref<any>,
|
|
49
59
|
) => {
|
|
60
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
50
61
|
const defaultComponents = {
|
|
51
62
|
Option: OptionComponent as React.ComponentType<OptionProps<OptionType>>,
|
|
52
63
|
};
|
|
@@ -59,6 +70,9 @@ const Select = React.forwardRef(
|
|
|
59
70
|
classNamePrefix={classNamePrefix}
|
|
60
71
|
className={classNames('select-wrapper', className)}
|
|
61
72
|
components={mergedComponents}
|
|
73
|
+
placeholder={text.placeholder}
|
|
74
|
+
noOptionsMessage={() => text.noOptions}
|
|
75
|
+
loadingMessage={() => text.loading}
|
|
62
76
|
{...props}
|
|
63
77
|
/>
|
|
64
78
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
import { FormLabelText } from '../subcomponents/Label';
|
|
2
3
|
|
|
3
4
|
export type SelectOption = {
|
|
4
5
|
label: string;
|
|
@@ -6,3 +7,13 @@ export type SelectOption = {
|
|
|
6
7
|
detail?: ReactNode;
|
|
7
8
|
[key: string]: any; // Allow for additional properties
|
|
8
9
|
};
|
|
10
|
+
|
|
11
|
+
/** Customizable text for Select. Extends FormLabelText for label-related text. */
|
|
12
|
+
export interface SelectText extends FormLabelText {
|
|
13
|
+
/** Placeholder text when no option is selected. Default: "Select..." */
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
/** Text when there are no options. Default: "No options" */
|
|
16
|
+
noOptions?: string;
|
|
17
|
+
/** Text while loading options. Default: "Loading..." */
|
|
18
|
+
loading?: string;
|
|
19
|
+
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
|
+
import { FormLabelText } from './types';
|
|
3
|
+
|
|
4
|
+
export type { FormLabelText } from './types';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_TEXT: Required<FormLabelText> = {
|
|
7
|
+
required: '(required)',
|
|
8
|
+
};
|
|
2
9
|
|
|
3
10
|
export interface LabelProps {
|
|
4
11
|
label?: string;
|
|
5
12
|
name: string;
|
|
6
13
|
isRequired?: boolean;
|
|
7
14
|
hasHiddenLabel?: boolean;
|
|
15
|
+
/** Customizable display text. */
|
|
16
|
+
text?: FormLabelText;
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
export const Label = ({ label, name, isRequired }: LabelProps) => {
|
|
@@ -21,17 +30,25 @@ export const Label = ({ label, name, isRequired }: LabelProps) => {
|
|
|
21
30
|
// HOC to add common label functionality to components
|
|
22
31
|
export function withLabel<P extends object>(WrappedComponent: React.ComponentType<P>) {
|
|
23
32
|
const WithLabelComponent = (
|
|
24
|
-
{ label, hasHiddenLabel = false, name, isRequired, ...rest }: P & LabelProps,
|
|
33
|
+
{ label, hasHiddenLabel = false, name, isRequired, text: textProp, ...rest }: P & LabelProps,
|
|
25
34
|
ref: React.Ref<any>,
|
|
26
35
|
) => {
|
|
36
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
27
37
|
const ariaLabel = hasHiddenLabel
|
|
28
|
-
? { 'aria-label': isRequired ? `${label}
|
|
38
|
+
? { 'aria-label': isRequired ? `${label} ${text.required}` : label }
|
|
29
39
|
: {};
|
|
30
40
|
|
|
31
41
|
return (
|
|
32
42
|
<div className="form-control">
|
|
33
43
|
{!hasHiddenLabel && <Label label={label} name={name} isRequired={isRequired} />}
|
|
34
|
-
<WrappedComponent
|
|
44
|
+
<WrappedComponent
|
|
45
|
+
{...(rest as P)}
|
|
46
|
+
id={name}
|
|
47
|
+
name={name}
|
|
48
|
+
{...ariaLabel}
|
|
49
|
+
text={textProp}
|
|
50
|
+
ref={ref}
|
|
51
|
+
/>
|
|
35
52
|
</div>
|
|
36
53
|
);
|
|
37
54
|
};
|
|
@@ -44,6 +44,16 @@ const meta: Meta<typeof TimePicker> = {
|
|
|
44
44
|
control: 'text',
|
|
45
45
|
defaultValue: 'Time Picker',
|
|
46
46
|
},
|
|
47
|
+
text: {
|
|
48
|
+
control: 'object',
|
|
49
|
+
description: 'Customizable text.',
|
|
50
|
+
table: {
|
|
51
|
+
category: 'i18n Text',
|
|
52
|
+
type: {
|
|
53
|
+
summary: '{ validationError?: string }',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
47
57
|
},
|
|
48
58
|
decorators: [
|
|
49
59
|
(Story: React.ComponentType) => (
|
|
@@ -3,6 +3,11 @@ import { Input } from '../input/Input';
|
|
|
3
3
|
import { FloatUI } from '../../floatUI/FloatUI';
|
|
4
4
|
import { formatTimeValue, validateInputValue } from './helpers';
|
|
5
5
|
import { offset, flip, shift } from '@floating-ui/react';
|
|
6
|
+
import { TimePickerText } from './types';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_TEXT: Required<TimePickerText> = {
|
|
9
|
+
validationError: 'Time validation error',
|
|
10
|
+
};
|
|
6
11
|
|
|
7
12
|
interface TimePickerProps {
|
|
8
13
|
ref?: React.LegacyRef<HTMLInputElement>;
|
|
@@ -20,6 +25,8 @@ interface TimePickerProps {
|
|
|
20
25
|
isReadOnly?: boolean;
|
|
21
26
|
isDisabled?: boolean;
|
|
22
27
|
tabIndex?: number;
|
|
28
|
+
/** Customizable display text. */
|
|
29
|
+
text?: TimePickerText;
|
|
23
30
|
[key: string]: unknown;
|
|
24
31
|
}
|
|
25
32
|
|
|
@@ -34,8 +41,10 @@ export const TimePicker = ({
|
|
|
34
41
|
isDisabled,
|
|
35
42
|
isReadOnly,
|
|
36
43
|
tabIndex,
|
|
44
|
+
text: textProp,
|
|
37
45
|
...rest
|
|
38
46
|
}: TimePickerProps) => {
|
|
47
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
39
48
|
const [validationError, setValidationError] = useState('');
|
|
40
49
|
const [inputValue, setInputValue] = useState(timeValue);
|
|
41
50
|
|
|
@@ -82,7 +91,7 @@ export const TimePicker = ({
|
|
|
82
91
|
/>
|
|
83
92
|
{/* This is a temporary work around to address a validation issue in cenote*/}
|
|
84
93
|
<FloatUI
|
|
85
|
-
ariaLabel=
|
|
94
|
+
ariaLabel={text.validationError}
|
|
86
95
|
isOpen={!!validationError}
|
|
87
96
|
setIsOpen={() => {}} // Prevent click-to-open behavior
|
|
88
97
|
isPortal
|
|
@@ -4,16 +4,22 @@ import { Checkbox } from '../forms/checkbox/Checkbox';
|
|
|
4
4
|
import { Col, Row } from '../grid';
|
|
5
5
|
import { Icon } from '../icons/Icon';
|
|
6
6
|
import { Modal } from './Modal';
|
|
7
|
-
import { ConfirmationModalProps } from './types';
|
|
7
|
+
import { ConfirmationModalProps, ConfirmationModalText } from './types';
|
|
8
8
|
import classNames from 'classnames';
|
|
9
9
|
import { useState } from 'react';
|
|
10
10
|
|
|
11
|
+
const DEFAULT_TEXT: Required<ConfirmationModalText> = {
|
|
12
|
+
closeButton: 'Close',
|
|
13
|
+
dontShowAgain: "Don't display this again.",
|
|
14
|
+
confirm: 'Confirm',
|
|
15
|
+
cancel: 'Cancel',
|
|
16
|
+
};
|
|
17
|
+
|
|
11
18
|
const defaultFooter = ({
|
|
12
19
|
onCancelRequest,
|
|
13
20
|
onConfirmRequest,
|
|
14
|
-
|
|
21
|
+
text,
|
|
15
22
|
confirmationButtonVariant,
|
|
16
|
-
cancelButtonText,
|
|
17
23
|
hasDontShowAgainCheckbox,
|
|
18
24
|
isChecked,
|
|
19
25
|
onDontShowAgainChange,
|
|
@@ -24,9 +30,8 @@ const defaultFooter = ({
|
|
|
24
30
|
}: {
|
|
25
31
|
dontShowAgain?: boolean;
|
|
26
32
|
}) => void | Promise<void> | Promise<boolean>;
|
|
27
|
-
|
|
33
|
+
text: Required<ConfirmationModalText>;
|
|
28
34
|
confirmationButtonVariant?: ButtonVariants;
|
|
29
|
-
cancelButtonText?: string;
|
|
30
35
|
hasDontShowAgainCheckbox?: boolean;
|
|
31
36
|
isChecked?: boolean;
|
|
32
37
|
onDontShowAgainChange?: (checked: boolean) => void;
|
|
@@ -35,7 +40,7 @@ const defaultFooter = ({
|
|
|
35
40
|
{hasDontShowAgainCheckbox && (
|
|
36
41
|
<Col>
|
|
37
42
|
<Checkbox
|
|
38
|
-
label=
|
|
43
|
+
label={text.dontShowAgain}
|
|
39
44
|
onChange={(e) => onDontShowAgainChange?.(e.target.checked)}
|
|
40
45
|
isChecked={isChecked}
|
|
41
46
|
id="dont-show-again"
|
|
@@ -44,17 +49,17 @@ const defaultFooter = ({
|
|
|
44
49
|
</Col>
|
|
45
50
|
)}
|
|
46
51
|
<Col xs="content">
|
|
47
|
-
<Button onClick={onCancelRequest} ariaLabel={
|
|
48
|
-
{
|
|
52
|
+
<Button onClick={onCancelRequest} ariaLabel={text.cancel} variant="outline">
|
|
53
|
+
{text.cancel}
|
|
49
54
|
</Button>
|
|
50
55
|
</Col>
|
|
51
56
|
<Col xs="content">
|
|
52
57
|
<Button
|
|
53
58
|
onClick={() => onConfirmRequest?.({ dontShowAgain: isChecked })}
|
|
54
|
-
ariaLabel={
|
|
59
|
+
ariaLabel={text.confirm}
|
|
55
60
|
variant={confirmationButtonVariant}
|
|
56
61
|
>
|
|
57
|
-
{
|
|
62
|
+
{text.confirm}
|
|
58
63
|
</Button>
|
|
59
64
|
</Col>
|
|
60
65
|
</Row>
|
|
@@ -77,15 +82,15 @@ export const ConfirmationModal = ({
|
|
|
77
82
|
children,
|
|
78
83
|
onConfirmRequest,
|
|
79
84
|
onCancelRequest,
|
|
80
|
-
confirmationButtonText = 'Confirm',
|
|
81
|
-
cancelButtonText = 'Cancel',
|
|
82
85
|
confirmationButtonVariant = 'solid',
|
|
83
86
|
icon,
|
|
84
87
|
title,
|
|
85
88
|
status = 'info',
|
|
86
89
|
maxWidthInPixels,
|
|
87
90
|
hasDontShowAgainCheckbox,
|
|
91
|
+
text: textProp,
|
|
88
92
|
}: ConfirmationModalProps) => {
|
|
93
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
89
94
|
const [dontShowAgain, setDontShowAgain] = useState(false);
|
|
90
95
|
|
|
91
96
|
const modalFooter =
|
|
@@ -93,8 +98,7 @@ export const ConfirmationModal = ({
|
|
|
93
98
|
defaultFooter({
|
|
94
99
|
onCancelRequest,
|
|
95
100
|
onConfirmRequest,
|
|
96
|
-
|
|
97
|
-
cancelButtonText,
|
|
101
|
+
text,
|
|
98
102
|
confirmationButtonVariant,
|
|
99
103
|
hasDontShowAgainCheckbox,
|
|
100
104
|
isChecked: dontShowAgain,
|
|
@@ -117,6 +121,7 @@ export const ConfirmationModal = ({
|
|
|
117
121
|
overlayElement={overlayElement}
|
|
118
122
|
footer={modalFooter}
|
|
119
123
|
maxWidthInPixels={maxWidthInPixels}
|
|
124
|
+
text={{ closeButton: text.closeButton }}
|
|
120
125
|
>
|
|
121
126
|
{icon && (
|
|
122
127
|
<Icon
|
|
@@ -173,15 +173,6 @@ const meta: Meta = {
|
|
|
173
173
|
},
|
|
174
174
|
},
|
|
175
175
|
},
|
|
176
|
-
confirmationButtonText: {
|
|
177
|
-
control: 'text',
|
|
178
|
-
table: {
|
|
179
|
-
category: 'Confirmation Modal',
|
|
180
|
-
type: {
|
|
181
|
-
summary: 'string',
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
176
|
confirmationButtonVariant: {
|
|
186
177
|
control: 'select',
|
|
187
178
|
options: ['solid', 'outline', 'link', 'action', 'destructive', 'soft'],
|
|
@@ -192,15 +183,6 @@ const meta: Meta = {
|
|
|
192
183
|
},
|
|
193
184
|
},
|
|
194
185
|
},
|
|
195
|
-
cancelButtonText: {
|
|
196
|
-
control: 'text',
|
|
197
|
-
table: {
|
|
198
|
-
category: 'Confirmation Modal',
|
|
199
|
-
type: {
|
|
200
|
-
summary: 'string',
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
186
|
status: {
|
|
205
187
|
control: 'select',
|
|
206
188
|
options: ['info', 'success', 'error'],
|
|
@@ -230,6 +212,17 @@ const meta: Meta = {
|
|
|
230
212
|
},
|
|
231
213
|
},
|
|
232
214
|
},
|
|
215
|
+
text: {
|
|
216
|
+
control: 'object',
|
|
217
|
+
table: {
|
|
218
|
+
category: 'i18n Text',
|
|
219
|
+
type: {
|
|
220
|
+
summary:
|
|
221
|
+
'{ closeButton?: string; dontShowAgain?: string; confirm?: string; cancel?: string }',
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
description: 'Customizable text.',
|
|
225
|
+
},
|
|
233
226
|
},
|
|
234
227
|
};
|
|
235
228
|
|
|
@@ -320,9 +313,8 @@ export const ConfirmationModalStory: StoryObj<typeof ConfirmationModal> = {
|
|
|
320
313
|
console.log('closed');
|
|
321
314
|
},
|
|
322
315
|
title: 'Disable User',
|
|
323
|
-
confirmationButtonText: 'Delete',
|
|
324
316
|
confirmationButtonVariant: 'destructive',
|
|
325
|
-
|
|
317
|
+
text: { confirm: 'Delete', cancel: 'Cancel' },
|
|
326
318
|
shouldCloseOnOverlayClick: true,
|
|
327
319
|
subtitle: '',
|
|
328
320
|
icon: 'trash',
|
|
@@ -371,9 +363,8 @@ export const ConfirmationModalStoryWithCheckbox: StoryObj<typeof ConfirmationMod
|
|
|
371
363
|
console.log('closed');
|
|
372
364
|
},
|
|
373
365
|
title: 'Disable User',
|
|
374
|
-
confirmationButtonText: 'Delete',
|
|
375
366
|
confirmationButtonVariant: 'destructive',
|
|
376
|
-
|
|
367
|
+
text: { confirm: 'Delete', cancel: 'Cancel' },
|
|
377
368
|
shouldCloseOnOverlayClick: true,
|
|
378
369
|
icon: 'trash',
|
|
379
370
|
status: 'error',
|
|
@@ -420,3 +411,43 @@ export const ConfirmationModalStoryWithCheckbox: StoryObj<typeof ConfirmationMod
|
|
|
420
411
|
);
|
|
421
412
|
},
|
|
422
413
|
};
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Use the `text` prop to customize displayed text.
|
|
417
|
+
*/
|
|
418
|
+
export const WithText: StoryObj<typeof ConfirmationModal> = {
|
|
419
|
+
args: {
|
|
420
|
+
title: 'Désactiver utilisateur',
|
|
421
|
+
confirmationButtonVariant: 'destructive',
|
|
422
|
+
icon: 'trash',
|
|
423
|
+
status: 'error',
|
|
424
|
+
maxWidthInPixels: 600,
|
|
425
|
+
hasDontShowAgainCheckbox: true,
|
|
426
|
+
parentSelector: () => document.body,
|
|
427
|
+
text: {
|
|
428
|
+
confirm: 'Supprimer',
|
|
429
|
+
cancel: 'Annuler',
|
|
430
|
+
closeButton: 'Fermer',
|
|
431
|
+
dontShowAgain: 'Ne plus afficher ce message',
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
|
|
435
|
+
render: (args) => {
|
|
436
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<Container>
|
|
440
|
+
<Row>
|
|
441
|
+
<Col sm={4}>
|
|
442
|
+
<ConfirmationModal {...args} isOpen={isOpen} onRequestClose={() => setIsOpen(false)}>
|
|
443
|
+
<p>French example with custom text.</p>
|
|
444
|
+
</ConfirmationModal>
|
|
445
|
+
<Button ariaLabel="open modal" onClick={() => setIsOpen(true)}>
|
|
446
|
+
Open French Modal
|
|
447
|
+
</Button>
|
|
448
|
+
</Col>
|
|
449
|
+
</Row>
|
|
450
|
+
</Container>
|
|
451
|
+
);
|
|
452
|
+
},
|
|
453
|
+
};
|
|
@@ -2,7 +2,11 @@ import classNames from 'classnames';
|
|
|
2
2
|
import ReactModal from 'react-modal';
|
|
3
3
|
import { Button } from '../button/Button';
|
|
4
4
|
import { Col, Row } from '../grid';
|
|
5
|
-
import { ModalProps } from './types';
|
|
5
|
+
import { ModalProps, ModalText } from './types';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TEXT: Required<ModalText> = {
|
|
8
|
+
closeButton: 'Close',
|
|
9
|
+
};
|
|
6
10
|
|
|
7
11
|
export const Modal = ({
|
|
8
12
|
className = '',
|
|
@@ -25,8 +29,10 @@ export const Modal = ({
|
|
|
25
29
|
subtitle,
|
|
26
30
|
footer,
|
|
27
31
|
maxWidthInPixels,
|
|
32
|
+
text: textProp,
|
|
28
33
|
...rest
|
|
29
34
|
}: ModalProps) => {
|
|
35
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
30
36
|
const modalClasses = classNames('modal', `modal--${position}`, className);
|
|
31
37
|
const overlayClasses = classNames('modal-overlay', overlayClassName);
|
|
32
38
|
|
|
@@ -55,7 +61,7 @@ export const Modal = ({
|
|
|
55
61
|
variant="link"
|
|
56
62
|
size="md"
|
|
57
63
|
iconLeft="x-close"
|
|
58
|
-
ariaLabel=
|
|
64
|
+
ariaLabel={text.closeButton}
|
|
59
65
|
/>
|
|
60
66
|
{hasHeader && (
|
|
61
67
|
<div className="modal-header">
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { ButtonVariants } from '../button/types';
|
|
2
2
|
import { IconName } from '../icons/types';
|
|
3
3
|
|
|
4
|
+
/** Customizable text for Modal. */
|
|
5
|
+
export interface ModalText {
|
|
6
|
+
/** Aria label for the close button. Default: "Close" */
|
|
7
|
+
closeButton?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
export interface ModalProps {
|
|
5
11
|
/** Additional classes for the badge component */
|
|
6
12
|
className?: string;
|
|
@@ -36,9 +42,21 @@ export interface ModalProps {
|
|
|
36
42
|
footer?: React.ReactNode;
|
|
37
43
|
/** The maximum width of the modal in pixels */
|
|
38
44
|
maxWidthInPixels?: number;
|
|
45
|
+
/** Customizable display text. */
|
|
46
|
+
text?: ModalText;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Customizable text for ConfirmationModal. Extends ModalText. */
|
|
50
|
+
export interface ConfirmationModalText extends ModalText {
|
|
51
|
+
/** Label for the "Don't show again" checkbox. Default: "Don't display this again." */
|
|
52
|
+
dontShowAgain?: string;
|
|
53
|
+
/** Text for the confirm button. Default: "Confirm" */
|
|
54
|
+
confirm?: string;
|
|
55
|
+
/** Text for the cancel button. Default: "Cancel" */
|
|
56
|
+
cancel?: string;
|
|
39
57
|
}
|
|
40
58
|
|
|
41
|
-
export interface ConfirmationModalProps extends ModalProps {
|
|
59
|
+
export interface ConfirmationModalProps extends Omit<ModalProps, 'text'> {
|
|
42
60
|
onConfirmRequest?: ({
|
|
43
61
|
dontShowAgain,
|
|
44
62
|
}: {
|
|
@@ -49,12 +67,10 @@ export interface ConfirmationModalProps extends ModalProps {
|
|
|
49
67
|
hasDontShowAgainCheckbox?: boolean;
|
|
50
68
|
/** The variant of the confirmation button. */
|
|
51
69
|
confirmationButtonVariant?: ButtonVariants;
|
|
52
|
-
/** The text of the confirmation button */
|
|
53
|
-
confirmationButtonText?: string;
|
|
54
|
-
/** The text of the cancel button */
|
|
55
|
-
cancelButtonText?: string;
|
|
56
70
|
/** The icon of the modal */
|
|
57
71
|
icon?: IconName;
|
|
58
72
|
/** The status of the modal. This will determine the color of the icon. */
|
|
59
73
|
status?: 'info' | 'success' | 'error';
|
|
74
|
+
/** Customizable display text. */
|
|
75
|
+
text?: ConfirmationModalText;
|
|
60
76
|
}
|
|
@@ -43,6 +43,17 @@ const meta: Meta = {
|
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
|
+
text: {
|
|
47
|
+
control: 'object',
|
|
48
|
+
description: 'Customizable text.',
|
|
49
|
+
table: {
|
|
50
|
+
category: 'i18n Text',
|
|
51
|
+
type: {
|
|
52
|
+
summary:
|
|
53
|
+
'{ previousPage?: string; nextPage?: string; currentPage?: string; of?: string }',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
46
57
|
},
|
|
47
58
|
};
|
|
48
59
|
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import { PaginationProps } from './types';
|
|
3
|
+
import { PaginationProps, PaginationText } from './types';
|
|
4
4
|
import { Container, Row, Col } from '../grid';
|
|
5
5
|
import { Input } from '../forms/input';
|
|
6
6
|
import { Button } from '../button';
|
|
7
7
|
|
|
8
|
+
const DEFAULT_TEXT: Required<PaginationText> = {
|
|
9
|
+
previousPage: 'Previous Page',
|
|
10
|
+
nextPage: 'Next Page',
|
|
11
|
+
currentPage: 'Current Page',
|
|
12
|
+
of: 'of',
|
|
13
|
+
};
|
|
14
|
+
|
|
8
15
|
export const Pagination = ({
|
|
9
16
|
totalPages,
|
|
10
17
|
currentPage = 1,
|
|
11
18
|
onChange,
|
|
12
19
|
className,
|
|
20
|
+
text: textProp,
|
|
13
21
|
...rest
|
|
14
22
|
}: PaginationProps) => {
|
|
23
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
15
24
|
const [inputValue, setInputValue] = useState(currentPage.toString());
|
|
16
|
-
const totalPagesText =
|
|
25
|
+
const totalPagesText = `${text.of} ${totalPages}`;
|
|
17
26
|
const classes = classNames('pagination', className);
|
|
18
27
|
|
|
19
28
|
useEffect(() => {
|
|
@@ -60,7 +69,7 @@ export const Pagination = ({
|
|
|
60
69
|
<div className="pagination__previous">
|
|
61
70
|
<Button
|
|
62
71
|
data-testid="pagination-previous-button"
|
|
63
|
-
ariaLabel=
|
|
72
|
+
ariaLabel={text.previousPage}
|
|
64
73
|
variant="link"
|
|
65
74
|
onClick={handlePreviousPage}
|
|
66
75
|
iconLeft="chevron-left"
|
|
@@ -78,7 +87,7 @@ export const Pagination = ({
|
|
|
78
87
|
})}
|
|
79
88
|
value={totalPages === 0 ? '0' : inputValue}
|
|
80
89
|
name="currentPage"
|
|
81
|
-
label=
|
|
90
|
+
label={text.currentPage}
|
|
82
91
|
hasHiddenLabel
|
|
83
92
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
84
93
|
if (e.key === 'Enter') {
|
|
@@ -103,7 +112,7 @@ export const Pagination = ({
|
|
|
103
112
|
<div className="pagination__next">
|
|
104
113
|
<Button
|
|
105
114
|
data-testid="pagination-next-button"
|
|
106
|
-
ariaLabel=
|
|
115
|
+
ariaLabel={text.nextPage}
|
|
107
116
|
variant="link"
|
|
108
117
|
onClick={handleNextPage}
|
|
109
118
|
iconLeft="chevron-right"
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/** Customizable text for Pagination. */
|
|
2
|
+
export interface PaginationText {
|
|
3
|
+
/** Aria label for previous page button. Default: "Previous Page" */
|
|
4
|
+
previousPage?: string;
|
|
5
|
+
/** Aria label for next page button. Default: "Next Page" */
|
|
6
|
+
nextPage?: string;
|
|
7
|
+
/** Label for current page input. Default: "Current Page" */
|
|
8
|
+
currentPage?: string;
|
|
9
|
+
/** Text between current page and total (e.g., "of"). Default: "of" */
|
|
10
|
+
of?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
export interface PaginationProps {
|
|
2
14
|
/** The total number of pages to be displayed */
|
|
3
15
|
totalPages: number;
|
|
@@ -7,4 +19,6 @@ export interface PaginationProps {
|
|
|
7
19
|
className?: string;
|
|
8
20
|
/** The callback function that is called when the page changes. */
|
|
9
21
|
onChange?: (value: number) => void;
|
|
22
|
+
/** Customizable display text. */
|
|
23
|
+
text?: PaginationText;
|
|
10
24
|
}
|
|
@@ -146,6 +146,17 @@ const meta: Meta = {
|
|
|
146
146
|
},
|
|
147
147
|
},
|
|
148
148
|
},
|
|
149
|
+
text: {
|
|
150
|
+
control: 'object',
|
|
151
|
+
description: 'Customizable text.',
|
|
152
|
+
table: {
|
|
153
|
+
category: 'i18n Text',
|
|
154
|
+
type: {
|
|
155
|
+
summary:
|
|
156
|
+
'{ previousStep?: string; previousStepAriaLabel?: string; nextStep?: string; nextStepAriaLabel?: string; finish?: string; finishAriaLabel?: string }',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
149
160
|
},
|
|
150
161
|
};
|
|
151
162
|
|
|
@@ -2,7 +2,13 @@ import { useState, Children } from 'react';
|
|
|
2
2
|
import { Legend } from './components/Legend';
|
|
3
3
|
import { BackNavigation } from './components/BackNavigation';
|
|
4
4
|
import { NextNavigation } from './components/NextNavigation';
|
|
5
|
-
import { StepperProps } from './types';
|
|
5
|
+
import { StepperProps, StepperText } from './types';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TEXT: Required<StepperText> = {
|
|
8
|
+
previousStep: 'Previous Step',
|
|
9
|
+
nextStep: 'Next Step',
|
|
10
|
+
finish: 'Finish',
|
|
11
|
+
};
|
|
6
12
|
|
|
7
13
|
export const Stepper = ({
|
|
8
14
|
currentStep: externalCurrentStep,
|
|
@@ -14,7 +20,9 @@ export const Stepper = ({
|
|
|
14
20
|
onFinishClick,
|
|
15
21
|
children,
|
|
16
22
|
onStepClick,
|
|
23
|
+
text: textProp,
|
|
17
24
|
}: StepperProps) => {
|
|
25
|
+
const text = { ...DEFAULT_TEXT, ...textProp };
|
|
18
26
|
const [internalCurrentStep, setInternalCurrentStep] = useState(0);
|
|
19
27
|
|
|
20
28
|
const currentStep = externalCurrentStep !== undefined ? externalCurrentStep : internalCurrentStep;
|
|
@@ -71,12 +79,18 @@ export const Stepper = ({
|
|
|
71
79
|
<div className="stepper-steps">{childrenArray[currentStep]}</div>
|
|
72
80
|
</div>
|
|
73
81
|
<div className="stepper-actions">
|
|
74
|
-
<BackNavigation
|
|
82
|
+
<BackNavigation
|
|
83
|
+
isDisabled={isFirstStep}
|
|
84
|
+
onBackClick={handleBackClick}
|
|
85
|
+
label={text.previousStep}
|
|
86
|
+
/>
|
|
75
87
|
<NextNavigation
|
|
76
88
|
isLastStep={isLastStep}
|
|
77
89
|
onNextClick={handleNextClick}
|
|
78
90
|
onFinishClick={handleFinishClick}
|
|
79
91
|
isDisabled={disableNextButton(currentStep)}
|
|
92
|
+
nextLabel={text.nextStep}
|
|
93
|
+
finishLabel={text.finish}
|
|
80
94
|
/>
|
|
81
95
|
</div>
|
|
82
96
|
</div>
|