@scottish-government/designsystem-react 0.7.0 → 0.8.0-beta.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/@types/common/AbstractNotificationBanner.d.ts +2 -2
- package/@types/common/ActionLink.d.ts +8 -0
- package/@types/common/FileIcon.d.ts +1 -1
- package/@types/common/Icon.d.ts +1 -1
- package/@types/components/Accordion.d.ts +0 -1
- package/@types/components/Breadcrumbs.d.ts +2 -5
- package/@types/components/Checkbox.d.ts +0 -2
- package/@types/components/ConfirmationMessage.d.ts +1 -1
- package/@types/components/ContentsNav.d.ts +4 -6
- package/@types/components/DatePicker.d.ts +1 -1
- package/@types/components/ErrorSummary.d.ts +3 -4
- package/@types/components/NotificationPanel.d.ts +1 -1
- package/@types/components/Pagination.d.ts +5 -4
- package/@types/components/PhaseBanner.d.ts +0 -1
- package/@types/components/Question.d.ts +1 -1
- package/@types/components/RadioButton.d.ts +0 -1
- package/@types/components/Select.d.ts +0 -7
- package/@types/components/SequentialNavigation.d.ts +4 -4
- package/@types/components/SideNavigation.d.ts +4 -5
- package/@types/components/SiteFooter.d.ts +25 -0
- package/@types/components/SiteHeader.d.ts +10 -3
- package/@types/components/SiteNavigation.d.ts +2 -3
- package/@types/components/SkipLinks.d.ts +3 -4
- package/@types/components/SummaryCard.d.ts +0 -2
- package/@types/components/SummaryList.d.ts +0 -13
- package/@types/components/Tabs.d.ts +0 -1
- package/@types/components/Tag.d.ts +1 -3
- package/@types/components/TaskList.d.ts +1 -0
- package/@types/sgds.d.ts +13 -2
- package/CHANGELOG.md +63 -1
- package/dist/common/AbstractNotificationBanner.jsx +8 -6
- package/dist/common/ActionLink.jsx +19 -0
- package/dist/common/FileIcon.jsx +2 -7
- package/dist/common/Icon.jsx +3 -9
- package/dist/components/Accordion/Accordion.jsx +12 -7
- package/dist/components/Breadcrumbs/Breadcrumbs.jsx +20 -15
- package/dist/components/Checkbox/Checkbox.jsx +4 -29
- package/dist/components/{aspect-box/aspect-box.jsx → Checkbox/CheckboxGroup.jsx} +14 -30
- package/dist/components/ContentsNav/ContentsNav.jsx +27 -16
- package/dist/components/CookieBanner/CookieBanner.jsx +1 -0
- package/dist/components/DatePicker/DatePicker.jsx +5 -5
- package/dist/components/ErrorSummary/ErrorSummary.jsx +28 -18
- package/dist/components/NotificationBanner/NotificationBanner.jsx +2 -2
- package/dist/components/Pagination/Pagination.jsx +42 -22
- package/dist/components/PhaseBanner/PhaseBanner.jsx +3 -3
- package/dist/components/Question/Question.jsx +3 -3
- package/dist/components/RadioButton/RadioButton.jsx +7 -17
- package/dist/components/RadioButton/RadioGroup.jsx +21 -0
- package/dist/components/Select/Select.jsx +4 -7
- package/dist/components/SequentialNavigation/SequentialNavigation.jsx +31 -18
- package/dist/components/SideNavigation/SideNavigation.jsx +17 -16
- package/dist/components/SiteFooter/SiteFooter.jsx +104 -0
- package/dist/components/SiteHeader/SiteHeader.jsx +113 -32
- package/dist/components/SiteNavigation/SiteNavigation.jsx +20 -7
- package/dist/components/SkipLinks/SkipLinks.jsx +10 -10
- package/dist/components/SummaryCard/SummaryCard.jsx +25 -14
- package/dist/components/SummaryList/SummaryList.jsx +65 -47
- package/dist/components/Tabs/Tabs.jsx +6 -6
- package/dist/components/Tag/Tag.jsx +2 -2
- package/dist/components/TaskList/TaskList.jsx +14 -3
- package/dist/components/TextInput/TextInput.jsx +3 -3
- package/dist/components/Textarea/Textarea.jsx +3 -3
- package/dist/hooks/useTracking.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/context.js +5 -0
- package/package.json +2 -2
- package/src/common/AbstractNotificationBanner.test.tsx +1 -1
- package/src/common/AbstractNotificationBanner.tsx +14 -13
- package/src/common/ActionLink.test.tsx +80 -0
- package/src/common/ActionLink.tsx +27 -0
- package/src/common/ConditionalWrapper.tsx +1 -1
- package/src/common/FileIcon.tsx +7 -11
- package/src/common/HintText.tsx +2 -2
- package/src/common/Icon.tsx +13 -17
- package/src/common/ScreenReaderText.tsx +2 -2
- package/src/common/WrapperTag.tsx +2 -2
- package/src/components/Accordion/Accordion.test.tsx +17 -4
- package/src/components/Accordion/Accordion.tsx +19 -14
- package/src/components/AspectBox/AspectBox.tsx +2 -2
- package/src/components/BackToTop/BackToTop.tsx +2 -2
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +79 -48
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +31 -31
- package/src/components/Button/Button.tsx +2 -2
- package/src/components/Checkbox/Checkbox.test.tsx +1 -96
- package/src/components/Checkbox/Checkbox.tsx +8 -55
- package/src/components/Checkbox/CheckboxGroup.test.tsx +37 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +41 -0
- package/src/components/ConfirmationMessage/ConfirmationMessage.tsx +2 -2
- package/src/components/ContentsNav/ContentsNav.test.tsx +40 -51
- package/src/components/ContentsNav/ContentsNav.tsx +32 -25
- package/src/components/CookieBanner/CookieBanner.tsx +3 -3
- package/src/components/DatePicker/DatePicker.test.tsx +1 -1
- package/src/components/DatePicker/DatePicker.tsx +7 -7
- package/src/components/Details/Details.tsx +2 -2
- package/src/components/ErrorMessage/ErrorMessage.tsx +2 -2
- package/src/components/ErrorSummary/ErrorSummary.test.tsx +40 -34
- package/src/components/ErrorSummary/ErrorSummary.tsx +40 -32
- package/src/components/FileDownload/FileDownload.tsx +2 -2
- package/src/components/HideThisPage/HideThisPage.tsx +2 -2
- package/src/components/InsetText/InsetText.tsx +2 -2
- package/src/components/NotificationBanner/NotificationBanner.tsx +6 -7
- package/src/components/NotificationPanel/NotificationPanel.tsx +2 -2
- package/src/components/PageHeader/PageHeader.tsx +2 -2
- package/src/components/PageMetadata/PageMetadata.tsx +4 -5
- package/src/components/Pagination/Pagination.test.tsx +26 -7
- package/src/components/Pagination/Pagination.tsx +70 -36
- package/src/components/PhaseBanner/PhaseBanner.tsx +4 -5
- package/src/components/Question/Question.test.tsx +1 -1
- package/src/components/Question/Question.tsx +5 -5
- package/src/components/RadioButton/RadioButton.test.tsx +7 -126
- package/src/components/RadioButton/RadioButton.tsx +10 -41
- package/src/components/RadioButton/RadioGroup.test.tsx +65 -0
- package/src/components/RadioButton/RadioGroup.tsx +31 -0
- package/src/components/Select/Select.test.tsx +39 -37
- package/src/components/Select/Select.tsx +7 -22
- package/src/components/SequentialNavigation/SequentialNavigation.test.tsx +32 -21
- package/src/components/SequentialNavigation/SequentialNavigation.tsx +52 -30
- package/src/components/SideNavigation/SideNavigation.test.tsx +39 -85
- package/src/components/SideNavigation/SideNavigation.tsx +27 -29
- package/src/components/SiteFooter/SiteFooter.test.tsx +153 -0
- package/src/components/SiteFooter/SiteFooter.tsx +107 -0
- package/src/components/SiteHeader/SiteHeader.test.tsx +87 -79
- package/src/components/SiteHeader/SiteHeader.tsx +103 -40
- package/src/components/SiteNavigation/SiteNavigation.test.tsx +42 -23
- package/src/components/SiteNavigation/SiteNavigation.tsx +28 -16
- package/src/components/SiteSearch/SiteSearch.tsx +2 -2
- package/src/components/SkipLinks/SkipLinks.test.tsx +22 -10
- package/src/components/SkipLinks/SkipLinks.tsx +16 -15
- package/src/components/SummaryCard/SummaryCard.test.tsx +31 -35
- package/src/components/SummaryCard/SummaryCard.tsx +39 -28
- package/src/components/SummaryList/SummaryList.test.tsx +49 -148
- package/src/components/SummaryList/SummaryList.tsx +54 -92
- package/src/components/Table/Table.tsx +2 -2
- package/src/components/Tabs/Tabs.tsx +14 -15
- package/src/components/Tag/Tag.test.tsx +4 -4
- package/src/components/Tag/Tag.tsx +4 -4
- package/src/components/TaskList/TaskList.test.tsx +26 -0
- package/src/components/TaskList/TaskList.tsx +21 -11
- package/src/components/TextInput/TextInput.test.tsx +1 -1
- package/src/components/TextInput/TextInput.tsx +5 -5
- package/src/components/Textarea/Textarea.test.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +5 -5
- package/src/components/WarningText/WarningText.tsx +2 -2
- package/src/hooks/useTracking.test.tsx +64 -0
- package/src/hooks/useTracking.ts +19 -0
- package/src/utils/context.ts +3 -0
- package/tsconfig.json +1 -1
- package/dist/common/abstract-notification-banner.jsx +0 -63
- package/dist/common/conditional-wrapper.jsx +0 -8
- package/dist/common/file-icon.jsx +0 -51
- package/dist/common/hint-text.jsx +0 -9
- package/dist/common/icon.jsx +0 -57
- package/dist/common/screen-reader-text.jsx +0 -9
- package/dist/common/wrapper-tag.jsx +0 -11
- package/dist/components/accordion/accordion.jsx +0 -102
- package/dist/components/back-to-top/back-to-top.jsx +0 -27
- package/dist/components/breadcrumbs/breadcrumbs.jsx +0 -28
- package/dist/components/button/button.jsx +0 -30
- package/dist/components/checkbox/checkbox.jsx +0 -62
- package/dist/components/confirmation-message/confirmation-message.jsx +0 -24
- package/dist/components/contents-nav/contents-nav.jsx +0 -33
- package/dist/components/cookie-banner/cookie-banner.jsx +0 -21
- package/dist/components/date-picker/date-picker.jsx +0 -54
- package/dist/components/details/details.jsx +0 -17
- package/dist/components/error-message/error-message.jsx +0 -12
- package/dist/components/error-summary/error-summary.jsx +0 -27
- package/dist/components/file-download/file-download.jsx +0 -50
- package/dist/components/hide-this-page/hide-this-page.jsx +0 -71
- package/dist/components/inset-text/inset-text.jsx +0 -14
- package/dist/components/notification-banner/notification-banner.jsx +0 -26
- package/dist/components/notification-panel/notification-panel.jsx +0 -21
- package/dist/components/page-header/page-header.jsx +0 -15
- package/dist/components/page-metadata/page-metadata.jsx +0 -26
- package/dist/components/pagination/pagination.jsx +0 -97
- package/dist/components/phase-banner/phase-banner.jsx +0 -23
- package/dist/components/question/question.jsx +0 -22
- package/dist/components/radio-button/radio-button.jsx +0 -43
- package/dist/components/select/select.jsx +0 -52
- package/dist/components/sequential-navigation/sequential-navigation.jsx +0 -31
- package/dist/components/side-navigation/side-navigation.jsx +0 -52
- package/dist/components/site-header/site-header.jsx +0 -68
- package/dist/components/site-navigation/site-navigation.jsx +0 -22
- package/dist/components/site-search/site-search.jsx +0 -55
- package/dist/components/skip-links/skip-links.jsx +0 -21
- package/dist/components/summary-card/summary-card.jsx +0 -67
- package/dist/components/summary-list/summary-list.jsx +0 -75
- package/dist/components/table/table.jsx +0 -24
- package/dist/components/tabs/tabs.jsx +0 -99
- package/dist/components/tag/tag.jsx +0 -13
- package/dist/components/task-list/task-list.jsx +0 -95
- package/dist/components/text-input/text-input.jsx +0 -58
- package/dist/components/textarea/textarea.jsx +0 -54
- package/dist/components/warning-text/warning-text.jsx +0 -16
- package/dist/icons/ArrowUpward.jsx +0 -41
- package/dist/icons/CalendarToday.jsx +0 -41
- package/dist/icons/Cancel.jsx +0 -40
- package/dist/icons/CheckCircle.jsx +0 -41
- package/dist/icons/ChevronLeft.jsx +0 -41
- package/dist/icons/ChevronRight.jsx +0 -41
- package/dist/icons/Close.jsx +0 -41
- package/dist/icons/Description.jsx +0 -41
- package/dist/icons/DoubleChevronLeft.jsx +0 -40
- package/dist/icons/DoubleChevronRight.jsx +0 -40
- package/dist/icons/Error.jsx +0 -41
- package/dist/icons/ExpandLess.jsx +0 -41
- package/dist/icons/ExpandMore.jsx +0 -41
- package/dist/icons/List.jsx +0 -44
- package/dist/icons/Menu.jsx +0 -41
- package/dist/icons/PriorityHigh.jsx +0 -42
- package/dist/icons/Search.jsx +0 -41
- package/dist/icons/index.js +0 -40
|
@@ -6,7 +6,7 @@ const TAG_TEXT = 'Beta';
|
|
|
6
6
|
|
|
7
7
|
test('tag renders correctly', () => {
|
|
8
8
|
render(
|
|
9
|
-
<Tag
|
|
9
|
+
<Tag>{TAG_TEXT}</Tag>
|
|
10
10
|
);
|
|
11
11
|
|
|
12
12
|
const tag = screen.getByText(TAG_TEXT);
|
|
@@ -17,7 +17,7 @@ test('tag renders correctly', () => {
|
|
|
17
17
|
|
|
18
18
|
test('tag with custom colour', () => {
|
|
19
19
|
render(
|
|
20
|
-
<Tag colour="red"
|
|
20
|
+
<Tag colour="red">{TAG_TEXT}</Tag>
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
const tag = screen.getByText(TAG_TEXT);
|
|
@@ -27,7 +27,7 @@ test('tag with custom colour', () => {
|
|
|
27
27
|
|
|
28
28
|
test('passing additional props', () => {
|
|
29
29
|
render(
|
|
30
|
-
<Tag data-test="foo"
|
|
30
|
+
<Tag data-test="foo">{TAG_TEXT}</Tag>
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
const tag = screen.getByText(TAG_TEXT);
|
|
@@ -36,7 +36,7 @@ test('passing additional props', () => {
|
|
|
36
36
|
|
|
37
37
|
test('tag with additional CSS class', () => {
|
|
38
38
|
render(
|
|
39
|
-
<Tag className="foo"
|
|
39
|
+
<Tag className="foo">{TAG_TEXT}</Tag>
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
const tag = screen.getByText(TAG_TEXT);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const Tag
|
|
1
|
+
const Tag = ({
|
|
2
|
+
children,
|
|
2
3
|
className,
|
|
3
4
|
colour,
|
|
4
|
-
title,
|
|
5
5
|
...props
|
|
6
|
-
}) => {
|
|
6
|
+
}: SGDS.Component.Tag) => {
|
|
7
7
|
return (
|
|
8
8
|
<span
|
|
9
9
|
className={[
|
|
@@ -13,7 +13,7 @@ const Tag: React.FC<SGDS.Component.Tag> = ({
|
|
|
13
13
|
].join(' ')}
|
|
14
14
|
{...props}
|
|
15
15
|
>
|
|
16
|
-
{
|
|
16
|
+
{children}
|
|
17
17
|
</span>
|
|
18
18
|
);
|
|
19
19
|
};
|
|
@@ -192,6 +192,32 @@ test('task with link', () => {
|
|
|
192
192
|
expect(link.textContent).toEqual(taskHeading.textContent);
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
+
test('task with custom link element', () => {
|
|
196
|
+
const TASK_HREF = '#foo';
|
|
197
|
+
|
|
198
|
+
render(
|
|
199
|
+
<TaskList.Item
|
|
200
|
+
id={TASK_ITEM.id}
|
|
201
|
+
statusText={TASK_ITEM.statusText}
|
|
202
|
+
title={TASK_ITEM.title}
|
|
203
|
+
href={TASK_HREF}
|
|
204
|
+
linkComponent={
|
|
205
|
+
({ className, ...props }) => (
|
|
206
|
+
<strong role="link" className={className} {...props}/>
|
|
207
|
+
)}
|
|
208
|
+
>
|
|
209
|
+
{TASK_SUMMARY_CONTENT}
|
|
210
|
+
</TaskList.Item>
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
const task = screen.getByRole('listitem');
|
|
214
|
+
const taskHeading = within(task).getByRole('heading');
|
|
215
|
+
const link = within(task).getByRole('link');
|
|
216
|
+
|
|
217
|
+
expect(link?.tagName).toEqual('STRONG');
|
|
218
|
+
expect(link?.textContent).toEqual(taskHeading.textContent);
|
|
219
|
+
});
|
|
220
|
+
|
|
195
221
|
test('completed task has green tag', () => {
|
|
196
222
|
render(
|
|
197
223
|
<TaskList.Item
|
|
@@ -4,21 +4,32 @@ import HintText from '../../common/HintText';
|
|
|
4
4
|
import ScreenReaderText from '../../common/ScreenReaderText';
|
|
5
5
|
import Tag from '../Tag/Tag';
|
|
6
6
|
|
|
7
|
-
const TaskItem
|
|
7
|
+
const TaskItem = ({
|
|
8
8
|
children,
|
|
9
9
|
className,
|
|
10
10
|
href,
|
|
11
11
|
id,
|
|
12
12
|
isComplete = false,
|
|
13
|
+
linkComponent,
|
|
13
14
|
statusText,
|
|
14
15
|
tagColour = 'grey',
|
|
15
16
|
title,
|
|
16
17
|
...props
|
|
17
|
-
}) => {
|
|
18
|
+
}: SGDS.Component.TaskList.Item) => {
|
|
18
19
|
if (isComplete) {
|
|
19
20
|
tagColour = 'green';
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
const LINK_CLASS = 'ds_task-list__task-link';
|
|
24
|
+
|
|
25
|
+
function getLinkElement(children: React.ReactNode) {
|
|
26
|
+
if (linkComponent) {
|
|
27
|
+
return linkComponent({ className: LINK_CLASS, href, children });
|
|
28
|
+
} else if (href) {
|
|
29
|
+
return <a href={href} className={LINK_CLASS}>{children}</a>;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
return (
|
|
23
34
|
<li
|
|
24
35
|
className={[
|
|
@@ -32,7 +43,7 @@ const TaskItem: React.FC<SGDS.Component.TaskList.Item> = ({
|
|
|
32
43
|
<h3 className="ds_task-list__task-heading">
|
|
33
44
|
<ConditionalWrapper
|
|
34
45
|
condition={typeof href !== 'undefined'}
|
|
35
|
-
wrapper={(children: React.JSX.Element) =>
|
|
46
|
+
wrapper={(children: React.JSX.Element) => getLinkElement(children)}
|
|
36
47
|
>
|
|
37
48
|
{title}
|
|
38
49
|
{statusText && <ScreenReaderText>({statusText})</ScreenReaderText>}
|
|
@@ -45,8 +56,9 @@ const TaskItem: React.FC<SGDS.Component.TaskList.Item> = ({
|
|
|
45
56
|
<Tag
|
|
46
57
|
aria-hidden="true"
|
|
47
58
|
colour={tagColour}
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
>
|
|
60
|
+
{statusText}
|
|
61
|
+
</Tag>
|
|
50
62
|
}
|
|
51
63
|
</li>
|
|
52
64
|
);
|
|
@@ -58,13 +70,13 @@ const TaskItem: React.FC<SGDS.Component.TaskList.Item> = ({
|
|
|
58
70
|
* @param {string} props.title - The title of the task group
|
|
59
71
|
* @returns {JSX.Element} - The element
|
|
60
72
|
*/
|
|
61
|
-
const TaskGroup
|
|
73
|
+
const TaskGroup = ({
|
|
62
74
|
children,
|
|
63
75
|
className,
|
|
64
76
|
intro,
|
|
65
77
|
title,
|
|
66
78
|
...props
|
|
67
|
-
}) => {
|
|
79
|
+
}: SGDS.Component.TaskList.Group) => {
|
|
68
80
|
return (
|
|
69
81
|
<li
|
|
70
82
|
className={[
|
|
@@ -82,15 +94,13 @@ const TaskGroup: React.FC<SGDS.Component.TaskList.Group> = ({
|
|
|
82
94
|
);
|
|
83
95
|
};
|
|
84
96
|
|
|
85
|
-
const TaskList
|
|
86
|
-
& { Group: React.FC<SGDS.Component.TaskList.Group> }
|
|
87
|
-
& { Item: React.FC<SGDS.Component.TaskList.Item> } = ({
|
|
97
|
+
const TaskList = ({
|
|
88
98
|
children,
|
|
89
99
|
className,
|
|
90
100
|
headingId = 'task-list',
|
|
91
101
|
title,
|
|
92
102
|
...props
|
|
93
|
-
}) => {
|
|
103
|
+
}: SGDS.Component.TaskList) => {
|
|
94
104
|
let taskCount = 0;
|
|
95
105
|
let incompleteTaskIds: string[] = [];
|
|
96
106
|
let completedTasksCount = 0;
|
|
@@ -6,7 +6,7 @@ import ConditionalWrapper from '../../common/ConditionalWrapper';
|
|
|
6
6
|
import ErrorMessage from '../ErrorMessage/ErrorMessage';
|
|
7
7
|
import HintText from '../../common/HintText';
|
|
8
8
|
|
|
9
|
-
const TextInput
|
|
9
|
+
const TextInput = ({
|
|
10
10
|
buttonIcon,
|
|
11
11
|
buttonText,
|
|
12
12
|
children,
|
|
@@ -15,9 +15,9 @@ const TextInput: React.FC<SGDS.Component.TextInput> = ({
|
|
|
15
15
|
width,
|
|
16
16
|
currency,
|
|
17
17
|
currencySymbol,
|
|
18
|
-
error,
|
|
19
18
|
errorMessage,
|
|
20
19
|
hasButton = false,
|
|
20
|
+
hasError,
|
|
21
21
|
hintText,
|
|
22
22
|
id,
|
|
23
23
|
label,
|
|
@@ -29,7 +29,7 @@ const TextInput: React.FC<SGDS.Component.TextInput> = ({
|
|
|
29
29
|
type = 'text',
|
|
30
30
|
value,
|
|
31
31
|
...props
|
|
32
|
-
}) => {
|
|
32
|
+
}: SGDS.Component.TextInput) => {
|
|
33
33
|
const errorMessageId = `error-message-${id}`;
|
|
34
34
|
const hintTextId = `hint-text-${id}`;
|
|
35
35
|
const ref = useRef(null);
|
|
@@ -71,11 +71,11 @@ const TextInput: React.FC<SGDS.Component.TextInput> = ({
|
|
|
71
71
|
>
|
|
72
72
|
<input
|
|
73
73
|
aria-describedby={describedbys.join(' ')}
|
|
74
|
-
aria-invalid={
|
|
74
|
+
aria-invalid={hasError}
|
|
75
75
|
className={[
|
|
76
76
|
'ds_input',
|
|
77
77
|
className,
|
|
78
|
-
|
|
78
|
+
hasError ? 'ds_input--error' : '',
|
|
79
79
|
width ? `ds_input--${width}` : '',
|
|
80
80
|
].join(' ')}
|
|
81
81
|
defaultValue={value}
|
|
@@ -5,11 +5,11 @@ import ConditionalWrapper from '../../common/ConditionalWrapper';
|
|
|
5
5
|
import ErrorMessage from '../ErrorMessage/ErrorMessage';
|
|
6
6
|
import HintText from '../../common/HintText';
|
|
7
7
|
|
|
8
|
-
const Textarea
|
|
8
|
+
const Textarea = ({
|
|
9
9
|
className,
|
|
10
10
|
countThreshold,
|
|
11
|
-
error,
|
|
12
11
|
errorMessage,
|
|
12
|
+
hasError,
|
|
13
13
|
hintText,
|
|
14
14
|
id,
|
|
15
15
|
label,
|
|
@@ -21,7 +21,7 @@ const Textarea: React.FC<SGDS.Component.Textarea> = ({
|
|
|
21
21
|
rows = 4,
|
|
22
22
|
value,
|
|
23
23
|
...props
|
|
24
|
-
}) => {
|
|
24
|
+
}: SGDS.Component.Textarea) => {
|
|
25
25
|
const errorMessageId = `error-message-${id}`;
|
|
26
26
|
const hintTextId = `hint-text-${id}`;
|
|
27
27
|
const ref = useRef(null);
|
|
@@ -59,10 +59,10 @@ const Textarea: React.FC<SGDS.Component.Textarea> = ({
|
|
|
59
59
|
|
|
60
60
|
<textarea
|
|
61
61
|
aria-describedby={describedbys.join(' ')}
|
|
62
|
-
aria-invalid={
|
|
62
|
+
aria-invalid={hasError}
|
|
63
63
|
className={[
|
|
64
64
|
'ds_input',
|
|
65
|
-
|
|
65
|
+
hasError && 'ds_input--error',
|
|
66
66
|
className
|
|
67
67
|
].join(' ')}
|
|
68
68
|
defaultValue={value}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { test, expect } from 'vitest';
|
|
5
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
6
|
+
|
|
7
|
+
import useTracking from './useTracking';
|
|
8
|
+
|
|
9
|
+
const Link = ({ children }) => <a href="#">{children}</a>;
|
|
10
|
+
|
|
11
|
+
const Links = () => {
|
|
12
|
+
useTracking();
|
|
13
|
+
const [links, setLinks] = useState<string[]>([]);
|
|
14
|
+
|
|
15
|
+
const addNewLink = () => {
|
|
16
|
+
setLinks((prev) => [...prev, 'Second link']);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
{links.map((link, index) => (
|
|
22
|
+
<Link key={`link-${index}`}>{link}</Link>
|
|
23
|
+
))}
|
|
24
|
+
|
|
25
|
+
<button onClick={addNewLink}>
|
|
26
|
+
Add
|
|
27
|
+
</button>
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// basic test to verify the tracking script is having an effect
|
|
33
|
+
test('text tracking on component render', async () => {
|
|
34
|
+
const SECTION_ONE_TEXT = 'Foo';
|
|
35
|
+
const SECTION_TWO_TEXT = 'Bar';
|
|
36
|
+
|
|
37
|
+
render(
|
|
38
|
+
<>
|
|
39
|
+
<h1>{SECTION_ONE_TEXT}</h1>
|
|
40
|
+
<Link>First link</Link>
|
|
41
|
+
<h1>{SECTION_TWO_TEXT}</h1>
|
|
42
|
+
<Links />
|
|
43
|
+
</>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const button = screen.getByRole('button');
|
|
47
|
+
const firstLink = screen.getByText('First link');
|
|
48
|
+
|
|
49
|
+
// todo: this will fail until the tracking script in DS core is updated to use textContent instead of innerText
|
|
50
|
+
// expect(firstLink).toHaveAttribute('data-section', SECTION_ONE_TEXT);
|
|
51
|
+
|
|
52
|
+
fireEvent(
|
|
53
|
+
button,
|
|
54
|
+
new MouseEvent('click', new MouseEvent('click', {
|
|
55
|
+
bubbles: true,
|
|
56
|
+
cancelable: true,
|
|
57
|
+
})
|
|
58
|
+
));
|
|
59
|
+
|
|
60
|
+
const secondLink = await screen.findByText('Second link')
|
|
61
|
+
|
|
62
|
+
// todo: this will fail until the tracking script in DS core is updated to use textContent instead of innerText
|
|
63
|
+
// expect(secondLink).toHaveAttribute('data-section', SECTION_TWO_TEXT);
|
|
64
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
//@ts-ignore
|
|
4
|
+
import DSTracking from '@scottish-government/design-system/src/base/tools/tracking/tracking';
|
|
5
|
+
|
|
6
|
+
export default function () {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const observer = new MutationObserver(() => {
|
|
9
|
+
DSTracking.init();
|
|
10
|
+
});
|
|
11
|
+
DSTracking.init();
|
|
12
|
+
|
|
13
|
+
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
14
|
+
|
|
15
|
+
return () => {
|
|
16
|
+
observer.disconnect();
|
|
17
|
+
}
|
|
18
|
+
}, []);
|
|
19
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const react_1 = require("react");
|
|
7
|
-
const icon_1 = __importDefault(require("./icon"));
|
|
8
|
-
const screen_reader_text_1 = __importDefault(require("./screen-reader-text"));
|
|
9
|
-
const Buttons = ({ children }) => {
|
|
10
|
-
return (<>{children}</>);
|
|
11
|
-
};
|
|
12
|
-
const AbstractNotificationBanner = ({ children, className, close, icon, iconColour, iconInverse, title = 'Information', ...props }) => {
|
|
13
|
-
let content = [];
|
|
14
|
-
let buttons;
|
|
15
|
-
react_1.Children.forEach(children, (child) => {
|
|
16
|
-
if ((0, react_1.isValidElement)(child) && child.type === Buttons) {
|
|
17
|
-
buttons = child;
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
content.push(child);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
return (<div className={[
|
|
24
|
-
'ds_notification',
|
|
25
|
-
className
|
|
26
|
-
].join(' ')} data-module="ds-notification" {...props}>
|
|
27
|
-
<div className="ds_wrapper">
|
|
28
|
-
<div className={[
|
|
29
|
-
'ds_notification__content',
|
|
30
|
-
close && 'ds_notification__content--has-close'
|
|
31
|
-
].join(' ')}>
|
|
32
|
-
<h2 className="visually-hidden">{title}</h2>
|
|
33
|
-
|
|
34
|
-
{icon &&
|
|
35
|
-
<span className={[
|
|
36
|
-
'ds_notification__icon',
|
|
37
|
-
iconInverse && 'ds_notification__icon--inverse',
|
|
38
|
-
iconColour && 'ds_notification__icon--colour'
|
|
39
|
-
].join(' ')} aria-hidden="true">
|
|
40
|
-
<icon_1.default icon={icon}/>
|
|
41
|
-
</span>}
|
|
42
|
-
|
|
43
|
-
<div className="ds_notification__text">
|
|
44
|
-
{content}
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
{close &&
|
|
48
|
-
<button type="button" className="ds_notification__close js-close-notification">
|
|
49
|
-
<screen_reader_text_1.default>Close this notification</screen_reader_text_1.default>
|
|
50
|
-
<icon_1.default fill icon="Close" aria-hidden="true"/>
|
|
51
|
-
</button>}
|
|
52
|
-
|
|
53
|
-
{buttons &&
|
|
54
|
-
<div className="ds_button-group">
|
|
55
|
-
{buttons}
|
|
56
|
-
</div>}
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</div>);
|
|
60
|
-
};
|
|
61
|
-
AbstractNotificationBanner.displayName = 'AbstractNotificationBanner';
|
|
62
|
-
AbstractNotificationBanner.Buttons = Buttons;
|
|
63
|
-
exports.default = AbstractNotificationBanner;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/**
|
|
4
|
-
* Wraps all children in a specified HTML tag if a condition is met.
|
|
5
|
-
*/
|
|
6
|
-
const ConditionalWrapper = ({ condition, wrapper, children }) => condition ? wrapper(children) : children;
|
|
7
|
-
ConditionalWrapper.displayName = 'ConditionalWrapper';
|
|
8
|
-
exports.default = ConditionalWrapper;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const react_1 = __importDefault(require("react"));
|
|
40
|
-
const FileIcons = __importStar(require("../images/documents"));
|
|
41
|
-
const FileIcon = ({ ariaLabel = '', className, icon }) => {
|
|
42
|
-
const Component = react_1.default.createElement(FileIcons[icon], {
|
|
43
|
-
className: className,
|
|
44
|
-
'aria-label': ariaLabel
|
|
45
|
-
});
|
|
46
|
-
return (<>
|
|
47
|
-
{Component}
|
|
48
|
-
</>);
|
|
49
|
-
};
|
|
50
|
-
FileIcon.displayName = 'FileIcon';
|
|
51
|
-
exports.default = FileIcon;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const HintText = ({ children, id, text, ...props }) => {
|
|
4
|
-
return (<p className="ds_hint-text" dangerouslySetInnerHTML={text ? { __html: text } : undefined} id={id} {...props}>
|
|
5
|
-
{!text ? children : null}
|
|
6
|
-
</p>);
|
|
7
|
-
};
|
|
8
|
-
HintText.displayName = 'HintText';
|
|
9
|
-
exports.default = HintText;
|
package/dist/common/icon.jsx
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const react_1 = __importDefault(require("react"));
|
|
40
|
-
const Icons = __importStar(require("../images/icons"));
|
|
41
|
-
const Icon = ({ ariaLabel, className, fill, icon, iconSize }) => {
|
|
42
|
-
const Component = react_1.default.createElement(Icons[icon], {
|
|
43
|
-
'aria-hidden': ariaLabel ? undefined : true,
|
|
44
|
-
'aria-label': ariaLabel,
|
|
45
|
-
className: [
|
|
46
|
-
'ds_icon',
|
|
47
|
-
className,
|
|
48
|
-
fill && 'ds_icon--fill',
|
|
49
|
-
iconSize && `ds_icon--${iconSize}`
|
|
50
|
-
].join(' ')
|
|
51
|
-
});
|
|
52
|
-
return (<>
|
|
53
|
-
{Component}
|
|
54
|
-
</>);
|
|
55
|
-
};
|
|
56
|
-
Icon.displayName = 'Icon';
|
|
57
|
-
exports.default = Icon;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ScreenReaderText = ({ children, ...props }) => {
|
|
4
|
-
return (<span className="visually-hidden" {...props}>
|
|
5
|
-
{children}
|
|
6
|
-
</span>);
|
|
7
|
-
};
|
|
8
|
-
ScreenReaderText.displayName = 'ScreenReaderText';
|
|
9
|
-
exports.default = ScreenReaderText;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/**
|
|
4
|
-
* Wraps all children in a specified HTML tag.
|
|
5
|
-
*/
|
|
6
|
-
const WrapperTag = ({ children, tagName = 'div', ...props }) => {
|
|
7
|
-
const TagName = tagName;
|
|
8
|
-
return <TagName {...props}>{children}</TagName>;
|
|
9
|
-
};
|
|
10
|
-
WrapperTag.displayName = 'WrapperTag';
|
|
11
|
-
exports.default = WrapperTag;
|