@scottish-government/designsystem-react 0.0.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.
Files changed (111) hide show
  1. package/.editorconfig +12 -0
  2. package/.github/workflows/release-package.yml +96 -0
  3. package/@types/common/ConditionalWrapper.d.ts +6 -0
  4. package/@types/common/HintText.d.ts +6 -0
  5. package/@types/common/Icon.d.ts +11 -0
  6. package/@types/common/ScreenReaderText.d.ts +4 -0
  7. package/@types/common/WrapperTag.d.ts +5 -0
  8. package/@types/components/Accordion.d.ts +15 -0
  9. package/@types/components/AspectBox.d.ts +5 -0
  10. package/@types/components/BackToTop.d.ts +5 -0
  11. package/@types/components/Breadcrumbs.d.ts +14 -0
  12. package/@types/components/Button.d.ts +17 -0
  13. package/@types/components/Checkbox.d.ts +13 -0
  14. package/@types/components/ConfirmationMessage.d.ts +7 -0
  15. package/@types/components/ContentsNav.d.ts +15 -0
  16. package/@types/components/DatePicker.d.ts +19 -0
  17. package/@types/components/Details.d.ts +6 -0
  18. package/@types/components/ErrorMessage.d.ts +6 -0
  19. package/@types/components/Metadata.d.ts +11 -0
  20. package/@types/components/NotificationBanner.d.ts +9 -0
  21. package/@types/components/NotificationPanel.d.ts +7 -0
  22. package/@types/components/PageHeader.d.ts +6 -0
  23. package/@types/components/PhaseBanner.d.ts +5 -0
  24. package/@types/components/Question.d.ts +11 -0
  25. package/@types/components/RadioButton.d.ts +15 -0
  26. package/@types/components/Select.d.ts +14 -0
  27. package/@types/components/SequentialNavigation.d.ts +14 -0
  28. package/@types/components/SideNavigation.d.ts +19 -0
  29. package/@types/components/SiteNavigation.d.ts +13 -0
  30. package/@types/components/SiteSearch.d.ts +14 -0
  31. package/@types/components/SkipLinks.d.ts +14 -0
  32. package/@types/components/Tag.d.ts +7 -0
  33. package/@types/components/TaskList.d.ts +21 -0
  34. package/@types/components/TextInput.d.ts +12 -0
  35. package/@types/components/Textarea.d.ts +4 -0
  36. package/@types/global.d.ts +1 -0
  37. package/@types/sgds.d.ts +35 -0
  38. package/package.json +36 -0
  39. package/src/common/conditional-wrapper.test.tsx +36 -0
  40. package/src/common/conditional-wrapper.tsx +9 -0
  41. package/src/common/hint-text.test.tsx +47 -0
  42. package/src/common/hint-text.tsx +21 -0
  43. package/src/common/icon.test.tsx +100 -0
  44. package/src/common/icon.tsx +28 -0
  45. package/src/common/screen-reader-text.test.tsx +31 -0
  46. package/src/common/screen-reader-text.tsx +17 -0
  47. package/src/common/wrapper-tag.test.tsx +42 -0
  48. package/src/common/wrapper-tag.tsx +15 -0
  49. package/src/components/accordion/accordion.test.tsx +212 -0
  50. package/src/components/accordion/accordion.tsx +108 -0
  51. package/src/components/aspect-box/aspect-box.test.tsx +81 -0
  52. package/src/components/aspect-box/aspect-box.tsx +57 -0
  53. package/src/components/back-to-top/back-to-top.test.tsx +45 -0
  54. package/src/components/back-to-top/back-to-top.tsx +33 -0
  55. package/src/components/breadcrumbs/breadcrumbs.test.tsx +77 -0
  56. package/src/components/breadcrumbs/breadcrumbs.tsx +53 -0
  57. package/src/components/button/button.test.tsx +125 -0
  58. package/src/components/button/button.tsx +48 -0
  59. package/src/components/checkbox/checkbox.test.tsx +180 -0
  60. package/src/components/checkbox/checkbox.tsx +107 -0
  61. package/src/components/confirmation-message/confirmation-message.test.tsx +46 -0
  62. package/src/components/confirmation-message/confirmation-message.tsx +32 -0
  63. package/src/components/contents-nav/contents-nav.test.tsx +136 -0
  64. package/src/components/contents-nav/contents-nav.tsx +54 -0
  65. package/src/components/date-picker/date-picker.test.tsx +209 -0
  66. package/src/components/date-picker/date-picker.tsx +129 -0
  67. package/src/components/details/details.test.tsx +38 -0
  68. package/src/components/details/details.tsx +25 -0
  69. package/src/components/error-message/error-message.test.tsx +40 -0
  70. package/src/components/error-message/error-message.tsx +23 -0
  71. package/src/components/inset-text/inset-text.test.tsx +33 -0
  72. package/src/components/inset-text/inset-text.tsx +19 -0
  73. package/src/components/notification-banner/notification-banner.test.tsx +93 -0
  74. package/src/components/notification-banner/notification-banner.tsx +70 -0
  75. package/src/components/notification-panel/notification-panel.test.tsx +77 -0
  76. package/src/components/notification-panel/notification-panel.tsx +31 -0
  77. package/src/components/page-header/page-header.test.tsx +48 -0
  78. package/src/components/page-header/page-header.tsx +22 -0
  79. package/src/components/page-metadata/page-metadata.test.tsx +56 -0
  80. package/src/components/page-metadata/page-metadata.tsx +39 -0
  81. package/src/components/phase-banner/phase-banner.test.tsx +67 -0
  82. package/src/components/phase-banner/phase-banner.tsx +27 -0
  83. package/src/components/question/question.test.tsx +69 -0
  84. package/src/components/question/question.tsx +33 -0
  85. package/src/components/radio-button/radio-button.test.tsx +190 -0
  86. package/src/components/radio-button/radio-button.tsx +88 -0
  87. package/src/components/select/select.test.tsx +208 -0
  88. package/src/components/select/select.tsx +86 -0
  89. package/src/components/sequential-navigation/sequential-navigation.test.tsx +67 -0
  90. package/src/components/sequential-navigation/sequential-navigation.tsx +55 -0
  91. package/src/components/side-navigation/side-navigation.test.tsx +156 -0
  92. package/src/components/side-navigation/side-navigation.tsx +85 -0
  93. package/src/components/site-navigation/site-navigation.test.tsx +63 -0
  94. package/src/components/site-navigation/site-navigation.tsx +40 -0
  95. package/src/components/site-search/site-search.test.tsx +153 -0
  96. package/src/components/site-search/site-search.tsx +97 -0
  97. package/src/components/skip-links/skip-links.test.tsx +84 -0
  98. package/src/components/skip-links/skip-links.tsx +39 -0
  99. package/src/components/tag/tag.test.tsx +45 -0
  100. package/src/components/tag/tag.tsx +23 -0
  101. package/src/components/task-list/task-list.test.tsx +409 -0
  102. package/src/components/task-list/task-list.tsx +132 -0
  103. package/src/components/text-input/text-input.test.tsx +307 -0
  104. package/src/components/text-input/text-input.tsx +98 -0
  105. package/src/components/textarea/textarea.test.tsx +212 -0
  106. package/src/components/textarea/textarea.tsx +82 -0
  107. package/src/components/warning-text/warning-text.test.tsx +40 -0
  108. package/src/components/warning-text/warning-text.tsx +21 -0
  109. package/tsconfig.json +45 -0
  110. package/vite.config.ts +12 -0
  111. package/vitest-setup.ts +13 -0
