@seamapi/react 1.30.2 → 1.32.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/README.md +1 -1
- package/dist/elements.js +6286 -5829
- package/dist/elements.js.map +1 -1
- package/dist/index.css +106 -0
- package/dist/index.css.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.css.map +1 -1
- package/lib/dates.d.ts +50 -0
- package/lib/dates.js +93 -1
- package/lib/dates.js.map +1 -1
- package/lib/icons/CheckboxBlank.d.ts +2 -0
- package/lib/icons/CheckboxBlank.js +5 -0
- package/lib/icons/CheckboxBlank.js.map +1 -0
- package/lib/icons/CheckboxFilled.d.ts +2 -0
- package/lib/icons/CheckboxFilled.js +5 -0
- package/lib/icons/CheckboxFilled.js.map +1 -0
- package/lib/icons/Edit.d.ts +2 -0
- package/lib/icons/Edit.js +7 -0
- package/lib/icons/Edit.js.map +1 -0
- package/lib/icons/RadioChecked.d.ts +2 -0
- package/lib/icons/RadioChecked.js +5 -0
- package/lib/icons/RadioChecked.js.map +1 -0
- package/lib/icons/RadioUnchecked.d.ts +2 -0
- package/lib/icons/RadioUnchecked.js +5 -0
- package/lib/icons/RadioUnchecked.js.map +1 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeForm.js +66 -12
- package/lib/seam/components/AccessCodeForm/AccessCodeForm.js.map +1 -1
- package/lib/seam/components/AccessCodeForm/AccessCodeFormDatePicker.d.ts +13 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormDatePicker.js +18 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormDatePicker.js.map +1 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimes.d.ts +8 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimes.js +12 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimes.js.map +1 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimezonePicker.d.ts +8 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimezonePicker.js +25 -0
- package/lib/seam/components/AccessCodeForm/AccessCodeFormTimezonePicker.js.map +1 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +2 -1
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +2 -2
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
- package/lib/seam/components/DeviceTable/DeviceTable.d.ts +2 -1
- package/lib/seam/components/DeviceTable/DeviceTable.js +2 -2
- package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
- package/lib/ui/Checkbox.d.ts +9 -0
- package/lib/ui/Checkbox.js +17 -0
- package/lib/ui/Checkbox.js.map +1 -0
- package/lib/ui/DateTimePicker/DateTimePicker.d.ts +5 -0
- package/lib/ui/DateTimePicker/DateTimePicker.js +8 -0
- package/lib/ui/DateTimePicker/DateTimePicker.js.map +1 -0
- package/lib/ui/FormField.js +2 -1
- package/lib/ui/FormField.js.map +1 -1
- package/lib/ui/Menu/Menu.d.ts +2 -2
- package/lib/ui/Menu/Menu.js +1 -5
- package/lib/ui/Menu/Menu.js.map +1 -1
- package/lib/ui/RadioField/Radio.d.ts +7 -0
- package/lib/ui/RadioField/Radio.js +19 -0
- package/lib/ui/RadioField/Radio.js.map +1 -0
- package/lib/ui/RadioField/RadioField.d.ts +15 -0
- package/lib/ui/RadioField/RadioField.js +20 -0
- package/lib/ui/RadioField/RadioField.js.map +1 -0
- package/lib/ui/TextField/TextField.d.ts +4 -2
- package/lib/ui/TextField/TextField.js +2 -2
- package/lib/ui/TextField/TextField.js.map +1 -1
- package/lib/ui/layout/ContentHeader.d.ts +2 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +9 -4
- package/src/lib/dates.ts +120 -1
- package/src/lib/icons/CheckboxBlank.tsx +22 -0
- package/src/lib/icons/CheckboxFilled.tsx +23 -0
- package/src/lib/icons/Edit.tsx +36 -0
- package/src/lib/icons/RadioChecked.tsx +21 -0
- package/src/lib/icons/RadioUnchecked.tsx +23 -0
- package/src/lib/seam/components/AccessCodeForm/AccessCodeForm.tsx +137 -23
- package/src/lib/seam/components/AccessCodeForm/AccessCodeFormDatePicker.tsx +68 -0
- package/src/lib/seam/components/AccessCodeForm/AccessCodeFormTimes.tsx +34 -0
- package/src/lib/seam/components/AccessCodeForm/AccessCodeFormTimezonePicker.tsx +70 -0
- package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.element.ts +1 -0
- package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +9 -5
- package/src/lib/seam/components/DeviceTable/DeviceTable.element.ts +1 -0
- package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +9 -5
- package/src/lib/ui/Checkbox.tsx +44 -0
- package/src/lib/ui/DateTimePicker/DateTimePicker.tsx +30 -0
- package/src/lib/ui/FormField.tsx +2 -1
- package/src/lib/ui/Menu/Menu.tsx +4 -8
- package/src/lib/ui/RadioField/Radio.tsx +45 -0
- package/src/lib/ui/RadioField/RadioField.tsx +55 -0
- package/src/lib/ui/TextField/TextField.tsx +12 -2
- package/src/lib/ui/layout/ContentHeader.tsx +1 -1
- package/src/lib/version.ts +1 -1
- package/src/styles/_access-code-form.scss +88 -0
- package/src/styles/_checkbox.scss +25 -0
- package/src/styles/_inputs.scss +3 -0
- package/src/styles/_main.scss +4 -0
- package/src/styles/_radio-field.scss +31 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getBrowserTimezone,
|
|
5
|
+
getTimezoneLabel,
|
|
6
|
+
getTimezoneOffset,
|
|
7
|
+
getTimezones,
|
|
8
|
+
} from 'lib/dates.js'
|
|
9
|
+
import { Checkbox } from 'lib/ui/Checkbox.js'
|
|
10
|
+
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
11
|
+
import { handleString } from 'lib/ui/TextField/TextField.js'
|
|
12
|
+
|
|
13
|
+
interface AccessCodeFormTimezonePickerProps {
|
|
14
|
+
value: string
|
|
15
|
+
onChange: (timezone: string) => void
|
|
16
|
+
onClose: () => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function AccessCodeFormTimezonePicker({
|
|
20
|
+
onChange,
|
|
21
|
+
value,
|
|
22
|
+
onClose,
|
|
23
|
+
}: AccessCodeFormTimezonePickerProps): JSX.Element {
|
|
24
|
+
const [manualTimezoneEnabled, setManualTimezoneEnabled] = useState(false)
|
|
25
|
+
|
|
26
|
+
const isBrowserTimezone = value === getBrowserTimezone()
|
|
27
|
+
const isManualTimezone = !isBrowserTimezone || manualTimezoneEnabled
|
|
28
|
+
|
|
29
|
+
const handleChangeManualTimezone = (enabled: boolean): void => {
|
|
30
|
+
setManualTimezoneEnabled(enabled)
|
|
31
|
+
if (!enabled) {
|
|
32
|
+
onChange(getBrowserTimezone())
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const title = isManualTimezone ? t.titleManual : t.titleAuto
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className='seam-timezone-picker'>
|
|
40
|
+
<ContentHeader title={title} onBack={onClose} />
|
|
41
|
+
<div className='seam-content'>
|
|
42
|
+
<Checkbox
|
|
43
|
+
label={t.setTimezoneManuallyLabel}
|
|
44
|
+
checked={isManualTimezone}
|
|
45
|
+
onChange={handleChangeManualTimezone}
|
|
46
|
+
className='seam-manual-timezone-checkbox'
|
|
47
|
+
/>
|
|
48
|
+
|
|
49
|
+
<select
|
|
50
|
+
value={value}
|
|
51
|
+
onChange={handleString(onChange)}
|
|
52
|
+
className='seam-timezone-select'
|
|
53
|
+
disabled={!isManualTimezone}
|
|
54
|
+
>
|
|
55
|
+
{getTimezones().map((timezone) => (
|
|
56
|
+
<option value={timezone} key={timezone}>
|
|
57
|
+
UTC {getTimezoneOffset(timezone)} {getTimezoneLabel(timezone)}
|
|
58
|
+
</option>
|
|
59
|
+
))}
|
|
60
|
+
</select>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const t = {
|
|
67
|
+
titleAuto: 'Time Zone (automatic)',
|
|
68
|
+
titleManual: 'Time Zone (manual)',
|
|
69
|
+
setTimezoneManuallyLabel: 'Set time zone manually',
|
|
70
|
+
}
|
|
@@ -7,6 +7,7 @@ export const name = 'seam-access-code-table'
|
|
|
7
7
|
export const props: ElementProps<AccessCodeTableProps> = {
|
|
8
8
|
deviceId: 'string',
|
|
9
9
|
disableLockUnlock: 'boolean',
|
|
10
|
+
disableSearch: 'boolean',
|
|
10
11
|
accessCodeFilter: 'function',
|
|
11
12
|
accessCodeComparator: 'function',
|
|
12
13
|
onAccessCodeClick: 'function',
|
|
@@ -39,6 +39,7 @@ const disableCreateAccessCode = true
|
|
|
39
39
|
export interface AccessCodeTableProps {
|
|
40
40
|
deviceId: string
|
|
41
41
|
disableLockUnlock?: boolean
|
|
42
|
+
disableSearch?: boolean
|
|
42
43
|
accessCodeFilter?: (
|
|
43
44
|
accessCode: AccessCode,
|
|
44
45
|
searchInputValue: string
|
|
@@ -71,6 +72,7 @@ const defaultAccessCodeFilter = (
|
|
|
71
72
|
export function AccessCodeTable({
|
|
72
73
|
deviceId,
|
|
73
74
|
disableLockUnlock = false,
|
|
75
|
+
disableSearch = false,
|
|
74
76
|
onAccessCodeClick = () => {},
|
|
75
77
|
preventDefaultOnAccessCodeClick = false,
|
|
76
78
|
onBack,
|
|
@@ -150,11 +152,13 @@ export function AccessCodeTable({
|
|
|
150
152
|
</IconButton>
|
|
151
153
|
)}
|
|
152
154
|
</div>
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
{!disableSearch && (
|
|
156
|
+
<SearchTextField
|
|
157
|
+
value={searchInputValue}
|
|
158
|
+
onChange={setSearchInputValue}
|
|
159
|
+
disabled={(accessCodes?.length ?? 0) === 0}
|
|
160
|
+
/>
|
|
161
|
+
)}
|
|
158
162
|
</TableHeader>
|
|
159
163
|
<TableBody>
|
|
160
164
|
<Content
|
|
@@ -28,6 +28,7 @@ export interface DeviceTableProps {
|
|
|
28
28
|
deviceIds?: string[]
|
|
29
29
|
connectedAccountIds?: string[]
|
|
30
30
|
disableLockUnlock?: boolean
|
|
31
|
+
disableSearch?: boolean
|
|
31
32
|
deviceFilter?: (device: Device, searchInputValue: string) => boolean
|
|
32
33
|
deviceComparator?: (deviceA: Device, deviceB: Device) => number
|
|
33
34
|
onDeviceClick?: (deviceId: string) => void
|
|
@@ -49,6 +50,7 @@ export function DeviceTable({
|
|
|
49
50
|
deviceIds,
|
|
50
51
|
connectedAccountIds,
|
|
51
52
|
disableLockUnlock = false,
|
|
53
|
+
disableSearch = false,
|
|
52
54
|
onDeviceClick = () => {},
|
|
53
55
|
preventDefaultOnDeviceClick = false,
|
|
54
56
|
onBack,
|
|
@@ -110,11 +112,13 @@ export function DeviceTable({
|
|
|
110
112
|
<TableTitle>
|
|
111
113
|
{t.devices} <Caption>({filteredDevices.length})</Caption>
|
|
112
114
|
</TableTitle>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
{!disableSearch && (
|
|
116
|
+
<SearchTextField
|
|
117
|
+
value={searchInputValue}
|
|
118
|
+
onChange={setSearchInputValue}
|
|
119
|
+
disabled={(devices?.length ?? 0) === 0}
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
118
122
|
</TableHeader>
|
|
119
123
|
<TableBody>
|
|
120
124
|
<Content devices={filteredDevices} onDeviceClick={handleDeviceClick} />
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
import { useRef } from 'react'
|
|
3
|
+
|
|
4
|
+
import { CheckboxBlankIcon } from 'lib/icons/CheckboxBlank.js'
|
|
5
|
+
import { CheckboxFilledIcon } from 'lib/icons/CheckboxFilled.js'
|
|
6
|
+
|
|
7
|
+
interface CheckboxProps {
|
|
8
|
+
label: string
|
|
9
|
+
checked?: boolean
|
|
10
|
+
onChange: (checked: boolean) => void
|
|
11
|
+
className?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Checkbox({
|
|
15
|
+
label,
|
|
16
|
+
checked,
|
|
17
|
+
onChange,
|
|
18
|
+
className,
|
|
19
|
+
}: CheckboxProps): JSX.Element {
|
|
20
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
21
|
+
|
|
22
|
+
const toggle = (): void => {
|
|
23
|
+
if (inputRef.current != null) {
|
|
24
|
+
inputRef.current.click()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={classNames('seam-checkbox', className)} onClick={toggle}>
|
|
30
|
+
<span className='seam-checkbox-icon'>
|
|
31
|
+
{checked === true ? <CheckboxFilledIcon /> : <CheckboxBlankIcon />}
|
|
32
|
+
</span>
|
|
33
|
+
<input
|
|
34
|
+
type='checkbox'
|
|
35
|
+
ref={inputRef}
|
|
36
|
+
onChange={(event) => {
|
|
37
|
+
onChange(event.target.checked)
|
|
38
|
+
}}
|
|
39
|
+
checked={checked}
|
|
40
|
+
/>
|
|
41
|
+
<span className=' seam-checkbox-label'>{label}</span>
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
import { forwardRef } from 'react'
|
|
3
|
+
|
|
4
|
+
import { TextField, type TextFieldProps } from 'lib/ui/TextField/TextField.js'
|
|
5
|
+
|
|
6
|
+
type DateTimePickerProps = Pick<
|
|
7
|
+
TextFieldProps,
|
|
8
|
+
'size' | 'value' | 'className'
|
|
9
|
+
> & {
|
|
10
|
+
onChange: (value: string) => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DateTimePicker = forwardRef<
|
|
14
|
+
HTMLInputElement | undefined,
|
|
15
|
+
DateTimePickerProps
|
|
16
|
+
>(function DateTextField(
|
|
17
|
+
{ className, value, onChange, ...props },
|
|
18
|
+
ref
|
|
19
|
+
): JSX.Element {
|
|
20
|
+
return (
|
|
21
|
+
<TextField
|
|
22
|
+
type='datetime-local'
|
|
23
|
+
className={classNames('seam-date-time-picker', className)}
|
|
24
|
+
ref={ref}
|
|
25
|
+
value={value}
|
|
26
|
+
onChange={onChange}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
})
|
package/src/lib/ui/FormField.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import { cloneElement, useRef } from 'react'
|
|
3
3
|
|
|
4
|
+
import { DateTimePicker } from 'lib/ui/DateTimePicker/DateTimePicker.js'
|
|
4
5
|
import { InputLabel } from 'lib/ui/InputLabel.js'
|
|
5
6
|
import { TextField } from 'lib/ui/TextField/TextField.js'
|
|
6
7
|
|
|
@@ -38,7 +39,7 @@ export function FormField({
|
|
|
38
39
|
})
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
if (component.type === TextField) {
|
|
42
|
+
if (component.type === TextField || component.type === DateTimePicker) {
|
|
42
43
|
return cloneElement(component, {
|
|
43
44
|
...baseProps,
|
|
44
45
|
ref: inputRef,
|
package/src/lib/ui/Menu/Menu.tsx
CHANGED
|
@@ -23,11 +23,11 @@ export interface MenuProps extends PropsWithChildren {
|
|
|
23
23
|
}>
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
interface
|
|
26
|
+
interface MenuContext {
|
|
27
27
|
close: () => void
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const menuContext = createContext<
|
|
30
|
+
const menuContext = createContext<MenuContext>({
|
|
31
31
|
close: () => {},
|
|
32
32
|
})
|
|
33
33
|
|
|
@@ -171,10 +171,6 @@ export function Menu({
|
|
|
171
171
|
)
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
export function useMenu():
|
|
175
|
-
|
|
176
|
-
if (context == null) {
|
|
177
|
-
throw new Error('useMenu must be used within a Menu.')
|
|
178
|
-
}
|
|
179
|
-
return context
|
|
174
|
+
export function useMenu(): MenuContext {
|
|
175
|
+
return useContext(menuContext)
|
|
180
176
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
import { RadioCheckedIcon } from 'lib/icons/RadioChecked.js'
|
|
4
|
+
import { RadioUncheckedIcon } from 'lib/icons/RadioUnchecked.js'
|
|
5
|
+
import { useRadioField } from 'lib/ui/RadioField/RadioField.js'
|
|
6
|
+
|
|
7
|
+
interface RadioProps<Value extends string> {
|
|
8
|
+
value: Value
|
|
9
|
+
label: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Radio<Value extends string>({
|
|
13
|
+
value,
|
|
14
|
+
label,
|
|
15
|
+
}: RadioProps<Value>): JSX.Element {
|
|
16
|
+
const { value: fieldValue, onChange, name } = useRadioField<Value>()
|
|
17
|
+
|
|
18
|
+
const checked = fieldValue === value
|
|
19
|
+
|
|
20
|
+
const inputRef = useRef<HTMLInputElement>()
|
|
21
|
+
|
|
22
|
+
const checkRadio = (): void => {
|
|
23
|
+
if (inputRef.current != null) {
|
|
24
|
+
inputRef.current.click()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<label className='seam-radio' onClick={checkRadio}>
|
|
30
|
+
<span className='seam-radio-icon'>
|
|
31
|
+
{checked ? <RadioCheckedIcon /> : <RadioUncheckedIcon />}
|
|
32
|
+
</span>
|
|
33
|
+
<input
|
|
34
|
+
type='radio'
|
|
35
|
+
name={name}
|
|
36
|
+
value={value}
|
|
37
|
+
checked={checked}
|
|
38
|
+
onChange={(event) => {
|
|
39
|
+
onChange(event.target.value as Value)
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
<span className='seam-radio-label'>{label}</span>
|
|
43
|
+
</label>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Radio } from 'lib/ui/RadioField/Radio.js'
|
|
4
|
+
|
|
5
|
+
interface RadioFieldProps<Value extends string> {
|
|
6
|
+
name: string
|
|
7
|
+
value: Value
|
|
8
|
+
onChange: (value: Value) => void
|
|
9
|
+
options: Array<RadioOption<Value>>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface RadioOption<Value> {
|
|
13
|
+
label: string
|
|
14
|
+
value: Value
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type RadioFieldContext<Value extends string> =
|
|
18
|
+
| Omit<RadioFieldProps<Value>, 'options'>
|
|
19
|
+
| undefined
|
|
20
|
+
|
|
21
|
+
const radioFieldContext = createContext<RadioFieldContext<any>>(undefined)
|
|
22
|
+
|
|
23
|
+
export function RadioField<Value extends string>({
|
|
24
|
+
value,
|
|
25
|
+
onChange,
|
|
26
|
+
name,
|
|
27
|
+
options,
|
|
28
|
+
}: RadioFieldProps<Value>): JSX.Element {
|
|
29
|
+
const { Provider } = radioFieldContext
|
|
30
|
+
return (
|
|
31
|
+
<Provider
|
|
32
|
+
value={{
|
|
33
|
+
value,
|
|
34
|
+
onChange,
|
|
35
|
+
name,
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div className='seam-radio-field'>
|
|
39
|
+
{options.map(({ value, label }, index) => (
|
|
40
|
+
<Radio value={value} label={label} key={index} />
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
</Provider>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function useRadioField<Value extends string>(): NonNullable<
|
|
48
|
+
RadioFieldContext<Value>
|
|
49
|
+
> {
|
|
50
|
+
const context = useContext<RadioFieldContext<Value>>(radioFieldContext)
|
|
51
|
+
if (context === undefined) {
|
|
52
|
+
throw new Error('useRadioField must be used within a <RadioField/>')
|
|
53
|
+
}
|
|
54
|
+
return context
|
|
55
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type FocusEventHandler,
|
|
5
5
|
forwardRef,
|
|
6
6
|
type InputHTMLAttributes,
|
|
7
|
+
type MouseEventHandler,
|
|
7
8
|
type MutableRefObject,
|
|
8
9
|
useEffect,
|
|
9
10
|
useImperativeHandle,
|
|
@@ -28,8 +29,10 @@ export interface TextFieldProps {
|
|
|
28
29
|
clearable?: boolean
|
|
29
30
|
onFocus?: FocusEventHandler<HTMLInputElement>
|
|
30
31
|
onBlur?: FocusEventHandler<HTMLInputElement>
|
|
32
|
+
onClick?: MouseEventHandler<HTMLInputElement>
|
|
31
33
|
helperText?: string
|
|
32
34
|
hasError?: boolean
|
|
35
|
+
type?: 'text' | 'datetime-local'
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
export const TextField = forwardRef<
|
|
@@ -48,8 +51,10 @@ export const TextField = forwardRef<
|
|
|
48
51
|
clearable = false,
|
|
49
52
|
onFocus,
|
|
50
53
|
onBlur,
|
|
54
|
+
onClick,
|
|
51
55
|
hasError = false,
|
|
52
56
|
helperText,
|
|
57
|
+
type = 'text',
|
|
53
58
|
},
|
|
54
59
|
ref
|
|
55
60
|
): JSX.Element {
|
|
@@ -90,11 +95,12 @@ export const TextField = forwardRef<
|
|
|
90
95
|
className='seam-text-field-input'
|
|
91
96
|
value={value}
|
|
92
97
|
onChange={onChange == null ? undefined : handleString(onChange)}
|
|
93
|
-
type='text'
|
|
94
98
|
disabled={disabled}
|
|
95
99
|
ref={setInputEl}
|
|
96
100
|
onFocus={onFocus}
|
|
97
101
|
onBlur={onBlur}
|
|
102
|
+
onClick={onClick}
|
|
103
|
+
type={type}
|
|
98
104
|
{...inputProps}
|
|
99
105
|
/>
|
|
100
106
|
{endAdornmentVisible && (
|
|
@@ -122,7 +128,11 @@ export const TextField = forwardRef<
|
|
|
122
128
|
|
|
123
129
|
export const handleString =
|
|
124
130
|
(setter: (v: string) => void) =>
|
|
125
|
-
(
|
|
131
|
+
(
|
|
132
|
+
event: ChangeEvent<
|
|
133
|
+
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
|
134
|
+
>
|
|
135
|
+
): void => {
|
|
126
136
|
setter(event.currentTarget.value)
|
|
127
137
|
}
|
|
128
138
|
|
package/src/lib/version.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
@mixin all {
|
|
4
4
|
.seam-access-code-form {
|
|
5
5
|
@include main;
|
|
6
|
+
@include schedule-picker;
|
|
7
|
+
@include timezone-picker;
|
|
6
8
|
}
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -42,6 +44,34 @@
|
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
.seam-selected-times {
|
|
48
|
+
margin-top: 4px;
|
|
49
|
+
margin-left: 36px;
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 24px;
|
|
53
|
+
|
|
54
|
+
> div {
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: auto auto;
|
|
57
|
+
grid-template-rows: auto auto;
|
|
58
|
+
grid-column-gap: 16px;
|
|
59
|
+
|
|
60
|
+
> span {
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
line-height: 134%;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
> .seam-label {
|
|
66
|
+
color: colors.$text-gray-2;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
> .seam-time {
|
|
70
|
+
color: colors.$text-gray-1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
45
75
|
.seam-actions {
|
|
46
76
|
display: flex;
|
|
47
77
|
gap: 8px;
|
|
@@ -53,3 +83,61 @@
|
|
|
53
83
|
}
|
|
54
84
|
}
|
|
55
85
|
}
|
|
86
|
+
|
|
87
|
+
@mixin schedule-picker {
|
|
88
|
+
.seam-schedule-picker {
|
|
89
|
+
.seam-content {
|
|
90
|
+
padding: 0 24px;
|
|
91
|
+
|
|
92
|
+
.seam-timezone {
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
font-size: 14px;
|
|
96
|
+
margin-bottom: 24px;
|
|
97
|
+
|
|
98
|
+
.seam-label {
|
|
99
|
+
color: colors.$text-gray-2;
|
|
100
|
+
margin-right: 4px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.seam-selected {
|
|
104
|
+
color: colors.$primary;
|
|
105
|
+
cursor: pointer;
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
|
|
109
|
+
svg {
|
|
110
|
+
scale: 0.6667;
|
|
111
|
+
transform: translate(-6px, 2px);
|
|
112
|
+
|
|
113
|
+
* {
|
|
114
|
+
fill: colors.$primary;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@mixin timezone-picker {
|
|
124
|
+
.seam-timezone-picker {
|
|
125
|
+
.seam-content {
|
|
126
|
+
padding: 0 24px;
|
|
127
|
+
|
|
128
|
+
.seam-manual-timezone-checkbox {
|
|
129
|
+
margin-bottom: 8px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
> .seam-timezone-select {
|
|
133
|
+
background: colors.$white;
|
|
134
|
+
padding: 0 12px;
|
|
135
|
+
width: 100%;
|
|
136
|
+
border: 1px solid colors.$text-gray-3;
|
|
137
|
+
border-radius: 8px;
|
|
138
|
+
height: 48px;
|
|
139
|
+
font-size: 16px;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@use './colors';
|
|
2
|
+
|
|
3
|
+
@mixin all {
|
|
4
|
+
.seam-checkbox {
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
gap: 8px;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
padding: 6px 0;
|
|
10
|
+
|
|
11
|
+
> .seam-checkbox-icon {
|
|
12
|
+
height: 24px;
|
|
13
|
+
width: 24px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
> input {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
> .seam-checkbox-label {
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
line-height: 150%;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/styles/_inputs.scss
CHANGED
package/src/styles/_main.scss
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
@use './access-code-form';
|
|
17
17
|
@use './input-label';
|
|
18
18
|
@use './form-field';
|
|
19
|
+
@use './radio-field';
|
|
20
|
+
@use './checkbox';
|
|
19
21
|
|
|
20
22
|
.seam-components {
|
|
21
23
|
// Reset
|
|
@@ -31,6 +33,8 @@
|
|
|
31
33
|
@include layout.all;
|
|
32
34
|
@include icons.all;
|
|
33
35
|
@include menus.all;
|
|
36
|
+
@include checkbox.all;
|
|
37
|
+
@include radio-field.all;
|
|
34
38
|
|
|
35
39
|
// Components
|
|
36
40
|
@include device-details.all;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
@use './colors';
|
|
2
|
+
|
|
3
|
+
@mixin all {
|
|
4
|
+
.seam-radio-field {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: 4px;
|
|
8
|
+
|
|
9
|
+
> .seam-radio {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
gap: 4px;
|
|
13
|
+
padding: 0 8px;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
|
|
16
|
+
> input {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
> .seam-radio-icon {
|
|
21
|
+
height: 24px;
|
|
22
|
+
width: 24px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
> .seam-radio-label {
|
|
26
|
+
font-size: 16px;
|
|
27
|
+
line-height: 134%;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|