@oslokommune/punkt-react 16.26.5 → 17.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/dist/components/accordion/Accordion.d.ts +1 -0
- package/dist/components/alert/Alert.d.ts +9 -0
- package/dist/components/button/Button.d.ts +1 -1
- package/dist/components/combobox/types.d.ts +2 -0
- package/dist/components/datepicker/types.d.ts +3 -0
- package/dist/components/footer/Footer.accessibility.test.d.ts +0 -0
- package/dist/components/footer/Footer.d.ts +12 -34
- package/dist/components/footer/Footer.test.d.ts +1 -0
- package/dist/components/footer/FooterGlobal.d.ts +23 -0
- package/dist/components/footerSimple/FooterSimple.d.ts +19 -16
- package/dist/components/footerSimple/FooterSimple.test.d.ts +1 -0
- package/dist/components/header/Header.d.ts +15 -3
- package/dist/components/header/HeaderGlobal.accessibility.test.d.ts +0 -0
- package/dist/components/header/HeaderGlobal.d.ts +2 -0
- package/dist/components/header/HeaderGlobal.test.d.ts +0 -0
- package/dist/components/header/HeaderService.accessibility.test.d.ts +0 -0
- package/dist/components/header/types.d.ts +30 -2
- package/dist/components/header-menu/HeaderMenu.d.ts +2 -4
- package/dist/components/index.d.ts +4 -0
- package/dist/components/inputwrapper/InputWrapper.d.ts +1 -0
- package/dist/components/searchinput/SearchInput.d.ts +1 -0
- package/dist/components/select/Select.d.ts +4 -7
- package/dist/components/textarea/Textarea.d.ts +2 -0
- package/dist/components/textinput/Textinput.d.ts +1 -0
- package/dist/components/timepicker/types.d.ts +3 -0
- package/dist/components/timepicker/useTimepickerState.d.ts +2 -0
- package/dist/punkt-react.cjs +1 -1
- package/dist/punkt-react.js +3188 -2729
- package/dist/shared-types/footer.d.ts +95 -0
- package/dist/shared-types/{header-menu.d.ts → header-footer.d.ts} +51 -4
- package/dist/shared-types/header.d.ts +1 -1
- package/dist/shared-types/index.d.ts +6 -4
- package/dist/shared-types/searchinput.d.ts +2 -0
- package/dist/shared-types/select.d.ts +3 -2
- package/dist/shared-types/size.d.ts +4 -0
- package/dist/shared-types/timepicker.d.ts +0 -6
- package/dist/shared-utils/datepicker-utils.d.ts +5 -4
- package/dist/shared-utils/fileupload/focus-trap.d.ts +4 -10
- package/dist/shared-utils/focus-trap/index.d.ts +22 -0
- package/dist/shared-utils/{header-menu → header-footer}/example-data.d.ts +5 -4
- package/dist/shared-utils/header-footer/external-domain.d.ts +26 -0
- package/dist/shared-utils/{header-menu → header-footer}/fetch-header-footer-data.d.ts +6 -2
- package/dist/shared-utils/{header-menu → header-footer}/index.d.ts +2 -1
- package/dist/shared-utils/{header-menu → header-footer}/select-megamenu.d.ts +1 -1
- package/dist/shared-utils/scroll-lock/index.d.ts +24 -0
- package/package.json +4 -4
- package/src/components/accordion/Accordion.test.tsx +51 -0
- package/src/components/accordion/Accordion.tsx +3 -3
- package/src/components/accordion/AccordionItem.tsx +7 -14
- package/src/components/alert/Alert.test.tsx +45 -9
- package/src/components/alert/Alert.tsx +13 -3
- package/src/components/button/Button.tsx +2 -2
- package/src/components/combobox/Combobox.core.test.tsx +14 -0
- package/src/components/combobox/Combobox.tsx +1 -0
- package/src/components/combobox/ComboboxInput.tsx +2 -0
- package/src/components/combobox/types.ts +2 -0
- package/src/components/combobox/useComboboxState.ts +2 -0
- package/src/components/consent/Consent.test.tsx +8 -14
- package/src/components/consent/Consent.tsx +9 -19
- package/src/components/datepicker/Datepicker.core.test.tsx +11 -0
- package/src/components/datepicker/Datepicker.tsx +4 -1
- package/src/components/datepicker/DatepickerInputs.tsx +16 -1
- package/src/components/datepicker/types.ts +3 -0
- package/src/components/datepicker/useDatepickerState.ts +17 -9
- package/src/components/footer/Footer.accessibility.test.tsx +46 -0
- package/src/components/footer/Footer.test.tsx +192 -86
- package/src/components/footer/Footer.tsx +169 -159
- package/src/components/footer/FooterGlobal.tsx +181 -0
- package/src/components/footerSimple/FooterSimple.test.tsx +49 -46
- package/src/components/footerSimple/FooterSimple.tsx +117 -78
- package/src/components/header/Header.tsx +17 -4
- package/src/components/header/HeaderGlobal.accessibility.test.tsx +86 -0
- package/src/components/header/HeaderGlobal.test.tsx +254 -0
- package/src/components/header/HeaderGlobal.tsx +467 -0
- package/src/components/header/HeaderService.accessibility.test.tsx +70 -0
- package/src/components/header/HeaderService.test.tsx +29 -16
- package/src/components/header/HeaderService.tsx +24 -84
- package/src/components/header/types.ts +35 -0
- package/src/components/header-menu/HeaderMenu.test.tsx +16 -39
- package/src/components/header-menu/HeaderMenu.tsx +62 -70
- package/src/components/index.ts +4 -0
- package/src/components/inputwrapper/InputWrapper.tsx +6 -1
- package/src/components/modal/Modal.tsx +7 -11
- package/src/components/searchinput/SearchInput.test.tsx +10 -0
- package/src/components/searchinput/SearchInput.tsx +19 -7
- package/src/components/select/Select.test.tsx +18 -0
- package/src/components/select/Select.tsx +8 -4
- package/src/components/textarea/Textarea.test.tsx +10 -0
- package/src/components/textarea/Textarea.tsx +5 -1
- package/src/components/textinput/Textinput.test.tsx +28 -0
- package/src/components/textinput/Textinput.tsx +5 -2
- package/src/components/timepicker/Timepicker.test.tsx +10 -0
- package/src/components/timepicker/Timepicker.tsx +8 -7
- package/src/components/timepicker/types.ts +8 -5
- package/src/components/timepicker/useTimepickerState.ts +4 -0
- package/dist/shared-utils/modal-scroll-lock.d.ts +0 -10
- /package/dist/shared-utils/{header-menu → header-footer}/icon-map.d.ts +0 -0
|
@@ -31,6 +31,7 @@ export interface IPktInputWrapper extends RefAttributes<HTMLElement> {
|
|
|
31
31
|
hasFieldset?: boolean
|
|
32
32
|
role?: string
|
|
33
33
|
counterPosition?: 'top' | 'bottom'
|
|
34
|
+
size?: 'small' | 'medium' | 'xsmall'
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export const PktInputWrapper = forwardRef(
|
|
@@ -60,6 +61,7 @@ export const PktInputWrapper = forwardRef(
|
|
|
60
61
|
hasFieldset = false,
|
|
61
62
|
role = 'group',
|
|
62
63
|
counterPosition = 'bottom',
|
|
64
|
+
size = 'medium',
|
|
63
65
|
}: IPktInputWrapper,
|
|
64
66
|
ref: ForwardedRef<HTMLDivElement>,
|
|
65
67
|
) => {
|
|
@@ -76,6 +78,7 @@ export const PktInputWrapper = forwardRef(
|
|
|
76
78
|
hasError ? 'pkt-inputwrapper--error' : '',
|
|
77
79
|
disabled ? 'pkt-inputwrapper--disabled' : '',
|
|
78
80
|
inline ? 'pkt-inputwrapper--inline' : '',
|
|
81
|
+
size ? `pkt-inputwrapper--${size}` : '',
|
|
79
82
|
]
|
|
80
83
|
.filter(Boolean)
|
|
81
84
|
.join(' ')
|
|
@@ -143,6 +146,8 @@ export const PktInputWrapper = forwardRef(
|
|
|
143
146
|
)
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
const errorAlertSize = size === 'medium' ? 'small' : 'xsmall'
|
|
150
|
+
|
|
146
151
|
const content = (
|
|
147
152
|
<>
|
|
148
153
|
{renderLabel()}
|
|
@@ -152,7 +157,7 @@ export const PktInputWrapper = forwardRef(
|
|
|
152
157
|
{counterBottom && <Counter />}
|
|
153
158
|
{hasError && errorMessage && (
|
|
154
159
|
<div className="pkt-inputwrapper__alert-wrapper">
|
|
155
|
-
<PktAlert skin="error" aria-live="assertive" role="alert" id={`${forId}-error`}
|
|
160
|
+
<PktAlert skin="error" size={errorAlertSize} aria-live="assertive" role="alert" id={`${forId}-error`}>
|
|
156
161
|
{errorMessage}
|
|
157
162
|
</PktAlert>
|
|
158
163
|
</div>
|
|
@@ -13,11 +13,7 @@ import {
|
|
|
13
13
|
useRef,
|
|
14
14
|
} from 'react'
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
acquireModalScrollLock,
|
|
18
|
-
createModalScrollLockToken,
|
|
19
|
-
releaseModalScrollLock,
|
|
20
|
-
} from 'shared-utils/modal-scroll-lock'
|
|
16
|
+
import { createScrollLockToken, setScrollLock } from 'shared-utils/scroll-lock'
|
|
21
17
|
|
|
22
18
|
import { PktButton } from '../button/Button'
|
|
23
19
|
|
|
@@ -59,7 +55,7 @@ export const PktModal = forwardRef(
|
|
|
59
55
|
ref: ForwardedRef<HTMLDialogElement>,
|
|
60
56
|
) => {
|
|
61
57
|
const internalRef = useRef<HTMLDialogElement | null>(null)
|
|
62
|
-
const scrollLockToken = useRef(
|
|
58
|
+
const scrollLockToken = useRef(createScrollLockToken())
|
|
63
59
|
|
|
64
60
|
// Merge consumer ref + internal ref so we always have a working DOM handle
|
|
65
61
|
// for our own logic, regardless of whether the consumer passes a callback ref
|
|
@@ -76,7 +72,7 @@ export const PktModal = forwardRef(
|
|
|
76
72
|
const close = useCallback(() => {
|
|
77
73
|
if (!internalRef.current?.open) return
|
|
78
74
|
internalRef.current.close()
|
|
79
|
-
|
|
75
|
+
setScrollLock(scrollLockToken.current, false)
|
|
80
76
|
onClose?.()
|
|
81
77
|
}, [onClose])
|
|
82
78
|
|
|
@@ -86,12 +82,12 @@ export const PktModal = forwardRef(
|
|
|
86
82
|
if (!internalRef.current?.open) {
|
|
87
83
|
internalRef.current?.showModal()
|
|
88
84
|
}
|
|
89
|
-
|
|
85
|
+
setScrollLock(scrollLockToken.current, true)
|
|
90
86
|
} else {
|
|
91
87
|
if (internalRef.current?.open) {
|
|
92
88
|
internalRef.current.close()
|
|
93
89
|
}
|
|
94
|
-
|
|
90
|
+
setScrollLock(scrollLockToken.current, false)
|
|
95
91
|
}
|
|
96
92
|
}, [open])
|
|
97
93
|
|
|
@@ -99,7 +95,7 @@ export const PktModal = forwardRef(
|
|
|
99
95
|
useEffect(() => {
|
|
100
96
|
const token = scrollLockToken.current
|
|
101
97
|
return () => {
|
|
102
|
-
|
|
98
|
+
setScrollLock(token, false)
|
|
103
99
|
}
|
|
104
100
|
}, [])
|
|
105
101
|
|
|
@@ -113,7 +109,7 @@ export const PktModal = forwardRef(
|
|
|
113
109
|
)
|
|
114
110
|
|
|
115
111
|
const handleNativeClose = useCallback(() => {
|
|
116
|
-
|
|
112
|
+
setScrollLock(scrollLockToken.current, false)
|
|
117
113
|
onClose?.()
|
|
118
114
|
}, [onClose])
|
|
119
115
|
|
|
@@ -91,6 +91,16 @@ describe('PktSearchInput', () => {
|
|
|
91
91
|
})
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
+
it('applies inputSize classes on wrapper, input and search button', () => {
|
|
95
|
+
const { container } = render(
|
|
96
|
+
<PktSearchInput id="test-search-input" appearance="local-with-button" inputSize="small" />,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
expect(container.querySelector('.pkt-searchinput--small')).toBeTruthy()
|
|
100
|
+
expect(container.querySelector('.pkt-input--small')).toBeTruthy()
|
|
101
|
+
expect(container.querySelector('.pkt-searchinput__button.pkt-btn--small')).toBeTruthy()
|
|
102
|
+
})
|
|
103
|
+
|
|
94
104
|
describe('accessibility', () => {
|
|
95
105
|
it('renders with no wcag errors with axe', async () => {
|
|
96
106
|
const suggestions = [
|
|
@@ -19,6 +19,7 @@ export type PktSearchInputSuggestion = Omit<IPktSearchInputSuggestion, 'title' |
|
|
|
19
19
|
|
|
20
20
|
interface ISearch extends HTMLProps<HTMLInputElement> {
|
|
21
21
|
appearance?: 'local' | 'local-with-button' | 'global'
|
|
22
|
+
inputSize?: 'small' | 'medium' | 'xsmall'
|
|
22
23
|
disabled?: boolean
|
|
23
24
|
fullwidth?: boolean
|
|
24
25
|
id: string
|
|
@@ -47,6 +48,7 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
47
48
|
(
|
|
48
49
|
{
|
|
49
50
|
appearance = 'local',
|
|
51
|
+
inputSize = 'medium',
|
|
50
52
|
disabled = false,
|
|
51
53
|
fullwidth = false,
|
|
52
54
|
id,
|
|
@@ -76,9 +78,14 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
76
78
|
value = e.target.value
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
const wrapperClass =
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const wrapperClass = [
|
|
82
|
+
'pkt-searchinput',
|
|
83
|
+
`pkt-searchinput--${appearance}`,
|
|
84
|
+
`pkt-searchinput--${inputSize}`,
|
|
85
|
+
fullwidth && 'pkt-searchinput--fullwidth',
|
|
86
|
+
]
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.join(' ')
|
|
82
89
|
|
|
83
90
|
const focusModality = useFocusModality()
|
|
84
91
|
|
|
@@ -107,6 +114,9 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
107
114
|
const suggestionClassName = (suggestion: PktSearchInputSuggestion) =>
|
|
108
115
|
['pkt-searchinput__suggestion', suggestion.onClick ? 'pkt-link-button' : ''].filter(Boolean).join(' ')
|
|
109
116
|
|
|
117
|
+
const fieldClass =
|
|
118
|
+
appearance === 'local' ? `pkt-input__container pkt-input__container--${inputSize}` : 'pkt-searchinput__field'
|
|
119
|
+
|
|
110
120
|
return WrapperElement(
|
|
111
121
|
<>
|
|
112
122
|
{label && (
|
|
@@ -114,9 +124,9 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
114
124
|
{label}
|
|
115
125
|
</label>
|
|
116
126
|
)}
|
|
117
|
-
<div className={
|
|
127
|
+
<div className={fieldClass}>
|
|
118
128
|
<input
|
|
119
|
-
className={`pkt-input ${fullwidth ? 'pkt-input--fullwidth' : ''}`}
|
|
129
|
+
className={`pkt-input pkt-input--${inputSize} ${fullwidth ? 'pkt-input--fullwidth' : ''}`}
|
|
120
130
|
type="search"
|
|
121
131
|
name={name || id}
|
|
122
132
|
id={id}
|
|
@@ -124,9 +134,9 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
124
134
|
defaultValue={value}
|
|
125
135
|
disabled={disabled}
|
|
126
136
|
autoComplete="off"
|
|
127
|
-
aria-autocomplete=
|
|
137
|
+
aria-autocomplete={suggestions ? 'list' : undefined}
|
|
128
138
|
ref={ref}
|
|
129
|
-
aria-controls={`${id}-suggestions`}
|
|
139
|
+
aria-controls={suggestions ? `${id}-suggestions` : undefined}
|
|
130
140
|
onChange={onChange ? onChange : handleNoOnChange}
|
|
131
141
|
onKeyUp={
|
|
132
142
|
onSearch &&
|
|
@@ -139,10 +149,12 @@ export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearc
|
|
|
139
149
|
}
|
|
140
150
|
{...props}
|
|
141
151
|
/>
|
|
152
|
+
|
|
142
153
|
<PktButton
|
|
143
154
|
className={`pkt-searchinput__button ${appearance === 'local' ? 'pkt-input-icon' : ''}`}
|
|
144
155
|
variant="icon-only"
|
|
145
156
|
iconName="magnifying-glass-big"
|
|
157
|
+
size={inputSize}
|
|
146
158
|
skin={appearance === 'local' ? 'tertiary' : 'primary'}
|
|
147
159
|
color={appearance === 'global' ? 'yellow' : undefined}
|
|
148
160
|
type="submit"
|
|
@@ -8,6 +8,24 @@ import { PktSelect } from './Select'
|
|
|
8
8
|
expect.extend(toHaveNoViolations)
|
|
9
9
|
|
|
10
10
|
describe('PktSelect', () => {
|
|
11
|
+
test('applies input wrapper size classes for small and xsmall', () => {
|
|
12
|
+
const { container: smallContainer } = render(
|
|
13
|
+
<PktSelect label="Label" id="select-small" inputSize="small">
|
|
14
|
+
<option value="a">A</option>
|
|
15
|
+
</PktSelect>,
|
|
16
|
+
)
|
|
17
|
+
expect(smallContainer.querySelector('.pkt-inputwrapper')).toHaveClass('pkt-inputwrapper--small')
|
|
18
|
+
expect(smallContainer.querySelector('.pkt-inputwrapper')).not.toHaveClass('pkt-inputwrapper--xsmall')
|
|
19
|
+
|
|
20
|
+
const { container: xsmallContainer } = render(
|
|
21
|
+
<PktSelect label="Label" id="select-xsmall" inputSize="xsmall">
|
|
22
|
+
<option value="a">A</option>
|
|
23
|
+
</PktSelect>,
|
|
24
|
+
)
|
|
25
|
+
expect(xsmallContainer.querySelector('.pkt-inputwrapper')).not.toHaveClass('pkt-inputwrapper--small')
|
|
26
|
+
expect(xsmallContainer.querySelector('.pkt-inputwrapper')).toHaveClass('pkt-inputwrapper--xsmall')
|
|
27
|
+
})
|
|
28
|
+
|
|
11
29
|
test('renders select field with correct props', async () => {
|
|
12
30
|
const { container } = render(
|
|
13
31
|
<PktSelect label="Input Label" id="inputIdeas" ariaLabelledby="inputId">
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { ForwardedRef, forwardRef, ReactNode, SelectHTMLAttributes } from 'react'
|
|
4
|
-
import type { TSelectOption } from 'shared-types'
|
|
5
4
|
|
|
6
5
|
import { PktInputWrapper } from '../inputwrapper/InputWrapper'
|
|
7
6
|
|
|
8
|
-
export type { TSelectOption }
|
|
7
|
+
export type { IPktSelectOption, TSelectOption } from 'shared-types/select'
|
|
9
8
|
|
|
10
9
|
export interface IPktSelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
|
|
11
10
|
ariaDescribedby?: string
|
|
@@ -27,7 +26,9 @@ export interface IPktSelectProps extends SelectHTMLAttributes<HTMLSelectElement>
|
|
|
27
26
|
requiredTag?: boolean
|
|
28
27
|
requiredText?: string
|
|
29
28
|
tagText?: string | null
|
|
30
|
-
|
|
29
|
+
inputSize?: 'small' | 'medium' | 'xsmall'
|
|
30
|
+
/** @deprecated Var aldri implementert — bruk children med `<option>`-elementer. */
|
|
31
|
+
options?: never
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const PktSelect = forwardRef(
|
|
@@ -53,11 +54,13 @@ export const PktSelect = forwardRef(
|
|
|
53
54
|
requiredTag = false,
|
|
54
55
|
requiredText,
|
|
55
56
|
tagText,
|
|
57
|
+
inputSize = 'medium',
|
|
56
58
|
...props
|
|
57
59
|
}: IPktSelectProps,
|
|
58
60
|
ref: ForwardedRef<HTMLSelectElement>,
|
|
59
61
|
) => {
|
|
60
62
|
const classNames = [className, 'pkt-select'].join(' ')
|
|
63
|
+
|
|
61
64
|
return (
|
|
62
65
|
<PktInputWrapper
|
|
63
66
|
className={classNames}
|
|
@@ -76,10 +79,11 @@ export const PktSelect = forwardRef(
|
|
|
76
79
|
disabled={disabled}
|
|
77
80
|
inline={inline}
|
|
78
81
|
ariaDescribedby={ariaDescribedby}
|
|
82
|
+
size={inputSize}
|
|
79
83
|
>
|
|
80
84
|
<select
|
|
81
85
|
ref={ref}
|
|
82
|
-
className={`pkt-input ${fullwidth ? 'pkt-input--fullwidth' : ''}`}
|
|
86
|
+
className={`pkt-input pkt-input--${inputSize} ${fullwidth ? 'pkt-input--fullwidth' : ''}`}
|
|
83
87
|
aria-invalid={hasError}
|
|
84
88
|
aria-errormessage={`${id}-error`}
|
|
85
89
|
aria-labelledby={ariaLabelledby || undefined}
|
|
@@ -15,6 +15,16 @@ describe('PktTextarea', () => {
|
|
|
15
15
|
expect(inputElement).toBeInTheDocument()
|
|
16
16
|
expect(inputElement.tagName).toBe('TEXTAREA')
|
|
17
17
|
expect(inputElement.id).toBe('inputId-input')
|
|
18
|
+
expect(inputElement).toHaveClass('pkt-input--medium')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('applies inputSize to textarea and wrapper', async () => {
|
|
22
|
+
const { container, getByLabelText } = render(
|
|
23
|
+
<PktTextarea label="Small textarea" id="smallTextarea" inputSize="small" />,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
expect(getByLabelText('Small textarea')).toHaveClass('pkt-input--small')
|
|
27
|
+
expect(container.querySelector('.pkt-inputwrapper--small')).toBeInTheDocument()
|
|
18
28
|
})
|
|
19
29
|
|
|
20
30
|
test('renders error message when hasError prop is true', async () => {
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from 'react'
|
|
13
13
|
|
|
14
14
|
import { PktInputWrapper } from '../inputwrapper/InputWrapper'
|
|
15
|
+
import { TPktInputSize } from 'shared-types/size'
|
|
15
16
|
|
|
16
17
|
export interface IPktTextarea extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
17
18
|
id: string
|
|
@@ -44,6 +45,7 @@ export interface IPktTextarea extends TextareaHTMLAttributes<HTMLTextAreaElement
|
|
|
44
45
|
readOnly?: boolean
|
|
45
46
|
required?: boolean
|
|
46
47
|
skipForwardTestid?: boolean
|
|
48
|
+
inputSize?: TPktInputSize
|
|
47
49
|
onChange?: ChangeEventHandler<HTMLTextAreaElement>
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -81,6 +83,7 @@ export const PktTextarea = forwardRef(
|
|
|
81
83
|
maxLength,
|
|
82
84
|
readOnly,
|
|
83
85
|
skipForwardTestid = false,
|
|
86
|
+
inputSize = 'medium',
|
|
84
87
|
...props
|
|
85
88
|
}: IPktTextarea,
|
|
86
89
|
ref: ForwardedRef<HTMLTextAreaElement>,
|
|
@@ -137,10 +140,11 @@ export const PktTextarea = forwardRef(
|
|
|
137
140
|
counter={counter}
|
|
138
141
|
counterCurrent={counterCurrent}
|
|
139
142
|
counterMaxLength={counterMaxLength}
|
|
143
|
+
size={inputSize}
|
|
140
144
|
>
|
|
141
145
|
<textarea
|
|
142
146
|
ref={initRef}
|
|
143
|
-
className={`pkt-input ${fullwidth ? 'pkt-input--fullwidth' : ''} ${
|
|
147
|
+
className={`pkt-input pkt-input--${inputSize} ${fullwidth ? 'pkt-input--fullwidth' : ''} ${
|
|
144
148
|
counterMaxLength && counterCurrent > counterMaxLength ? 'pkt-input--counter-error' : ''
|
|
145
149
|
}`}
|
|
146
150
|
name={`${name || id}`}
|
|
@@ -27,7 +27,35 @@ describe('PktTextinput', () => {
|
|
|
27
27
|
const alertContainer = screen.getByRole('alert')
|
|
28
28
|
expect(alertContainer).toHaveAttribute('id', errorMessageId)
|
|
29
29
|
expect(alertContainer).toHaveTextContent('Input error')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('inputSize', () => {
|
|
33
|
+
test('applies medium size classes by default', async () => {
|
|
34
|
+
const { container } = render(<PktTextinput label={label} id={inputId} />)
|
|
35
|
+
|
|
36
|
+
const inputElement = container.querySelector('input')
|
|
37
|
+
const containerElement = container.querySelector('.pkt-input__container')
|
|
38
|
+
expect(inputElement).toHaveClass('pkt-input--medium')
|
|
39
|
+
expect(containerElement).toHaveClass('pkt-input__container--medium')
|
|
40
|
+
})
|
|
30
41
|
|
|
42
|
+
test('applies small size classes when inputSize is small', async () => {
|
|
43
|
+
const { container } = render(<PktTextinput label={label} id={inputId} inputSize="small" />)
|
|
44
|
+
|
|
45
|
+
const inputElement = container.querySelector('input')
|
|
46
|
+
const containerElement = container.querySelector('.pkt-input__container')
|
|
47
|
+
expect(inputElement).toHaveClass('pkt-input--small')
|
|
48
|
+
expect(containerElement).toHaveClass('pkt-input__container--small')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('applies xsmall size classes when inputSize is xsmall', async () => {
|
|
52
|
+
const { container } = render(<PktTextinput label={label} id={inputId} inputSize="xsmall" />)
|
|
53
|
+
|
|
54
|
+
const inputElement = container.querySelector('input')
|
|
55
|
+
const containerElement = container.querySelector('.pkt-input__container')
|
|
56
|
+
expect(inputElement).toHaveClass('pkt-input--xsmall')
|
|
57
|
+
expect(containerElement).toHaveClass('pkt-input__container--xsmall')
|
|
58
|
+
})
|
|
31
59
|
})
|
|
32
60
|
|
|
33
61
|
describe('PktTextinput', () => {
|
|
@@ -55,6 +55,7 @@ export interface IPktTextinput extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
55
55
|
dataTestid?: string
|
|
56
56
|
onChange?: ChangeEventHandler<HTMLInputElement>
|
|
57
57
|
skipForwardTestid?: boolean
|
|
58
|
+
inputSize?: 'small' | 'medium' | 'xsmall'
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
export const PktTextinput = forwardRef(
|
|
@@ -101,6 +102,7 @@ export const PktTextinput = forwardRef(
|
|
|
101
102
|
dataTestid,
|
|
102
103
|
onChange,
|
|
103
104
|
skipForwardTestid = false,
|
|
105
|
+
inputSize = 'medium',
|
|
104
106
|
...props
|
|
105
107
|
}: IPktTextinput,
|
|
106
108
|
ref: ForwardedRef<HTMLInputElement>,
|
|
@@ -153,9 +155,10 @@ export const PktTextinput = forwardRef(
|
|
|
153
155
|
counter={counter}
|
|
154
156
|
counterCurrent={counterCurrent}
|
|
155
157
|
counterMaxLength={counterMaxLength}
|
|
158
|
+
size={inputSize}
|
|
156
159
|
>
|
|
157
160
|
<div
|
|
158
|
-
className=
|
|
161
|
+
className={`pkt-input__container pkt-input__container--${inputSize}`}
|
|
159
162
|
data-testid={dataTestid}
|
|
160
163
|
data-skip-forward-testid={skipForwardTestid ? 'true' : undefined}
|
|
161
164
|
>
|
|
@@ -163,7 +166,7 @@ export const PktTextinput = forwardRef(
|
|
|
163
166
|
<input
|
|
164
167
|
{...props}
|
|
165
168
|
ref={ref}
|
|
166
|
-
className={`pkt-input ${fullwidth ? 'pkt-input--fullwidth' : ''} ${
|
|
169
|
+
className={`pkt-input pkt-input--${inputSize} ${fullwidth ? 'pkt-input--fullwidth' : ''} ${
|
|
167
170
|
counterMaxLength && counterCurrent > counterMaxLength ? 'pkt-input--counter-error' : ''
|
|
168
171
|
}`}
|
|
169
172
|
type={type}
|
|
@@ -43,6 +43,16 @@ describe('PktTimepicker', () => {
|
|
|
43
43
|
expect(container.querySelector('.pkt-timepicker--fullwidth')).toBeInTheDocument()
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
+
test('applies inputSize classes on root, container, inputs and clock button', () => {
|
|
47
|
+
const { container } = render(
|
|
48
|
+
<PktTimepicker id={id} name="t" label={label} inputSize="small" />,
|
|
49
|
+
)
|
|
50
|
+
expect(container.querySelector('.pkt-timepicker--small')).toBeTruthy()
|
|
51
|
+
expect(container.querySelector('.pkt-input__container--small')).toBeTruthy()
|
|
52
|
+
expect(container.querySelectorAll('.pkt-input--small')).toHaveLength(2)
|
|
53
|
+
expect(container.querySelector('.pkt-timepicker__button.pkt-btn--small')).toBeTruthy()
|
|
54
|
+
})
|
|
55
|
+
|
|
46
56
|
test('renders clock button when picker is visible', () => {
|
|
47
57
|
render(<PktTimepicker id={id} name="t" label={label} />)
|
|
48
58
|
expect(
|
|
@@ -10,7 +10,7 @@ import type { IPktTimepicker } from './types'
|
|
|
10
10
|
export type { IPktTimepicker } from './types'
|
|
11
11
|
|
|
12
12
|
export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props, ref) => {
|
|
13
|
-
const { onChange } = props
|
|
13
|
+
const { onChange, inputSize = 'medium' } = props
|
|
14
14
|
const state = useTimepickerState(props, ref)
|
|
15
15
|
|
|
16
16
|
const hoursLabel = state.strings.hours
|
|
@@ -80,7 +80,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
80
80
|
|
|
81
81
|
const renderContainer = () => (
|
|
82
82
|
<div
|
|
83
|
-
className=
|
|
83
|
+
className={`pkt-input__container pkt-input__container--${inputSize}`}
|
|
84
84
|
onClick={(e) => {
|
|
85
85
|
const target = e.target as HTMLElement
|
|
86
86
|
if (target.closest('button, input')) return
|
|
@@ -90,7 +90,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
90
90
|
{state.stepArrows && (
|
|
91
91
|
<button
|
|
92
92
|
type="button"
|
|
93
|
-
className=
|
|
93
|
+
className={`pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${inputSize} pkt-timepicker__button pkt-timepicker__button--prev`}
|
|
94
94
|
aria-label={state.strings.prevTime}
|
|
95
95
|
disabled={state.disabled}
|
|
96
96
|
onClick={() => state.stepTimeDelta(-1)}
|
|
@@ -105,7 +105,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
105
105
|
inputMode="numeric"
|
|
106
106
|
maxLength={2}
|
|
107
107
|
size={2}
|
|
108
|
-
className=
|
|
108
|
+
className={`pkt-input pkt-input--${inputSize} pkt-timepicker__input`}
|
|
109
109
|
id={state.hoursId}
|
|
110
110
|
data-min="0"
|
|
111
111
|
data-max="23"
|
|
@@ -137,7 +137,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
137
137
|
inputMode="numeric"
|
|
138
138
|
maxLength={2}
|
|
139
139
|
size={2}
|
|
140
|
-
className=
|
|
140
|
+
className={`pkt-input pkt-input--${inputSize} pkt-timepicker__input`}
|
|
141
141
|
id={state.minutesId}
|
|
142
142
|
data-min="0"
|
|
143
143
|
data-max="59"
|
|
@@ -169,7 +169,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
169
169
|
<button
|
|
170
170
|
ref={state.buttonRef}
|
|
171
171
|
type="button"
|
|
172
|
-
className=
|
|
172
|
+
className={`pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${inputSize} pkt-timepicker__button`}
|
|
173
173
|
aria-label={state.strings.openPicker}
|
|
174
174
|
aria-haspopup="listbox"
|
|
175
175
|
aria-expanded={state.isOpen}
|
|
@@ -184,7 +184,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
184
184
|
{state.stepArrows && (
|
|
185
185
|
<button
|
|
186
186
|
type="button"
|
|
187
|
-
className=
|
|
187
|
+
className={`pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${inputSize} pkt-timepicker__button pkt-timepicker__button--next`}
|
|
188
188
|
aria-label={state.strings.nextTime}
|
|
189
189
|
disabled={state.disabled}
|
|
190
190
|
onClick={() => state.stepTimeDelta(1)}
|
|
@@ -234,6 +234,7 @@ export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props,
|
|
|
234
234
|
helptextDropdown={state.helptextDropdown}
|
|
235
235
|
helptextDropdownButton={state.helptextDropdownButton}
|
|
236
236
|
tagText={state.tagText}
|
|
237
|
+
size={inputSize}
|
|
237
238
|
>
|
|
238
239
|
{!state.hidePicker && !state.stepArrows ? (
|
|
239
240
|
<div className="pkt-timepicker__anchor">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ChangeEvent, FocusEvent, InputHTMLAttributes, ReactNode } from 'react'
|
|
2
|
+
import { TPktInputSize } from 'shared-types/size'
|
|
2
3
|
import type { ITimepickerStrings } from 'shared-types/timepicker'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -7,11 +8,10 @@ import type { ITimepickerStrings } from 'shared-types/timepicker'
|
|
|
7
8
|
* The value is submitted via a hidden `input type="time"`; hour/minute fields are the editing UI. Use `value`
|
|
8
9
|
* or `defaultValue` for controlled vs. uncontrolled mode.
|
|
9
10
|
*/
|
|
10
|
-
export interface IPktTimepicker
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
> {
|
|
11
|
+
export interface IPktTimepicker extends Omit<
|
|
12
|
+
InputHTMLAttributes<HTMLInputElement>,
|
|
13
|
+
'value' | 'onChange' | 'onInput' | 'min' | 'max' | 'step' | 'onFocus' | 'onBlur'
|
|
14
|
+
> {
|
|
15
15
|
/** Unique id; used for hour, minute, popup, and hidden input ids. */
|
|
16
16
|
id: string
|
|
17
17
|
|
|
@@ -112,4 +112,7 @@ export interface IPktTimepicker
|
|
|
112
112
|
|
|
113
113
|
/** Extra class names on the root (`pkt-timepicker`). */
|
|
114
114
|
className?: string
|
|
115
|
+
|
|
116
|
+
/** Size of the Timepicker component. */
|
|
117
|
+
inputSize?: TPktInputSize
|
|
115
118
|
}
|
|
@@ -14,6 +14,7 @@ import { stepTime } from 'shared-utils/timepicker/stepper'
|
|
|
14
14
|
import { isValidTimeString, timeToMinutes } from 'shared-utils/timepicker/time-utils'
|
|
15
15
|
|
|
16
16
|
import type { IPktTimepicker } from './types'
|
|
17
|
+
import { TPktInputSize } from 'shared-types/size'
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* ## Why this hook exists (React form model)
|
|
@@ -138,6 +139,7 @@ export function useTimepickerState(props: IPktTimepicker, ref: React.ForwardedRe
|
|
|
138
139
|
ariaDescribedby,
|
|
139
140
|
strings: stringsProp,
|
|
140
141
|
className,
|
|
142
|
+
inputSize = 'medium' as TPktInputSize,
|
|
141
143
|
onValueChange,
|
|
142
144
|
onFocus: onFocusProp,
|
|
143
145
|
onBlur: onBlurProp,
|
|
@@ -777,6 +779,7 @@ export function useTimepickerState(props: IPktTimepicker, ref: React.ForwardedRe
|
|
|
777
779
|
|
|
778
780
|
const outerClasses = [
|
|
779
781
|
'pkt-timepicker',
|
|
782
|
+
`pkt-timepicker--${inputSize}`,
|
|
780
783
|
fullwidth ? 'pkt-timepicker--fullwidth' : '',
|
|
781
784
|
stepArrows ? 'pkt-timepicker--stepper' : '',
|
|
782
785
|
className ?? '',
|
|
@@ -788,6 +791,7 @@ export function useTimepickerState(props: IPktTimepicker, ref: React.ForwardedRe
|
|
|
788
791
|
id,
|
|
789
792
|
containerRef,
|
|
790
793
|
outerClasses,
|
|
794
|
+
inputSize,
|
|
791
795
|
strings,
|
|
792
796
|
label,
|
|
793
797
|
disabled,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare const acquireModalScrollLock: (token: {
|
|
2
|
-
locked: boolean;
|
|
3
|
-
}) => void;
|
|
4
|
-
export declare const releaseModalScrollLock: (token: {
|
|
5
|
-
locked: boolean;
|
|
6
|
-
}) => void;
|
|
7
|
-
export type ModalScrollLockToken = {
|
|
8
|
-
locked: boolean;
|
|
9
|
-
};
|
|
10
|
-
export declare const createModalScrollLockToken: () => ModalScrollLockToken;
|
|
File without changes
|