@transferwise/components 46.103.1 → 46.105.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/build/header/Header.js +60 -43
- package/build/header/Header.js.map +1 -1
- package/build/header/Header.mjs +57 -43
- package/build/header/Header.mjs.map +1 -1
- package/build/i18n/cs.json +2 -0
- package/build/i18n/cs.json.js +2 -0
- package/build/i18n/cs.json.js.map +1 -1
- package/build/i18n/cs.json.mjs +2 -0
- package/build/i18n/cs.json.mjs.map +1 -1
- package/build/i18n/es.json +2 -0
- package/build/i18n/es.json.js +2 -0
- package/build/i18n/es.json.js.map +1 -1
- package/build/i18n/es.json.mjs +2 -0
- package/build/i18n/es.json.mjs.map +1 -1
- package/build/i18n/th.json +2 -0
- package/build/i18n/th.json.js +2 -0
- package/build/i18n/th.json.js.map +1 -1
- package/build/i18n/th.json.mjs +2 -0
- package/build/i18n/th.json.mjs.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/index.mjs +2 -1
- package/build/index.mjs.map +1 -1
- package/build/inputs/SelectInput.js +1 -1
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +1 -1
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js +56 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js.map +1 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs +54 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs.map +1 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.js +23 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.js.map +1 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs +21 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs.map +1 -0
- package/build/listItem/AvatarView/ListItemAvatarView.js +23 -0
- package/build/listItem/AvatarView/ListItemAvatarView.js.map +1 -0
- package/build/listItem/AvatarView/ListItemAvatarView.mjs +21 -0
- package/build/listItem/AvatarView/ListItemAvatarView.mjs.map +1 -0
- package/build/listItem/Button/ListItemButton.js +43 -0
- package/build/listItem/Button/ListItemButton.js.map +1 -0
- package/build/listItem/Button/ListItemButton.mjs +41 -0
- package/build/listItem/Button/ListItemButton.mjs.map +1 -0
- package/build/listItem/Checkbox/ListItemCheckbox.js +30 -0
- package/build/listItem/Checkbox/ListItemCheckbox.js.map +1 -0
- package/build/listItem/Checkbox/ListItemCheckbox.mjs +28 -0
- package/build/listItem/Checkbox/ListItemCheckbox.mjs.map +1 -0
- package/build/listItem/IconButton/ListItemIconButton.js +56 -0
- package/build/listItem/IconButton/ListItemIconButton.js.map +1 -0
- package/build/listItem/IconButton/ListItemIconButton.mjs +54 -0
- package/build/listItem/IconButton/ListItemIconButton.mjs.map +1 -0
- package/build/listItem/Image/ListItemImage.js +31 -0
- package/build/listItem/Image/ListItemImage.js.map +1 -0
- package/build/listItem/Image/ListItemImage.mjs +29 -0
- package/build/listItem/Image/ListItemImage.mjs.map +1 -0
- package/build/listItem/ListItem.js +311 -0
- package/build/listItem/ListItem.js.map +1 -0
- package/build/listItem/ListItem.mjs +306 -0
- package/build/listItem/ListItem.mjs.map +1 -0
- package/build/listItem/ListItemContext.js +8 -0
- package/build/listItem/ListItemContext.js.map +1 -0
- package/build/listItem/ListItemContext.mjs +6 -0
- package/build/listItem/ListItemContext.mjs.map +1 -0
- package/build/listItem/Navigation/ListItemNavigation.js +44 -0
- package/build/listItem/Navigation/ListItemNavigation.js.map +1 -0
- package/build/listItem/Navigation/ListItemNavigation.mjs +42 -0
- package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -0
- package/build/listItem/Prompt/ListItemPrompt.js +59 -0
- package/build/listItem/Prompt/ListItemPrompt.js.map +1 -0
- package/build/listItem/Prompt/ListItemPrompt.mjs +54 -0
- package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -0
- package/build/listItem/Radio/ListItemRadio.js +30 -0
- package/build/listItem/Radio/ListItemRadio.js.map +1 -0
- package/build/listItem/Radio/ListItemRadio.mjs +28 -0
- package/build/listItem/Radio/ListItemRadio.mjs.map +1 -0
- package/build/listItem/Switch/ListItemSwitch.js +30 -0
- package/build/listItem/Switch/ListItemSwitch.js.map +1 -0
- package/build/listItem/Switch/ListItemSwitch.mjs +28 -0
- package/build/listItem/Switch/ListItemSwitch.mjs.map +1 -0
- package/build/listItem/useListItemControl.js +22 -0
- package/build/listItem/useListItemControl.js.map +1 -0
- package/build/listItem/useListItemControl.mjs +20 -0
- package/build/listItem/useListItemControl.mjs.map +1 -0
- package/build/listItem/useListItemMedia.js +21 -0
- package/build/listItem/useListItemMedia.js.map +1 -0
- package/build/listItem/useListItemMedia.mjs +19 -0
- package/build/listItem/useListItemMedia.mjs.map +1 -0
- package/build/main.css +794 -14
- package/build/styles/header/Header.css +21 -14
- package/build/styles/listItem/ListItem.css +773 -0
- package/build/styles/listItem/ListItem.grid.css +370 -0
- package/build/styles/listItem/Prompt/ListItemPrompt.css +157 -0
- package/build/styles/main.css +794 -14
- package/build/title/Title.js +10 -4
- package/build/title/Title.js.map +1 -1
- package/build/title/Title.mjs +6 -4
- package/build/title/Title.mjs.map +1 -1
- package/build/types/header/Header.d.ts +27 -11
- package/build/types/header/Header.d.ts.map +1 -1
- package/build/types/header/index.d.ts +1 -0
- package/build/types/header/index.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts +15 -0
- package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts.map +1 -0
- package/build/types/listItem/AdditionalInfo/index.d.ts +3 -0
- package/build/types/listItem/AdditionalInfo/index.d.ts.map +1 -0
- package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts +18 -0
- package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts.map +1 -0
- package/build/types/listItem/AvatarLayout/index.d.ts +3 -0
- package/build/types/listItem/AvatarLayout/index.d.ts.map +1 -0
- package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts +16 -0
- package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts.map +1 -0
- package/build/types/listItem/AvatarView/index.d.ts +3 -0
- package/build/types/listItem/AvatarView/index.d.ts.map +1 -0
- package/build/types/listItem/Button/ListItemButton.d.ts +20 -0
- package/build/types/listItem/Button/ListItemButton.d.ts.map +1 -0
- package/build/types/listItem/Button/index.d.ts +3 -0
- package/build/types/listItem/Button/index.d.ts.map +1 -0
- package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts +14 -0
- package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts.map +1 -0
- package/build/types/listItem/Checkbox/index.d.ts +3 -0
- package/build/types/listItem/Checkbox/index.d.ts.map +1 -0
- package/build/types/listItem/IconButton/ListItemIconButton.d.ts +18 -0
- package/build/types/listItem/IconButton/ListItemIconButton.d.ts.map +1 -0
- package/build/types/listItem/IconButton/index.d.ts +3 -0
- package/build/types/listItem/IconButton/index.d.ts.map +1 -0
- package/build/types/listItem/Image/ListItemImage.d.ts +25 -0
- package/build/types/listItem/Image/ListItemImage.d.ts.map +1 -0
- package/build/types/listItem/Image/index.d.ts +3 -0
- package/build/types/listItem/Image/index.d.ts.map +1 -0
- package/build/types/listItem/ListItem.d.ts +111 -0
- package/build/types/listItem/ListItem.d.ts.map +1 -0
- package/build/types/listItem/ListItemContext.d.ts +21 -0
- package/build/types/listItem/ListItemContext.d.ts.map +1 -0
- package/build/types/listItem/Navigation/ListItemNavigation.d.ts +15 -0
- package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -0
- package/build/types/listItem/Navigation/index.d.ts +3 -0
- package/build/types/listItem/Navigation/index.d.ts.map +1 -0
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts +16 -0
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -0
- package/build/types/listItem/Prompt/index.d.ts +3 -0
- package/build/types/listItem/Prompt/index.d.ts.map +1 -0
- package/build/types/listItem/Radio/ListItemRadio.d.ts +14 -0
- package/build/types/listItem/Radio/ListItemRadio.d.ts.map +1 -0
- package/build/types/listItem/Radio/index.d.ts +3 -0
- package/build/types/listItem/Radio/index.d.ts.map +1 -0
- package/build/types/listItem/Switch/ListItemSwitch.d.ts +14 -0
- package/build/types/listItem/Switch/ListItemSwitch.d.ts.map +1 -0
- package/build/types/listItem/Switch/index.d.ts +3 -0
- package/build/types/listItem/Switch/index.d.ts.map +1 -0
- package/build/types/listItem/_stories/helpers.d.ts +27 -0
- package/build/types/listItem/_stories/helpers.d.ts.map +1 -0
- package/build/types/listItem/_stories/subcomponents.d.ts +18 -0
- package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -0
- package/build/types/listItem/index.d.ts +14 -0
- package/build/types/listItem/index.d.ts.map +1 -0
- package/build/types/listItem/test-utils.d.ts +7 -0
- package/build/types/listItem/test-utils.d.ts.map +1 -0
- package/build/types/listItem/useListItemControl.d.ts +5 -0
- package/build/types/listItem/useListItemControl.d.ts.map +1 -0
- package/build/types/listItem/useListItemMedia.d.ts +6 -0
- package/build/types/listItem/useListItemMedia.d.ts.map +1 -0
- package/build/types/title/Title.d.ts +4 -5
- package/build/types/title/Title.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/button/Button.spec.tsx +25 -1
- package/src/button/Button.story.tsx +1 -0
- package/src/header/Header.accessibility.docs.mdx +85 -0
- package/src/header/Header.css +21 -14
- package/src/header/Header.less +17 -10
- package/src/header/Header.spec.tsx +68 -50
- package/src/header/Header.story.tsx +190 -36
- package/src/header/Header.tsx +96 -65
- package/src/header/index.ts +1 -0
- package/src/i18n/cs.json +2 -0
- package/src/i18n/es.json +2 -0
- package/src/i18n/th.json +2 -0
- package/src/iconButton/iconButton.spec.tsx +31 -0
- package/src/index.ts +16 -0
- package/src/legacylistItem/LegacyListItem.story.tsx +1 -1
- package/src/legacylistItem/LegacyListItem.tests.story.tsx +2 -1
- package/src/list/List.story.tsx +13 -3
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.spec.tsx +56 -0
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +198 -0
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.tsx +36 -0
- package/src/listItem/AdditionalInfo/index.ts +2 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.spec.tsx +59 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +124 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.tsx +27 -0
- package/src/listItem/AvatarLayout/index.ts +2 -0
- package/src/listItem/AvatarView/ListItemAvatarView.spec.tsx +75 -0
- package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +339 -0
- package/src/listItem/AvatarView/ListItemAvatarView.tsx +27 -0
- package/src/listItem/AvatarView/index.ts +2 -0
- package/src/listItem/Button/ListItemButton.spec.tsx +90 -0
- package/src/listItem/Button/ListItemButton.story.tsx +473 -0
- package/src/listItem/Button/ListItemButton.tsx +56 -0
- package/src/listItem/Button/index.ts +2 -0
- package/src/listItem/Checkbox/ListItemCheckbox.spec.tsx +82 -0
- package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +128 -0
- package/src/listItem/Checkbox/ListItemCheckbox.tsx +33 -0
- package/src/listItem/Checkbox/index.ts +2 -0
- package/src/listItem/IconButton/ListItemIconButton.spec.tsx +131 -0
- package/src/listItem/IconButton/ListItemIconButton.story.tsx +284 -0
- package/src/listItem/IconButton/ListItemIconButton.tsx +73 -0
- package/src/listItem/IconButton/index.ts +2 -0
- package/src/listItem/Image/ListItemImage.spec.tsx +30 -0
- package/src/listItem/Image/ListItemImage.story.tsx +80 -0
- package/src/listItem/Image/ListItemImage.tsx +46 -0
- package/src/listItem/Image/index.ts +2 -0
- package/src/listItem/ListItem.css +773 -0
- package/src/listItem/ListItem.grid.css +370 -0
- package/src/listItem/ListItem.grid.less +622 -0
- package/src/listItem/ListItem.less +291 -0
- package/src/listItem/ListItem.spec.tsx +1511 -0
- package/src/listItem/ListItem.tsx +440 -0
- package/src/listItem/ListItemContext.tsx +26 -0
- package/src/listItem/Navigation/ListItemNavigation.spec.tsx +67 -0
- package/src/listItem/Navigation/ListItemNavigation.story.tsx +114 -0
- package/src/listItem/Navigation/ListItemNavigation.tsx +39 -0
- package/src/listItem/Navigation/index.ts +2 -0
- package/src/listItem/Prompt/ListItemPrompt.css +157 -0
- package/src/listItem/Prompt/ListItemPrompt.less +134 -0
- package/src/listItem/Prompt/ListItemPrompt.spec.tsx +36 -0
- package/src/listItem/Prompt/ListItemPrompt.story.tsx +204 -0
- package/src/listItem/Prompt/ListItemPrompt.tsx +32 -0
- package/src/listItem/Prompt/index.ts +2 -0
- package/src/listItem/Radio/ListItemRadio.spec.tsx +66 -0
- package/src/listItem/Radio/ListItemRadio.story.tsx +111 -0
- package/src/listItem/Radio/ListItemRadio.tsx +33 -0
- package/src/listItem/Radio/index.ts +2 -0
- package/src/listItem/Switch/ListItemSwitch.spec.tsx +47 -0
- package/src/listItem/Switch/ListItemSwitch.story.tsx +79 -0
- package/src/listItem/Switch/ListItemSwitch.tsx +33 -0
- package/src/listItem/Switch/index.ts +2 -0
- package/src/listItem/_stories/ListItem.focus.test.story.tsx +265 -0
- package/src/listItem/_stories/ListItem.layout.test.story.tsx +374 -0
- package/src/listItem/_stories/ListItem.scenarios.story.tsx +228 -0
- package/src/listItem/_stories/ListItem.story.tsx +774 -0
- package/src/listItem/_stories/ListItem.variants.test.story.tsx +274 -0
- package/src/listItem/_stories/helpers.tsx +53 -0
- package/src/listItem/_stories/subcomponents.tsx +141 -0
- package/src/listItem/index.ts +14 -0
- package/src/listItem/test-utils.tsx +33 -0
- package/src/listItem/useListItemControl.tsx +18 -0
- package/src/listItem/useListItemMedia.tsx +16 -0
- package/src/main.css +794 -14
- package/src/main.less +1 -0
- package/src/primitives/PrimitiveAnchor/test/PrimitiveAnchor.spec.tsx +15 -4
- package/src/title/Title.tsx +25 -12
|
@@ -1,95 +1,113 @@
|
|
|
1
1
|
import { render, screen, userEvent } from '../test-utils';
|
|
2
|
-
|
|
3
|
-
import Header from '.';
|
|
2
|
+
import Header, { HeaderProps } from '.';
|
|
4
3
|
|
|
5
4
|
describe('Header', () => {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const defaultProps: HeaderProps = {
|
|
6
|
+
title: 'Header title',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const renderHeader = (props: Partial<HeaderProps> = {}) => {
|
|
10
|
+
return render(<Header {...defaultProps} {...props} />);
|
|
11
|
+
};
|
|
8
12
|
|
|
13
|
+
it('can set header title', () => {
|
|
14
|
+
renderHeader();
|
|
9
15
|
expect(screen.getByText('Header title')).toBeInTheDocument();
|
|
10
16
|
});
|
|
11
17
|
|
|
12
18
|
it('can trigger header action', async () => {
|
|
13
19
|
const onHeaderActionClick = jest.fn();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
onClick: onHeaderActionClick,
|
|
21
|
-
}}
|
|
22
|
-
/>,
|
|
23
|
-
);
|
|
20
|
+
renderHeader({
|
|
21
|
+
action: {
|
|
22
|
+
text: 'Click me!',
|
|
23
|
+
onClick: onHeaderActionClick,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
24
26
|
|
|
25
27
|
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
|
|
26
|
-
|
|
27
28
|
expect(onHeaderActionClick).toHaveBeenCalledTimes(1);
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
it('can set aria-label property for header action', async () => {
|
|
31
32
|
const onHeaderActionClick = jest.fn();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
onClick: onHeaderActionClick,
|
|
40
|
-
}}
|
|
41
|
-
/>,
|
|
42
|
-
);
|
|
33
|
+
renderHeader({
|
|
34
|
+
action: {
|
|
35
|
+
'aria-label': 'Magic',
|
|
36
|
+
text: 'Click me!',
|
|
37
|
+
onClick: onHeaderActionClick,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
43
40
|
|
|
44
41
|
await userEvent.click(screen.getByRole('button', { name: 'Magic' }));
|
|
45
|
-
|
|
46
42
|
expect(onHeaderActionClick).toHaveBeenCalledTimes(1);
|
|
47
43
|
});
|
|
48
44
|
|
|
49
45
|
it('renders header action as a link when href is provided', () => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}}
|
|
58
|
-
/>,
|
|
59
|
-
);
|
|
46
|
+
renderHeader({
|
|
47
|
+
action: {
|
|
48
|
+
'aria-label': 'Click me!',
|
|
49
|
+
text: 'I am a link',
|
|
50
|
+
href: 'https://wise.com',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
60
53
|
|
|
61
54
|
const link = screen.getByRole('link', { name: 'Click me!' });
|
|
62
|
-
|
|
63
55
|
expect(link).toHaveAttribute('href', 'https://wise.com');
|
|
64
56
|
});
|
|
65
57
|
|
|
66
58
|
it('renders header with h5 heading tag by default', () => {
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
renderHeader();
|
|
69
60
|
expect(screen.getByRole('heading', { name: 'Header title', level: 5 })).toBeInTheDocument();
|
|
70
61
|
});
|
|
71
62
|
|
|
72
63
|
it('can render header with specific heading tag', () => {
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
renderHeader({ as: 'h3' });
|
|
75
65
|
expect(screen.getByRole('heading', { name: 'Header title', level: 3 })).toBeInTheDocument();
|
|
76
66
|
});
|
|
77
67
|
|
|
78
|
-
it('
|
|
79
|
-
|
|
68
|
+
it('renders header with group level', () => {
|
|
69
|
+
renderHeader({ level: 'group' });
|
|
70
|
+
const header = screen.getByRole('heading', { name: 'Header title' });
|
|
71
|
+
expect(header).toHaveClass('np-header--group');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('warns if Header as legend is not inside a fieldset', () => {
|
|
75
|
+
const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();
|
|
76
|
+
|
|
77
|
+
renderHeader({ as: 'legend' });
|
|
78
|
+
|
|
79
|
+
expect(consoleWarnMock).toHaveBeenCalledWith(
|
|
80
|
+
'Legends should be the first child in a fieldset, and this is not possible when including an action',
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
consoleWarnMock.mockRestore();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('does not warn if Header as legend is inside a fieldset', () => {
|
|
87
|
+
const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();
|
|
88
|
+
|
|
80
89
|
render(
|
|
81
|
-
<
|
|
82
|
-
as="
|
|
83
|
-
|
|
84
|
-
action={{ text: 'Click me', href: '#', onClick: callback }}
|
|
85
|
-
/>,
|
|
90
|
+
<fieldset>
|
|
91
|
+
<Header as="legend" title="Header title" />
|
|
92
|
+
</fieldset>,
|
|
86
93
|
);
|
|
87
94
|
|
|
95
|
+
expect(consoleWarnMock).not.toHaveBeenCalled();
|
|
96
|
+
|
|
97
|
+
consoleWarnMock.mockRestore();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('runs onClick if specified even when it got href prop', async () => {
|
|
101
|
+
const callback = jest.fn();
|
|
102
|
+
renderHeader({
|
|
103
|
+
as: 'h3',
|
|
104
|
+
action: { text: 'Click me', href: '#', onClick: callback },
|
|
105
|
+
});
|
|
106
|
+
|
|
88
107
|
const button = screen.getByRole('link', { name: 'Click me' });
|
|
89
108
|
expect(button).toBeInTheDocument();
|
|
90
109
|
|
|
91
110
|
await userEvent.click(button);
|
|
92
|
-
|
|
93
111
|
expect(callback).toHaveBeenCalledTimes(1);
|
|
94
112
|
});
|
|
95
113
|
});
|
|
@@ -1,53 +1,207 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
import Header, { HeaderProps } from './Header';
|
|
3
|
+
import { storyConfig } from '../test-utils';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const withContainer = (Story: any) => (
|
|
6
|
+
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
|
7
|
+
<Story />
|
|
8
|
+
</div>
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Not all stories need access to all controls as it causes unnecessary UI noise.
|
|
13
|
+
*/
|
|
14
|
+
const hideControls = (args: string[]) =>
|
|
15
|
+
Object.fromEntries(args.map((item) => [item, { table: { disable: true } }]));
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Reusable render logic for wrapping `Header` in a `<fieldset>` if `as` is `legend`.
|
|
19
|
+
*/
|
|
20
|
+
const renderHeader = (args: HeaderProps) => {
|
|
21
|
+
if (args.as === 'legend') {
|
|
22
|
+
return (
|
|
23
|
+
<fieldset style={{ width: '100%' }}>
|
|
24
|
+
<Header {...args} />
|
|
25
|
+
</fieldset>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return <Header {...args} />;
|
|
10
29
|
};
|
|
11
30
|
|
|
12
|
-
|
|
13
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Helper to generate variants for `AllVariants` story.
|
|
33
|
+
*/
|
|
34
|
+
const renderVariants = () => (
|
|
35
|
+
<div
|
|
36
|
+
className="header-variants"
|
|
37
|
+
style={{ display: 'flex', flexWrap: 'wrap', gap: '16px', maxWidth: '1200px' }}
|
|
38
|
+
>
|
|
39
|
+
{(['h1', 'h2', 'h3', 'legend'] as const).map((as) => (
|
|
40
|
+
<Header key={as} as={as} title={`Header as ${as}`} />
|
|
41
|
+
))}
|
|
42
|
+
{(['section', 'group'] as const).map((level) => (
|
|
43
|
+
<Header key={level} level={level} title={`Header level ${level}`} />
|
|
44
|
+
))}
|
|
14
45
|
<Header
|
|
15
|
-
|
|
46
|
+
as="h2"
|
|
47
|
+
title="Header with Action"
|
|
16
48
|
action={{
|
|
17
|
-
'aria-label': '
|
|
18
|
-
text: '
|
|
19
|
-
onClick: () => alert('Action!'),
|
|
49
|
+
'aria-label': 'Action',
|
|
50
|
+
text: 'Action',
|
|
51
|
+
onClick: () => alert('Action clicked!'),
|
|
20
52
|
}}
|
|
21
53
|
/>
|
|
22
|
-
);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const WithActionAsLink = () => {
|
|
26
|
-
return (
|
|
27
54
|
<Header
|
|
28
|
-
|
|
55
|
+
as="h2"
|
|
56
|
+
title="Header with link"
|
|
29
57
|
action={{
|
|
30
|
-
|
|
58
|
+
'aria-label': 'Action',
|
|
59
|
+
text: 'Action',
|
|
31
60
|
href: 'https://wise.com',
|
|
32
61
|
}}
|
|
33
62
|
/>
|
|
34
|
-
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The stories below document the `Header` component, which is used to structure content and convey hierarchy. <br />
|
|
68
|
+
* For more details, refer to the [design documentation](https://wise.design/components/section-header).
|
|
69
|
+
*/
|
|
70
|
+
const meta: Meta<typeof Header> = {
|
|
71
|
+
component: Header,
|
|
72
|
+
title: 'Typography/Header',
|
|
73
|
+
argTypes: {
|
|
74
|
+
level: {
|
|
75
|
+
type: {
|
|
76
|
+
name: 'enum',
|
|
77
|
+
value: ['section', 'group'],
|
|
78
|
+
},
|
|
79
|
+
table: {
|
|
80
|
+
type: {
|
|
81
|
+
summary: 'HeaderLevel',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
description: 'Defines the hierarchical level of the header.',
|
|
85
|
+
},
|
|
86
|
+
as: {
|
|
87
|
+
type: {
|
|
88
|
+
name: 'enum',
|
|
89
|
+
value: ['h1', 'h2', 'h3', 'legend'],
|
|
90
|
+
},
|
|
91
|
+
table: {
|
|
92
|
+
type: {
|
|
93
|
+
summary: 'HeaderAs',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
description:
|
|
97
|
+
'Defines which HTML element the Header will render as. Use `legend` only as the first child of a `<fieldset>` — otherwise a warning will appear. The `action` prop is not supported with `legend`. You can also use heading tags like `h1`, `h2`, `h3`, or `header`.',
|
|
98
|
+
},
|
|
99
|
+
action: {
|
|
100
|
+
table: {
|
|
101
|
+
type: {
|
|
102
|
+
summary: 'HeaderAction',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
description: 'Defines an optional action (e.g., button or link) associated with the header.',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
args: {
|
|
109
|
+
title: 'Default Header',
|
|
110
|
+
level: 'group',
|
|
111
|
+
as: 'h1',
|
|
112
|
+
action: undefined,
|
|
113
|
+
},
|
|
114
|
+
tags: ['autodocs'],
|
|
115
|
+
decorators: [withContainer],
|
|
116
|
+
parameters: {
|
|
117
|
+
docs: {
|
|
118
|
+
toc: true,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
35
121
|
};
|
|
36
122
|
|
|
37
|
-
export
|
|
38
|
-
return (
|
|
39
|
-
<Header
|
|
40
|
-
title="Header title"
|
|
41
|
-
action={{
|
|
42
|
-
text: 'This is a link',
|
|
43
|
-
href: 'https://wise.com',
|
|
44
|
-
onClick: (event: React.MouseEvent<HTMLElement>) => {
|
|
45
|
-
alert('Running onClick handler');
|
|
123
|
+
export default meta;
|
|
46
124
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
125
|
+
type Story = StoryObj<typeof Header>;
|
|
126
|
+
|
|
127
|
+
export const Playground: Story = {
|
|
128
|
+
render: renderHeader,
|
|
129
|
+
args: {
|
|
130
|
+
title: 'Playground Header',
|
|
131
|
+
level: 'group',
|
|
132
|
+
as: 'h2',
|
|
133
|
+
action: {
|
|
134
|
+
'aria-label': 'Action',
|
|
135
|
+
text: 'Click me',
|
|
136
|
+
onClick: () => alert('Action clicked!'),
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Demonstrates a `Header` with an associated action.
|
|
143
|
+
*/
|
|
144
|
+
export const Action: Story = {
|
|
145
|
+
args: {
|
|
146
|
+
title: 'Header with Action',
|
|
147
|
+
action: {
|
|
148
|
+
'aria-label': 'Action',
|
|
149
|
+
text: 'Action',
|
|
150
|
+
onClick: () => alert('Action clicked!'),
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
argTypes: hideControls(['as', 'className', 'level', 'title', 'testId']),
|
|
53
154
|
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Demonstrates a `Header` with an associated action as a link.
|
|
158
|
+
*/
|
|
159
|
+
export const ActionAsLink: Story = {
|
|
160
|
+
args: {
|
|
161
|
+
title: 'Header with Action as Link',
|
|
162
|
+
action: {
|
|
163
|
+
'aria-label': 'Learn more about this section',
|
|
164
|
+
text: 'Learn more',
|
|
165
|
+
href: 'https://wise.com',
|
|
166
|
+
target: '_blank',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
argTypes: hideControls(['as', 'className', 'level', 'title', 'testId']),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Demonstrates a `Header` rendered as a custom HTML element.
|
|
174
|
+
*/
|
|
175
|
+
export const CustomElement: Story = {
|
|
176
|
+
render: renderHeader,
|
|
177
|
+
args: {
|
|
178
|
+
title: 'Legend Header',
|
|
179
|
+
as: 'legend',
|
|
180
|
+
},
|
|
181
|
+
argTypes: hideControls(['action', 'className', 'level', 'testId']),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Demonstrates a `Header` with a specific hierarchical level.
|
|
186
|
+
*/
|
|
187
|
+
export const SectionLevel: Story = {
|
|
188
|
+
args: {
|
|
189
|
+
title: 'Section Header',
|
|
190
|
+
level: 'section',
|
|
191
|
+
},
|
|
192
|
+
argTypes: hideControls(['action', 'as', 'className', 'title', 'testId']),
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Displays all variants of the `Header` component, including different levels, tags, and actions.
|
|
197
|
+
*/
|
|
198
|
+
export const AllVariants = storyConfig(
|
|
199
|
+
{
|
|
200
|
+
tags: ['!autodocs'],
|
|
201
|
+
parameters: {
|
|
202
|
+
padding: '0',
|
|
203
|
+
},
|
|
204
|
+
render: renderVariants,
|
|
205
|
+
},
|
|
206
|
+
{ variants: ['default', 'dark', 'bright-green', 'forest-green', 'rtl'] },
|
|
207
|
+
);
|
package/src/header/Header.tsx
CHANGED
|
@@ -1,102 +1,133 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
|
|
3
|
-
import { ActionButtonProps } from '../actionButton/ActionButton';
|
|
4
|
-
import Button from '../button';
|
|
5
3
|
import { AriaLabelProperty, CommonProps, Heading, LinkProps, Typography } from '../common';
|
|
4
|
+
import Button from '../button';
|
|
6
5
|
import Link from '../link';
|
|
7
6
|
import Title from '../title';
|
|
8
|
-
import {
|
|
7
|
+
import React, { useEffect, useRef, FunctionComponent } from 'react';
|
|
9
8
|
|
|
10
9
|
type ActionProps = AriaLabelProperty & {
|
|
11
10
|
text: string;
|
|
11
|
+
onClick?: () => void;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
type ButtonActionProps = ActionProps
|
|
15
|
-
|
|
14
|
+
type ButtonActionProps = ActionProps;
|
|
16
15
|
type LinkActionProps = ActionProps & LinkProps;
|
|
17
16
|
|
|
18
|
-
export
|
|
17
|
+
export interface HeaderProps extends CommonProps {
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
19
|
+
* Optional prop to define the action for the header. If the `href` property
|
|
20
|
+
* is provided, a `Link` will be rendered instead of a `Button`.
|
|
21
21
|
*/
|
|
22
22
|
action?: ButtonActionProps | LinkActionProps;
|
|
23
|
+
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* Option prop to specify DOM render element of the title
|
|
26
|
+
*
|
|
27
|
+
* - When `as="legend"`, the `Header` will render as a `<legend>` element.
|
|
28
|
+
* **Note:** `<legend>` elements must be the first child of a `<fieldset>` to comply with HTML semantics.
|
|
29
|
+
* If this condition is not met, a warning will be logged to the console.
|
|
25
30
|
*
|
|
26
|
-
*
|
|
31
|
+
* - Other valid values include standard heading tags (`h1` to `h6`) or `header`.
|
|
27
32
|
*/
|
|
28
33
|
as?: Heading | 'legend' | 'header';
|
|
34
|
+
|
|
35
|
+
/** Required prop to set the title of the Header. */
|
|
29
36
|
title: string;
|
|
30
|
-
} & Pick<HTMLAttributes<HTMLDivElement>, 'role' | 'id'>;
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
'aria-label': action['aria-label'],
|
|
35
|
-
};
|
|
38
|
+
/** Optional prop to specify the level of the Header */
|
|
39
|
+
level?: 'section' | 'group';
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{action.text}
|
|
41
|
-
</Link>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
41
|
+
className?: string;
|
|
42
|
+
testId?: string;
|
|
43
|
+
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Renders a header action which can be either a button or a link.
|
|
47
|
+
*
|
|
48
|
+
* @param {Object} props - The properties object.
|
|
49
|
+
* @param {ButtonActionProps | LinkActionProps} props.action - The action object which can be either a button or a link.
|
|
50
|
+
* @returns {JSX.Element} The rendered header action component.
|
|
51
|
+
*/
|
|
52
|
+
const HeaderAction = React.forwardRef<
|
|
53
|
+
HTMLButtonElement | HTMLAnchorElement,
|
|
54
|
+
{ action: ButtonActionProps | LinkActionProps }
|
|
55
|
+
>(({ action }, ref) => {
|
|
45
56
|
return (
|
|
46
|
-
<
|
|
47
|
-
className="np-
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
<Link
|
|
58
|
+
className="np-header__action-button"
|
|
59
|
+
aria-label={action['aria-label']}
|
|
60
|
+
href={'href' in action ? action.href : undefined}
|
|
61
|
+
target={'target' in action ? action.target : undefined}
|
|
50
62
|
onClick={action.onClick}
|
|
51
|
-
{...props}
|
|
52
63
|
>
|
|
53
64
|
{action.text}
|
|
54
|
-
</
|
|
65
|
+
</Link>
|
|
55
66
|
);
|
|
56
|
-
};
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
HeaderAction.displayName = 'HeaderAction';
|
|
57
70
|
|
|
58
71
|
/**
|
|
72
|
+
* @param {ButtonActionProps | LinkActionProps} [action] - Optional prop to specify the action button or link.
|
|
73
|
+
* @param {Heading | 'legend'} [as='h5'] - Optional prop to override the heading element rendered for the title.
|
|
74
|
+
* @param {string} title - Required prop to set the title of the section header.
|
|
75
|
+
* @param {'group' | 'section'} [level='group'] - Optional prop to specify the level of the section header.
|
|
76
|
+
* @param {string} [className]
|
|
77
|
+
* @param {string} [testId]
|
|
59
78
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
79
|
+
* @see {@link Header } for further information.
|
|
80
|
+
* @see {@link https://storybook.wise.design/?path=/docs/typography-header--docs|Storybook Wise Design}
|
|
62
81
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
82
|
+
const Header: FunctionComponent<HeaderProps> = React.forwardRef(
|
|
83
|
+
(
|
|
84
|
+
{ as = 'h5', action, className, testId, title, level = 'group', ...props },
|
|
85
|
+
ref: React.Ref<HTMLDivElement | HTMLHeadingElement | HTMLLegendElement>,
|
|
86
|
+
) => {
|
|
87
|
+
const internalRef = useRef<HTMLLegendElement>(null);
|
|
88
|
+
const levelTypography =
|
|
89
|
+
level === 'group' ? Typography.TITLE_GROUP : Typography.TITLE_SUBSECTION;
|
|
90
|
+
const isLegendOrNoAction = !action || as === 'legend';
|
|
91
|
+
const headerClasses = clsx('np-header', className, {
|
|
92
|
+
'np-header--group': level === 'group',
|
|
93
|
+
'np-header__title': isLegendOrNoAction,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const commonProps = {
|
|
97
|
+
className: headerClasses,
|
|
98
|
+
'data-testid': testId,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (as === 'legend' && internalRef.current) {
|
|
103
|
+
const { parentElement } = internalRef.current;
|
|
104
|
+
if (!parentElement || parentElement.tagName.toLowerCase() !== 'fieldset') {
|
|
105
|
+
console.warn(
|
|
106
|
+
'Legends should be the first child in a fieldset, and this is not possible when including an action',
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}, [as]);
|
|
84
111
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
112
|
+
if (!action) {
|
|
113
|
+
return (
|
|
114
|
+
<Title ref={internalRef} as={as} type={levelTypography} {...commonProps} {...props}>
|
|
115
|
+
{title}
|
|
116
|
+
</Title>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div {...commonProps} {...props} ref={ref as React.Ref<HTMLDivElement>}>
|
|
122
|
+
<Title as={as} type={levelTypography} className="np-header__title">
|
|
123
|
+
{title}
|
|
124
|
+
</Title>
|
|
125
|
+
<HeaderAction action={action} />
|
|
126
|
+
</div>
|
|
89
127
|
);
|
|
90
|
-
}
|
|
128
|
+
},
|
|
129
|
+
);
|
|
91
130
|
|
|
92
|
-
|
|
93
|
-
<div className={clsx('np-header', className)}>
|
|
94
|
-
<Title as={as} type={Typography.TITLE_GROUP} id={id} className="np-header__title">
|
|
95
|
-
{title}
|
|
96
|
-
</Title>
|
|
97
|
-
<HeaderAction action={action} />
|
|
98
|
-
</div>
|
|
99
|
-
);
|
|
100
|
-
};
|
|
131
|
+
Header.displayName = 'Header';
|
|
101
132
|
|
|
102
133
|
export default Header;
|
package/src/header/index.ts
CHANGED
package/src/i18n/cs.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"neptune.Upload.csFailureText": "Nahrání se nezdařilo. Zkuste to prosím později",
|
|
46
46
|
"neptune.Upload.csSuccessText": "Úspěšně nahráno!",
|
|
47
47
|
"neptune.Upload.csTooLargeMessage": "Nahrajte soubor menší než {maxSize} MB",
|
|
48
|
+
"neptune.Upload.csTooLargeNoLimitMessage": "Nahrajte menší soubor",
|
|
48
49
|
"neptune.Upload.csWrongTypeMessage": "Tento formát souboru není podporován. Zkuste to znovu s jiným souborem",
|
|
49
50
|
"neptune.Upload.psButtonText": "Zrušit",
|
|
50
51
|
"neptune.Upload.psProcessingText": "Načítání...",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"neptune.Upload.usButtonText": "Nebo vyberte soubor",
|
|
53
54
|
"neptune.Upload.usDropMessage": "Přetáhněte soubor a zahajte nahrávání",
|
|
54
55
|
"neptune.Upload.usPlaceholder": "Přetáhněte soubor menší než {maxSize} MB",
|
|
56
|
+
"neptune.Upload.usPlaceholderNoLimit": "Přetáhněte soubor",
|
|
55
57
|
"neptune.UploadButton.allFileTypes": "Všechny typy souborů",
|
|
56
58
|
"neptune.UploadButton.dropFiles": "Přetáhněte soubor a zahajte nahrávání",
|
|
57
59
|
"neptune.UploadButton.instructions": "{fileTypes}, menší než {size} MB",
|
package/src/i18n/es.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"neptune.Upload.csFailureText": "La carga del archivo ha fallado. Por favor, inténtalo de nuevo",
|
|
46
46
|
"neptune.Upload.csSuccessText": "¡Se ha subido el archivo!",
|
|
47
47
|
"neptune.Upload.csTooLargeMessage": "Proporciona un archivo menor de {maxSize} MB",
|
|
48
|
+
"neptune.Upload.csTooLargeNoLimitMessage": "Proporciona un archivo más pequeño",
|
|
48
49
|
"neptune.Upload.csWrongTypeMessage": "Tipo de archivo no aceptado. Por favor, inténtalo de nuevo con un archivo diferente",
|
|
49
50
|
"neptune.Upload.psButtonText": "Cancela",
|
|
50
51
|
"neptune.Upload.psProcessingText": "Subiendo...",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"neptune.Upload.usButtonText": "O selecciona un archivo",
|
|
53
54
|
"neptune.Upload.usDropMessage": "Arrastra un archivo para subirlo",
|
|
54
55
|
"neptune.Upload.usPlaceholder": "Arrastra y suelta un archivo de menos de {maxSize} MB",
|
|
56
|
+
"neptune.Upload.usPlaceholderNoLimit": "Arrastra y suelta un archivo",
|
|
55
57
|
"neptune.UploadButton.allFileTypes": "Todos los tipos de archivos",
|
|
56
58
|
"neptune.UploadButton.dropFiles": "Arrastra un archivo para subirlo",
|
|
57
59
|
"neptune.UploadButton.instructions": "{fileTypes}, menor que {size}MB",
|
package/src/i18n/th.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"neptune.Upload.csFailureText": "การอัปโหลดล้มเหลว กรุณาลองอีกครั้ง",
|
|
46
46
|
"neptune.Upload.csSuccessText": "อัปโหลดเรียบร้อย!",
|
|
47
47
|
"neptune.Upload.csTooLargeMessage": "กรุณาใช้ไฟล์ที่มีขนาดเล็กกว่า {maxSize} MB",
|
|
48
|
+
"neptune.Upload.csTooLargeNoLimitMessage": "โปรดอัปโหลดไฟล์ที่เล็กลง",
|
|
48
49
|
"neptune.Upload.csWrongTypeMessage": "ไม่รองรับประเภทไฟล์ โปรดลองอีกครั้งโดยใช้ไฟล์อื่น",
|
|
49
50
|
"neptune.Upload.psButtonText": "ยกเลิก",
|
|
50
51
|
"neptune.Upload.psProcessingText": "กำลังอัปโหลด...",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"neptune.Upload.usButtonText": "หรือเลือกไฟล์",
|
|
53
54
|
"neptune.Upload.usDropMessage": "วางไฟล์เพื่อเริ่มการอัปโหลด",
|
|
54
55
|
"neptune.Upload.usPlaceholder": "ลากและวางไฟล์ที่น้อยกว่า {maxSize} MB",
|
|
56
|
+
"neptune.Upload.usPlaceholderNoLimit": "ลากและวางไฟล์",
|
|
55
57
|
"neptune.UploadButton.allFileTypes": "ไฟล์ทุกประเภท",
|
|
56
58
|
"neptune.UploadButton.dropFiles": "วางไฟล์เพื่อเริ่มการอัปโหลด",
|
|
57
59
|
"neptune.UploadButton.instructions": "{fileTypes} น้อยกว่า {size} MB",
|