package/.editorconfig ADDED
@@ -0,0 +1,12 @@
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+ root = true
5
+
6
+ [*]
7
+ indent_size = 4
8
+ indent_style = space
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
@@ -0,0 +1,96 @@
1
+ name: Versioned release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ release_type:
7
+ description: 'Release type'
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - patch
12
+ - minor
13
+ - major
14
+ - prepatch
15
+ - preminor
16
+ - premajor
17
+ - prerelease
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v4
26
+
27
+ # Set up node and add the registry url
28
+ - name: Setup Node.js
29
+ uses: actions/setup-node@v3
30
+ with:
31
+ node-version: 18
32
+ registry-url: 'https://registry.npmjs.org'
33
+ always-auth: true
34
+
35
+ # Install
36
+ - name: Install
37
+ run: npm ci
38
+
39
+ # Test
40
+ - name: Run tests
41
+ run: npm run test
42
+
43
+ # Configure Git
44
+ - name: Git configuration
45
+ run: |
46
+ git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
47
+ git config --global user.name "GitHub Actions"
48
+
49
+ # Set package version
50
+ - name: Set package version
51
+ if: startsWith(github.event.inputs.release_type, 'pre') != true
52
+ run: |
53
+ echo "NEW_VERSION=$(npm --no-git-tag-version version $RELEASE_TYPE)" >> $GITHUB_ENV
54
+ echo "RELEASE_TAG=latest" >> $GITHUB_ENV
55
+ env:
56
+ RELEASE_TYPE: ${{github.event.inputs.release_type}}
57
+
58
+ # Set pre-release version
59
+ - name: Set pre-release version
60
+ if: startsWith(github.event.inputs.release_type, 'pre')
61
+ run: |
62
+ echo "NEW_VERSION=$(npm --no-git-tag-version --preid=beta version $RELEASE_TYPE)" >> $GITHUB_ENV
63
+ echo "RELEASE_TAG=beta" >> $GITHUB_ENV
64
+ env:
65
+ RELEASE_TYPE: ${{github.event.inputs.release_type}}
66
+
67
+ # Build release assets
68
+ - name: Build release assets
69
+ run: |
70
+ npm run build
71
+
72
+ ## Add release assets
73
+ - name: Add release assets to commit
74
+ run: |
75
+ git add -f "dist/**/*"
76
+
77
+ # Commit updated package.json
78
+ - name: Commit package.json and create tag
79
+ run: |
80
+ git add "package.json"
81
+ git add "package-lock.json"
82
+ git commit -m "chore: release ${{env.NEW_VERSION}}"
83
+ git tag ${{env.NEW_VERSION}}
84
+
85
+ # Push to git repo
86
+ - name: Push changes to git
87
+ env:
88
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
89
+ run: |
90
+ git push origin && git push --tags
91
+
92
+ # Publish to npm
93
+ - name: Publish npm package
94
+ run: npm publish --access public
95
+ env:
96
+ NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
@@ -0,0 +1,6 @@
1
+ declare namespace SGDS.Common {
2
+ interface ConditionalWrapper extends React.AllHTMLAttributes<HTMLElement> {
3
+ condition: boolean,
4
+ wrapper: any
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ declare namespace SGDS.Common {
2
+ interface HintText extends React.AllHTMLAttributes<HTMLElement> {
3
+ id?: string,
4
+ text?: string
5
+ }
6
+ }
@@ -0,0 +1,11 @@
1
+ declare namespace SGDS.Common {
2
+ interface Icon extends React.AllHTMLAttributes<SVGSVGElement> {
3
+ accessible?: boolean,
4
+ className?: string,
5
+ fill?: boolean,
6
+ icon: string
7
+ iconPath?: string,
8
+ iconSize?: string,
9
+ title?: string
10
+ }
11
+ }
@@ -0,0 +1,4 @@
1
+ declare namespace SGDS.Common {
2
+ interface ScreenReaderText extends React.AllHTMLAttributes<HTMLElement> {
3
+ }
4
+ }
@@ -0,0 +1,5 @@
1
+ declare namespace SGDS.Common {
2
+ interface WrapperTag extends React.AllHTMLAttributes<HTMLElement> {
3
+ tagName?: string
4
+ }
5
+ }
@@ -0,0 +1,15 @@
1
+ declare namespace SGDS.Component {
2
+ namespace Accordion {
3
+ interface Item extends React.AllHTMLAttributes<HTMLElement> {
4
+ headerLevel?: SGDS.HeaderLevel,
5
+ id: string,
6
+ open?: boolean,
7
+ title: string
8
+ }
9
+ }
10
+
11
+ interface Accordion extends React.AllHTMLAttributes<HTMLElement> {
12
+ headerLevel?: SGDS.HeaderLevel,
13
+ hideOpenAll?: boolean
14
+ }
15
+ }
@@ -0,0 +1,5 @@
1
+ declare namespace SGDS.Component {
2
+ interface AspectBox extends React.AllHTMLAttributes<HTMLElement> {
3
+ ratio?: 'square' | '1:1' | '4:3' | '16:9' | '21:9';
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ declare namespace SGDS.Component {
2
+ interface BackToTop extends React.AllHTMLAttributes<HTMLElement> {
3
+ href?: string;
4
+ }
5
+ }
@@ -0,0 +1,14 @@
1
+ declare namespace SGDS.Component {
2
+ namespace Breadcrumbs {
3
+ interface Item extends React.AllHTMLAttributes<HTMLElement> {
4
+ hidden?: boolean,
5
+ href?: string,
6
+ title: string
7
+ }
8
+ }
9
+
10
+ interface Breadcrumbs extends React.AllHTMLAttributes<HTMLElement> {
11
+ hideLastItem?: boolean,
12
+ items: Breadcrumbs.Item[]
13
+ }
14
+ }
@@ -0,0 +1,17 @@
1
+ declare namespace SGDS.Component {
2
+ type ButtonStyle = 'primary' | 'secondary';
3
+ type ButtonType = 'submit' | 'reset' | 'button';
4
+ type ButtonWidth = 'fluid' | 'fixed' | 'max';
5
+
6
+ interface Button extends React.AllHTMLAttributes<HTMLButtonElement> {
7
+ icon?: string,
8
+ iconLeft?: boolean
9
+ iconOnly?: boolean,
10
+ href?: string,
11
+ small?: boolean,
12
+ buttonStyle?: ButtonStyle,
13
+ styleAsLink?: boolean,
14
+ type?: ButtonType
15
+ width?: ButtonWidth
16
+ }
17
+ }
@@ -0,0 +1,13 @@
1
+ declare namespace SGDS.Component {
2
+ namespace Checkbox {
3
+ interface Group extends React.AllHTMLAttributes<HTMLElement> {
4
+ items: Checkbox[],
5
+ small?: boolean
6
+ }
7
+ }
8
+
9
+ interface Checkbox extends CheckboxRadioBase<HTMLInputElement> {
10
+ exclusive?: boolean
11
+ id: string
12
+ }
13
+ }
@@ -0,0 +1,7 @@
1
+ declare namespace SGDS.Component {
2
+ interface ConfirmationMessage extends React.AllHTMLAttributes<HTMLElement> {
3
+ ariaLive: AriaLive,
4
+ headerLevel: HeaderLevel,
5
+ title: string
6
+ }
7
+ }
@@ -0,0 +1,15 @@
1
+ declare namespace SGDS.Component {
2
+ namespace ContentsNav {
3
+ interface Link extends React.AllHTMLAttributes<HTMLElement> {
4
+ title: string,
5
+ current: boolean,
6
+ href: string
7
+ }
8
+ }
9
+
10
+ interface ContentsNav extends React.AllHTMLAttributes<HTMLElement> {
11
+ items: ContentsNav.Link[],
12
+ label: string,
13
+ title: string
14
+ }
15
+ }
@@ -0,0 +1,19 @@
1
+ declare namespace SGDS.Component {
2
+ interface DatePicker extends React.AllHTMLAttributes<HTMLElement> {
3
+ disabledDates?: string,
4
+ error?: boolean,
5
+ errorMessage?: string,
6
+ id: string,
7
+ hintText?: string,
8
+ iconPath?: string,
9
+ label: string,
10
+ maxDate?: string,
11
+ minDate?: string,
12
+ multiple?: boolean,
13
+ name?: string,
14
+ onBlur?: React.EventHandler<any>,
15
+ onChange?: React.EventHandler<any>,
16
+ value?: string,
17
+ width?: SGDS.InputWidth
18
+ }
19
+ }
@@ -0,0 +1,6 @@
1
+ declare namespace SGDS.Component {
2
+ interface Details extends React.AllHTMLAttributes<HTMLDetailsElement> {
3
+ title?: string,
4
+ summary: string
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ declare namespace SGDS.Component {
2
+ interface ErrorMessage extends React.AllHTMLAttributes<HTMLElement> {
3
+ id?: string,
4
+ text: string | undefined
5
+ }
6
+ }
@@ -0,0 +1,11 @@
1
+ declare namespace SGDS.Component {
2
+ namespace Metadata {
3
+ interface Item extends React.AllHTMLAttributes<HTMLElement> {
4
+ name: string
5
+ }
6
+ }
7
+
8
+ interface Metadata extends React.AllHTMLAttributes<HTMLDListElement> {
9
+ inline?: boolean
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ declare namespace SGDS.Component {
2
+ interface NotificationBanner extends React.AllHTMLAttributes<HTMLDivElement> {
3
+ close?: boolean,
4
+ icon?: boolean,
5
+ iconColour?: boolean,
6
+ iconInverse?: boolean,
7
+ title: string
8
+ }
9
+ }
@@ -0,0 +1,7 @@
1
+ declare namespace SGDS.Component {
2
+ interface NotificationPanel extends React.AllHTMLAttributes<HTMLDivElement> {
3
+ ariaLive?: AriaLive,
4
+ headerLevel?: HeaderLevel,
5
+ title: string
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ declare namespace SGDS.Component {
2
+ interface PageHeader extends React.AllHTMLAttributes<HTMLHeadingElement> {
3
+ label?: string,
4
+ title: string
5
+ }
6
+ }
@@ -0,0 +1,5 @@
1
+ declare namespace SGDS.Component {
2
+ interface PhaseBanner extends React.AllHTMLAttributes<HTMLDivElement> {
3
+ phaseName: string
4
+ }
5
+ }
@@ -0,0 +1,11 @@
1
+ declare namespace SGDS.Component {
2
+ type QuestionTags = 'div' | 'fieldset';
3
+
4
+ interface Question extends React.AllHTMLAttributes<HTMLElement> {
5
+ error?: boolean,
6
+ errorMessage?: string,
7
+ hintText?: string,
8
+ legend?: string,
9
+ tagName: QuestionTags
10
+ }
11
+ }
@@ -0,0 +1,15 @@
1
+ declare namespace SGDS.Component {
2
+ namespace RadioButton {
3
+ interface Group extends React.AllHTMLAttributes<HTMLElement> {
4
+ inline?: boolean,
5
+ items: RadioButton[],
6
+ name: string,
7
+ small?: boolean
8
+ }
9
+ }
10
+
11
+ interface RadioButton extends CheckboxRadioBase<HTMLInputElement> {
12
+ id: string,
13
+ name: string
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ declare namespace SGDS.Component {
2
+ namespace Select {
3
+ interface Option extends React.AllHTMLAttributes<HTMLOptionElement> {
4
+ text: string
5
+ }
6
+ }
7
+
8
+ interface Select extends FormFieldBase<HTMLDivElement> {
9
+ defaultValue?: string,
10
+ options: Select.Option[],
11
+ placeholder?: string,
12
+ width?: InputWidth
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ declare namespace SGDS.Component {
2
+ namespace SequentialNavigation {
3
+ interface Link extends React.AllHTMLAttributes<HTMLDivElement> {
4
+ href: string,
5
+ title: string
6
+ }
7
+ }
8
+
9
+ interface SequentialNavigation extends React.AllHTMLAttributes<HTMLElement> {
10
+ ariaLabel?: string,
11
+ next?: SequentialNavigation.Link,
12
+ previous?: SequentialNavigation.Link
13
+ }
14
+ }
@@ -0,0 +1,19 @@
1
+ declare namespace SGDS.Component {
2
+ namespace SideNavigation {
3
+ interface List extends React.AllHTMLAttributes<HTMLUListElement> {
4
+ items?: SideNavigation.Link[],
5
+ root?: boolean
6
+ }
7
+
8
+ interface Link extends React.AllHTMLAttributes<HTMLLIElement> {
9
+ current?: boolean,
10
+ href: string,
11
+ items?: SideNavigation.Link[]
12
+ title: string,
13
+ }
14
+ }
15
+
16
+ interface SideNavigation extends React.AllHTMLAttributes<HTMLElement> {
17
+ items: SideNavigation.Link[]
18
+ }
19
+ }
@@ -0,0 +1,13 @@
1
+ declare namespace SGDS.Component {
2
+ namespace SiteNavigation {
3
+ interface Link extends React.AllHTMLAttributes<HTMLLIElement> {
4
+ current?: boolean,
5
+ href: string,
6
+ title: string
7
+ }
8
+ }
9
+
10
+ interface SiteNavigation extends React.AllHTMLAttributes<HTMLElement> {
11
+ items: SiteNavigation.Link[]
12
+ }
13
+ }
@@ -0,0 +1,14 @@
1
+ declare namespace SGDS.Component {
2
+ type FormMethods = 'GET' | 'POST';
3
+
4
+ interface SiteSearch extends React.AllHTMLAttributes<HTMLInputElement> {
5
+ action?: string,
6
+ autocompleteEndpoint?: string,
7
+ autocompleteSuggestionMappingFunction?: Function,
8
+ id: string,
9
+ method?: FormMethods,
10
+ minLength?: number,
11
+ name?: string,
12
+ placeholder?: string
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ declare namespace SGDS.Component {
2
+ namespace SkipLinks {
3
+ interface Link extends React.AllHTMLAttributes<HTMLLIElement> {
4
+ targetId: string,
5
+ title: string
6
+ }
7
+ }
8
+
9
+ interface SkipLinks extends React.AllHTMLAttributes<HTMLDivElement> {
10
+ items?: SkipLinks.Link[],
11
+ mainContentId?: string,
12
+ mainLinkText?: string
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ declare namespace SGDS.Component {
2
+ interface Tag extends React.AllHTMLAttributes<HTMLElement> {
3
+ className?: string,
4
+ colour?: TagColour,
5
+ title: string
6
+ }
7
+ }
@@ -0,0 +1,21 @@
1
+ declare namespace SGDS.Component {
2
+ namespace TaskList {
3
+ interface Group extends React.AllHTMLAttributes<HTMLElement> {
4
+ intro?: string,
5
+ title: string
6
+ }
7
+
8
+ interface Task extends React.AllHTMLAttributes<HTMLElement> {
9
+ href?: string,
10
+ id?: string,
11
+ isComplete?: boolean,
12
+ statusText?: string,
13
+ tagColour?: TagColour,
14
+ title: string
15
+ }
16
+ }
17
+
18
+ interface TaskList extends React.AllHTMLAttributes<HTMLElement> {
19
+ headingId?: string
20
+ }
21
+ }
@@ -0,0 +1,12 @@
1
+ declare namespace SGDS.Component {
2
+ interface TextInput extends TextInputBase<HTMLInputElement> {
3
+ buttonIcon?: string,
4
+ buttonText?: string,
5
+ className?: string,
6
+ currency?: boolean,
7
+ currencySymbol?: string,
8
+ hasButton?: boolean,
9
+ type?: string,
10
+ width?: InputWidth
11
+ }
12
+ }
@@ -0,0 +1,4 @@
1
+ declare namespace SGDS.Component {
2
+ interface Textarea extends TextInputBase<HTMLTextAreaElement> {
3
+ }
4
+ }
@@ -0,0 +1 @@
1
+ import React from 'react'
@@ -0,0 +1,35 @@
1
+ declare namespace SGDS {
2
+ type AriaLive = 'polite' | 'assertive';
3
+ type HeaderLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
4
+ type InputWidth = 'fixed-20' | 'fixed-10' | 'fixed-5' | 'fixed-4' | 'fixed-3' | 'fixed-2' | 'fluid-three-quarters' | 'fluid-two-thirds' | 'fluid-half' | 'fluid-one-third' | 'fluid-one-quarter';
5
+ type TagColour = 'grey' | 'green' | 'teal' | 'blue' | 'purple' | 'pink' | 'red' | 'orange' | 'yellow';
6
+
7
+ interface CheckboxRadioBase<T> extends React.AllHTMLAttributes<T> {
8
+ checked?: boolean,
9
+ hintText?: string,
10
+ id?: string,
11
+ label: string,
12
+ name?: string,
13
+ onBlur?: React.EventHandler<any>,
14
+ onChange?: React.EventHandler<any>,
15
+ small?: boolean
16
+ }
17
+
18
+ interface FormFieldBase<T> extends React.AllHTMLAttributes <T> {
19
+ error?: boolean,
20
+ errorMessage?: string,
21
+ id: string,
22
+ hintText?: string,
23
+ label: string,
24
+ name?: string,
25
+ onBlur?: React.EventHandler<any>,
26
+ onChange?: React.EventHandler<any>
27
+ }
28
+
29
+ interface TextInputBase<T> extends FormFieldBase<T> {
30
+ countThreshold?: number,
31
+ maxlength?: number,
32
+ placeholder?: string,
33
+ value?: string
34
+ }
35
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@scottish-government/designsystem-react",
3
+ "description": "A React/JSX implementation of the Scottish Government Design System",
4
+ "version": "0.0.0",
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "Scottish Government Digital Design System team",
8
+ "email": "designsystem@gov.scot",
9
+ "url": "https://designsystem.gov.scot"
10
+ },
11
+ "scripts": {
12
+ "build": "npm run tsc",
13
+ "coverage": "vitest run --coverage",
14
+ "test": "vitest",
15
+ "tsc": "node ./node_modules/typescript/bin/tsc"
16
+ },
17
+ "dependencies": {
18
+ "@scottish-government/design-system": "^3.0.1"
19
+ },
20
+ "devDependencies": {
21
+ "@testing-library/dom": "^10.4.0",
22
+ "@testing-library/jest-dom": "^6.6.3",
23
+ "@testing-library/react": "^16.3.0",
24
+ "@testing-library/user-event": "^14.6.1",
25
+ "@types/node": "22.15.19",
26
+ "@types/react": "^19.1.6",
27
+ "@types/react-dom": "^19.1.5",
28
+ "@vitejs/plugin-react-swc": "^3.10.0",
29
+ "@vitest/coverage-v8": "^3.2.0",
30
+ "jsdom": "^26.1.0",
31
+ "react": "^19.1.0",
32
+ "react-dom": "^19.1.0",
33
+ "typescript": "^5.8.3",
34
+ "vitest": "^3.2.0"
35
+ }
36
+ }
@@ -0,0 +1,36 @@
1
+ import { test, expect } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import ConditionalWrapper from './conditional-wrapper';
4
+
5
+ test('conditional wrapper true', () => {
6
+ render(
7
+ <ConditionalWrapper
8
+ condition={true}
9
+ wrapper={(children: React.JSX.Element) => <a data-testid="wrapper">{children}</a>}
10
+ >
11
+ <span data-testid="testContent">Bar</span>
12
+ </ConditionalWrapper>
13
+ );
14
+
15
+ const element = screen.getByTestId('testContent');
16
+ const elementParent = screen.getByTestId('wrapper');
17
+ expect(element).toBeInTheDocument();
18
+ expect(elementParent).toBeInTheDocument();
19
+ expect(element.parentNode).toEqual(elementParent)
20
+ });
21
+
22
+ test('conditional wrapper false', () => {
23
+ render(
24
+ <ConditionalWrapper
25
+ condition={false}
26
+ wrapper={(children: React.JSX.Element) => <a href="foo">{children}</a>}
27
+ >
28
+ <span data-testid="testContent">Bar</span>
29
+ </ConditionalWrapper>
30
+ );
31
+
32
+ const element = screen.getByTestId('testContent');
33
+ const elementParent = screen.queryByTestId('wrapper');
34
+ expect(element).toBeInTheDocument();
35
+ expect(elementParent).not.toBeInTheDocument();
36
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Wraps all children in a specified HTML tag if a condition is met.
3
+ */
4
+ const ConditionalWrapper: React.FC<SGDS.Common.ConditionalWrapper> = ({ condition, wrapper, children }) =>
5
+ condition ? wrapper(children) : children;
6
+
7
+ ConditionalWrapper.displayName = 'ConditionalWrapper';
8
+
9
+ export default ConditionalWrapper;