@loadsmart/loadsmart-ui 5.0.1 → 5.2.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/dist/components/Button/Button.d.ts +1 -0
- package/dist/components/Calendar/Pickers/PickerButton.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.stories.d.ts +6 -7
- package/dist/components/Dropdown/Dropdown.types.d.ts +2 -2
- package/dist/components/Dropdown/DropdownTrigger.d.ts +1 -1
- package/dist/components/Dropdown/useDropdown.d.ts +1 -5
- package/dist/components/Icon/Icon.d.ts +1 -0
- package/dist/components/Select/Select.types.d.ts +4 -4
- package/dist/components/Table/Table.d.ts +7 -1
- package/dist/components/Table/Table.fixtures.d.ts +1 -0
- package/dist/components/Table/Table.stories.d.ts +20 -4
- package/dist/components/Table/Table.types.d.ts +30 -1
- package/dist/components/Table/useSortBy.d.ts +2 -2
- package/dist/components/Table/useSortBy.types.d.ts +5 -6
- package/dist/hooks/useClickOutside/useClickOutside.d.ts +1 -1
- package/dist/index.js +448 -440
- package/dist/index.js.map +1 -1
- package/dist/loadsmart.theme-63c13988.js +2 -0
- package/dist/{loadsmart.theme-37a60d56.js.map → loadsmart.theme-63c13988.js.map} +1 -1
- package/dist/{prop-06c02f6d.js → prop-0c635ee9.js} +2 -2
- package/dist/{prop-06c02f6d.js.map → prop-0c635ee9.js.map} +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/theming/index.js +1 -1
- package/dist/tools/index.js +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Calendar/Pickers/DayPicker.tsx +9 -1
- package/src/components/Calendar/Pickers/PickerButton.tsx +14 -6
- package/src/components/Dropdown/Dropdown.stories.tsx +26 -75
- package/src/components/Dropdown/Dropdown.tsx +11 -8
- package/src/components/Dropdown/Dropdown.types.ts +2 -2
- package/src/components/Dropdown/DropdownTrigger.tsx +1 -1
- package/src/components/Dropdown/useDropdown.ts +1 -6
- package/src/components/Icon/Icon.tsx +2 -0
- package/src/components/Icon/assets/dots-horizontal.svg +1 -0
- package/src/components/Select/Select.test.tsx +23 -1
- package/src/components/Select/Select.types.ts +4 -4
- package/src/components/Select/useSelect.ts +11 -9
- package/src/components/Table/Table.fixtures.ts +26 -16
- package/src/components/Table/Table.stories.tsx +156 -25
- package/src/components/Table/Table.test.tsx +29 -0
- package/src/components/Table/Table.tsx +85 -1
- package/src/components/Table/Table.types.ts +39 -1
- package/src/components/Table/useSortBy.ts +5 -5
- package/src/components/Table/useSortBy.types.ts +5 -5
- package/src/hooks/useClickOutside/useClickOutside.ts +6 -6
- package/src/testing/SelectEvent/SelectEvent.ts +8 -7
- package/dist/loadsmart.theme-37a60d56.js +0 -2
|
@@ -10,7 +10,14 @@ import hoverable from 'styles/hoverable'
|
|
|
10
10
|
import typography from 'styles/typography'
|
|
11
11
|
|
|
12
12
|
const PickerButton = styled(BaseButton)<{
|
|
13
|
-
$status:
|
|
13
|
+
$status:
|
|
14
|
+
| 'default'
|
|
15
|
+
| 'current-day'
|
|
16
|
+
| 'faded'
|
|
17
|
+
| 'selection-start'
|
|
18
|
+
| 'selection-end'
|
|
19
|
+
| 'selection'
|
|
20
|
+
| 'next-month-day'
|
|
14
21
|
}>`
|
|
15
22
|
${typography(
|
|
16
23
|
conditional({
|
|
@@ -32,25 +39,26 @@ const PickerButton = styled(BaseButton)<{
|
|
|
32
39
|
$status: ['selection-start', 'selection', 'selection-end'],
|
|
33
40
|
}),
|
|
34
41
|
'color-neutral-darker': whenProps({ $status: ['default', 'faded'] }),
|
|
42
|
+
'color-neutral-dark': whenProps({ $status: 'next-month-day' }),
|
|
35
43
|
'color-accent': whenProps({ $status: 'current-day' }),
|
|
36
44
|
})};
|
|
37
45
|
|
|
38
46
|
background: ${conditional({
|
|
39
|
-
'color-transparent': whenProps({ $status: ['default', 'faded'] }),
|
|
47
|
+
'color-transparent': whenProps({ $status: ['default', 'faded', 'next-month-day'] }),
|
|
40
48
|
'color-neutral-darker': whenProps({ $status: ['selection-start', 'selection-end'] }),
|
|
41
49
|
'color-neutral': whenProps({ $status: 'selection' }),
|
|
42
50
|
'color-neutral-lightest': whenProps({ $status: 'current-day' }),
|
|
43
51
|
})};
|
|
44
52
|
|
|
45
53
|
border-color: ${conditional({
|
|
46
|
-
'color-transparent': whenProps({ $status: ['default', 'faded'] }),
|
|
54
|
+
'color-transparent': whenProps({ $status: ['default', 'faded', 'next-month-day'] }),
|
|
47
55
|
'color-neutral-darker': whenProps({ $status: ['selection-start', 'selection-end'] }),
|
|
48
56
|
'color-neutral': whenProps({ $status: 'selection' }),
|
|
49
57
|
'color-neutral-light': whenProps({ $status: 'current-day' }),
|
|
50
58
|
})};
|
|
51
59
|
|
|
52
60
|
${conditional({
|
|
53
|
-
'opacity: 0.
|
|
61
|
+
'opacity: 0.4;': whenProps({ $status: 'faded' }),
|
|
54
62
|
'opacity: 1;': whenProps({ $status: (status) => status !== 'faded' }),
|
|
55
63
|
})}
|
|
56
64
|
|
|
@@ -59,7 +67,7 @@ const PickerButton = styled(BaseButton)<{
|
|
|
59
67
|
${hoverable`
|
|
60
68
|
border-color: ${token('color-neutral')};
|
|
61
69
|
background-color: ${conditional({
|
|
62
|
-
'color-transparent': whenProps({ $status: ['default', 'faded'] }),
|
|
70
|
+
'color-transparent': whenProps({ $status: ['default', 'faded', 'next-month-day'] }),
|
|
63
71
|
'color-neutral-dark': whenProps({
|
|
64
72
|
$status: ['selection-start', 'selection', 'selection-end'],
|
|
65
73
|
}),
|
|
@@ -99,7 +107,7 @@ const PickerButton = styled(BaseButton)<{
|
|
|
99
107
|
'color-transparent': whenProps({ 'aria-checked': false }),
|
|
100
108
|
})};
|
|
101
109
|
|
|
102
|
-
color: ${token('color-neutral-
|
|
110
|
+
color: ${token('color-neutral-darker')};
|
|
103
111
|
`}
|
|
104
112
|
|
|
105
113
|
visibility: ${conditional({
|
|
@@ -8,12 +8,18 @@ import { TextField } from 'components/TextField'
|
|
|
8
8
|
import Dropdown from './Dropdown'
|
|
9
9
|
import DropdownContext from './Dropdown.context'
|
|
10
10
|
|
|
11
|
-
import type { DropdownProps } from './Dropdown.types'
|
|
11
|
+
import type { DropdownProps, DropdownMenuProps, DropdownTriggerProps } from './Dropdown.types'
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
title: 'Components/Dropdown',
|
|
15
15
|
component: Dropdown,
|
|
16
16
|
argTypes: {
|
|
17
|
+
align: {
|
|
18
|
+
control: {
|
|
19
|
+
type: 'select',
|
|
20
|
+
options: ['start', 'end'],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
17
23
|
onBlur: {
|
|
18
24
|
table: {
|
|
19
25
|
disable: true,
|
|
@@ -22,14 +28,16 @@ export default {
|
|
|
22
28
|
},
|
|
23
29
|
} as Meta
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
type DropdownStoryProps = DropdownProps & DropdownMenuProps & DropdownTriggerProps
|
|
32
|
+
|
|
33
|
+
export const Playground: Story<DropdownStoryProps> = (args: DropdownStoryProps) => {
|
|
26
34
|
const [message, setMessage] = useState('')
|
|
27
35
|
|
|
28
36
|
return (
|
|
29
37
|
<div className="flex flex-col">
|
|
30
38
|
<Dropdown {...args}>
|
|
31
|
-
<Dropdown.Trigger>Actions</Dropdown.Trigger>
|
|
32
|
-
<Dropdown.Menu>
|
|
39
|
+
<Dropdown.Trigger outlined={args.outlined}>Actions</Dropdown.Trigger>
|
|
40
|
+
<Dropdown.Menu align={args.align}>
|
|
33
41
|
{ACTIONS.map(({ label, value }) => (
|
|
34
42
|
<Dropdown.Item
|
|
35
43
|
key={value}
|
|
@@ -52,44 +60,18 @@ export const Playground: Story<DropdownProps> = (args: DropdownProps) => {
|
|
|
52
60
|
|
|
53
61
|
Playground.args = {
|
|
54
62
|
disabled: false,
|
|
63
|
+
align: 'start',
|
|
64
|
+
outlined: true,
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
export const
|
|
58
|
-
const [message, setMessage] = useState('')
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div className="flex flex-col">
|
|
62
|
-
<Dropdown {...args}>
|
|
63
|
-
<Dropdown.Trigger>Actions</Dropdown.Trigger>
|
|
64
|
-
<Dropdown.Menu align="end">
|
|
65
|
-
{ACTIONS.map(({ label, value }) => (
|
|
66
|
-
<Dropdown.Item
|
|
67
|
-
key={value}
|
|
68
|
-
onClick={() => {
|
|
69
|
-
setMessage(label)
|
|
70
|
-
}}
|
|
71
|
-
>
|
|
72
|
-
{label}
|
|
73
|
-
</Dropdown.Item>
|
|
74
|
-
))}
|
|
75
|
-
</Dropdown.Menu>
|
|
76
|
-
</Dropdown>
|
|
77
|
-
|
|
78
|
-
<output className="mt-4 text-sm text-black" data-testid="output">
|
|
79
|
-
{message}
|
|
80
|
-
</output>
|
|
81
|
-
</div>
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const WithSections: Story<DropdownProps> = (args: DropdownProps) => {
|
|
67
|
+
export const WithSections: Story<DropdownStoryProps> = (args: DropdownStoryProps) => {
|
|
86
68
|
const [message, setMessage] = useState('')
|
|
87
69
|
|
|
88
70
|
return (
|
|
89
71
|
<div className="flex flex-col">
|
|
90
72
|
<Dropdown {...args}>
|
|
91
|
-
<Dropdown.Trigger>Sections</Dropdown.Trigger>
|
|
92
|
-
<Dropdown.Menu>
|
|
73
|
+
<Dropdown.Trigger outlined={args.outlined}>Sections</Dropdown.Trigger>
|
|
74
|
+
<Dropdown.Menu align={args.align}>
|
|
93
75
|
<Dropdown.Section header="My profile">
|
|
94
76
|
{PROFILE_ACTIONS.map(({ label, value }) => (
|
|
95
77
|
<Dropdown.Item
|
|
@@ -126,16 +108,18 @@ export const WithSections: Story<DropdownProps> = (args: DropdownProps) => {
|
|
|
126
108
|
|
|
127
109
|
WithSections.args = {
|
|
128
110
|
disabled: false,
|
|
111
|
+
outlined: true,
|
|
129
112
|
}
|
|
130
113
|
|
|
131
|
-
export const Extended: Story<
|
|
114
|
+
export const Extended: Story<DropdownStoryProps> = (args: DropdownStoryProps) => {
|
|
132
115
|
const [message, setMessage] = useState('')
|
|
133
116
|
|
|
134
117
|
return (
|
|
135
118
|
<div className="flex flex-col">
|
|
136
119
|
<Dropdown {...args}>
|
|
137
|
-
<Dropdown.Trigger>With Header & Footer</Dropdown.Trigger>
|
|
120
|
+
<Dropdown.Trigger outlined={args.outlined}>With Header & Footer</Dropdown.Trigger>
|
|
138
121
|
<Dropdown.Menu
|
|
122
|
+
align={args.align}
|
|
139
123
|
header={<p className="px-2">Header</p>}
|
|
140
124
|
footer={<p className="px-2">A cool footer</p>}
|
|
141
125
|
>
|
|
@@ -161,41 +145,7 @@ export const Extended: Story<DropdownProps> = (args: DropdownProps) => {
|
|
|
161
145
|
|
|
162
146
|
Extended.args = {
|
|
163
147
|
disabled: false,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
export const NoOutlineOnTrigger: Story<DropdownProps> = (args: DropdownProps) => {
|
|
167
|
-
const [message, setMessage] = useState('')
|
|
168
|
-
|
|
169
|
-
return (
|
|
170
|
-
<div className="flex flex-col">
|
|
171
|
-
<Dropdown {...args}>
|
|
172
|
-
<Dropdown.Trigger outlined={false}>Download</Dropdown.Trigger>
|
|
173
|
-
<Dropdown.Menu
|
|
174
|
-
header={<p className="px-2">Header</p>}
|
|
175
|
-
footer={<p className="px-2">A cool footer</p>}
|
|
176
|
-
>
|
|
177
|
-
{ACTIONS.map(({ label, value }) => (
|
|
178
|
-
<Dropdown.Item
|
|
179
|
-
key={value}
|
|
180
|
-
onClick={() => {
|
|
181
|
-
setMessage(label)
|
|
182
|
-
}}
|
|
183
|
-
>
|
|
184
|
-
{label}
|
|
185
|
-
</Dropdown.Item>
|
|
186
|
-
))}
|
|
187
|
-
</Dropdown.Menu>
|
|
188
|
-
</Dropdown>
|
|
189
|
-
|
|
190
|
-
<output className="mt-4 text-sm text-black" data-testid="output">
|
|
191
|
-
{message}
|
|
192
|
-
</output>
|
|
193
|
-
</div>
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
NoOutlineOnTrigger.args = {
|
|
198
|
-
disabled: false,
|
|
148
|
+
outlined: true,
|
|
199
149
|
}
|
|
200
150
|
|
|
201
151
|
function ActionTrigger() {
|
|
@@ -235,12 +185,12 @@ function InputTrigger() {
|
|
|
235
185
|
)
|
|
236
186
|
}
|
|
237
187
|
|
|
238
|
-
export const CustomTrigger: Story<
|
|
188
|
+
export const CustomTrigger: Story<DropdownStoryProps> = (args: DropdownStoryProps) => {
|
|
239
189
|
const [message, setMessage] = useState('')
|
|
240
190
|
|
|
241
191
|
function renderMenu() {
|
|
242
192
|
return (
|
|
243
|
-
<Dropdown.Menu>
|
|
193
|
+
<Dropdown.Menu align={args.align}>
|
|
244
194
|
{ACTIONS.map(({ label, value }) => (
|
|
245
195
|
<Dropdown.Item
|
|
246
196
|
key={value}
|
|
@@ -259,7 +209,7 @@ export const CustomTrigger: Story<DropdownProps> = (args: DropdownProps) => {
|
|
|
259
209
|
<div className="flex flex-col">
|
|
260
210
|
<div className="flex flex-row">
|
|
261
211
|
<Dropdown {...args}>
|
|
262
|
-
<Dropdown.Trigger.Button trailing={null}>
|
|
212
|
+
<Dropdown.Trigger.Button outlined={args.outlined} trailing={null}>
|
|
263
213
|
{({ expanded }) => {
|
|
264
214
|
return (
|
|
265
215
|
<React.Fragment>
|
|
@@ -291,4 +241,5 @@ export const CustomTrigger: Story<DropdownProps> = (args: DropdownProps) => {
|
|
|
291
241
|
|
|
292
242
|
CustomTrigger.args = {
|
|
293
243
|
disabled: false,
|
|
244
|
+
outlined: true,
|
|
294
245
|
}
|
|
@@ -43,15 +43,18 @@ export function GenericDropdown(props: GenericDropdownProps): JSX.Element {
|
|
|
43
43
|
const [contextValue, setContextValue] = useState({ expanded, toggle, disabled })
|
|
44
44
|
const ref = useRef(null)
|
|
45
45
|
|
|
46
|
-
useClickOutside(
|
|
47
|
-
|
|
46
|
+
useClickOutside(
|
|
47
|
+
ref,
|
|
48
|
+
function handleClickOutside(event?: MouseEvent | TouchEvent | KeyboardEvent) {
|
|
49
|
+
onBlur?.(event)
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (!expanded) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
toggle()
|
|
56
|
+
}
|
|
57
|
+
)
|
|
55
58
|
|
|
56
59
|
useEffect(
|
|
57
60
|
function updateContextValue() {
|
|
@@ -73,7 +76,7 @@ export function GenericDropdown(props: GenericDropdownProps): JSX.Element {
|
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
/**
|
|
76
|
-
* @example
|
|
79
|
+
* @example
|
|
77
80
|
<Dropdown>
|
|
78
81
|
<Dropdown.Trigger>Download</Dropdown.Trigger>
|
|
79
82
|
<Dropdown.Menu
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react'
|
|
2
1
|
import type { ButtonProps } from 'components/Button'
|
|
2
|
+
import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react'
|
|
3
3
|
|
|
4
4
|
export interface useDropdownProps {
|
|
5
5
|
expanded: boolean
|
|
@@ -15,7 +15,7 @@ export interface useDropdownReturn {
|
|
|
15
15
|
|
|
16
16
|
export interface DropdownProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onBlur'> {
|
|
17
17
|
disabled?: boolean
|
|
18
|
-
onBlur?: () => void
|
|
18
|
+
onBlur?: (event?: MouseEvent | TouchEvent | KeyboardEvent) => void
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface GenericDropdownProps extends DropdownProps, useDropdownProps {}
|
|
@@ -228,7 +228,7 @@ const RotatableIcon = styled(DefaultIcon)<{ $rotate: boolean }>`
|
|
|
228
228
|
})}
|
|
229
229
|
`
|
|
230
230
|
|
|
231
|
-
interface DropdownTriggerButtonProps extends DropdownTriggerProps {
|
|
231
|
+
export interface DropdownTriggerButtonProps extends DropdownTriggerProps {
|
|
232
232
|
children: DropdownTriggerProps['children'] | ((args: DropdownContextReturn) => React.ReactNode)
|
|
233
233
|
}
|
|
234
234
|
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
export interface DropdownProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onBlur'> {
|
|
6
|
-
disabled?: boolean
|
|
7
|
-
onBlur?: () => void
|
|
8
|
-
}
|
|
3
|
+
import type { DropdownProps } from './Dropdown.types'
|
|
9
4
|
|
|
10
5
|
export interface useDropdownProps {
|
|
11
6
|
expanded: boolean
|
|
@@ -19,6 +19,7 @@ import SortDescIcon from './assets/sort-desc.svg'
|
|
|
19
19
|
import SortIcon from './assets/sort.svg'
|
|
20
20
|
import UploadIcon from './assets/upload.svg'
|
|
21
21
|
import WarningIcon from './assets/warning.svg'
|
|
22
|
+
import DotsHorizontalIcon from './assets/dots-horizontal.svg'
|
|
22
23
|
|
|
23
24
|
import type { IconProps as GenericIconProps } from '../IconFactory'
|
|
24
25
|
|
|
@@ -42,6 +43,7 @@ const icons = {
|
|
|
42
43
|
'sort-desc': SortDescIcon as JSX.Element,
|
|
43
44
|
upload: UploadIcon as JSX.Element,
|
|
44
45
|
warning: WarningIcon as JSX.Element,
|
|
46
|
+
'dots-horizontal': DotsHorizontalIcon as JSX.Element,
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
const Icon = IconFactory(icons)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><path d="M14 24a5 5 0 11-10 0 5 5 0 0110 0zm15 0a5 5 0 11-10 0 5 5 0 0110 0zm15 0a5 5 0 11-10 0 5 5 0 0110 0z" fill="currentColor" fill-rule="evenodd"/></svg>
|
|
@@ -11,6 +11,7 @@ import selectEvent from '../../testing/SelectEvent'
|
|
|
11
11
|
|
|
12
12
|
import type { SelectProps, Option, GenericOption } from './Select.types'
|
|
13
13
|
import Select from './Select'
|
|
14
|
+
import userEvent from '@testing-library/user-event'
|
|
14
15
|
|
|
15
16
|
const {
|
|
16
17
|
Playground,
|
|
@@ -159,6 +160,27 @@ describe('Select', () => {
|
|
|
159
160
|
expect(items.length).toBeGreaterThanOrEqual(1)
|
|
160
161
|
expect(items[0]).toHaveTextContent(FRUITS[indexToSearch].label)
|
|
161
162
|
})
|
|
163
|
+
|
|
164
|
+
it('calls blur when focus is lost', async () => {
|
|
165
|
+
const onBlur = jest.fn((event?: MouseEvent | TouchEvent | KeyboardEvent) => event)
|
|
166
|
+
|
|
167
|
+
setup({ onBlur })
|
|
168
|
+
|
|
169
|
+
const selectInput = screen.getByLabelText('Select your favorite fruit')
|
|
170
|
+
|
|
171
|
+
await selectEvent.expand(selectInput)
|
|
172
|
+
|
|
173
|
+
userEvent.click(document.body)
|
|
174
|
+
|
|
175
|
+
await selectEvent.expand(selectInput)
|
|
176
|
+
|
|
177
|
+
userEvent.keyboard('{Escape}{/Escape}')
|
|
178
|
+
|
|
179
|
+
expect(onBlur).toHaveBeenCalledTimes(2)
|
|
180
|
+
|
|
181
|
+
expect(onBlur).toHaveBeenNthCalledWith(1, new MouseEvent('mousedown'))
|
|
182
|
+
expect(onBlur).toHaveBeenNthCalledWith(2, new KeyboardEvent('keyup'))
|
|
183
|
+
})
|
|
162
184
|
})
|
|
163
185
|
|
|
164
186
|
describe('Single selection', () => {
|
|
@@ -839,7 +861,7 @@ describe('Select', () => {
|
|
|
839
861
|
const setup = (overrides: Partial<SelectProps>) =>
|
|
840
862
|
renderer(<Playground {...overrides} options={SelectableKeyTypeOptions} />).render()
|
|
841
863
|
|
|
842
|
-
const expectedValue = (value:
|
|
864
|
+
const expectedValue = (value: unknown) => ({
|
|
843
865
|
target: {
|
|
844
866
|
id: 'select-playground',
|
|
845
867
|
name: 'select-playground',
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import EventLike from 'utils/types/EventLike'
|
|
3
3
|
|
|
4
|
-
import type {
|
|
5
|
-
import type { DropdownProps, DropdownMenuItemProps } from 'components/Dropdown'
|
|
4
|
+
import type { DropdownMenuItemProps, DropdownProps } from 'components/Dropdown'
|
|
6
5
|
import type { TextFieldProps } from 'components/TextField'
|
|
7
6
|
import type {
|
|
8
|
-
SelectableAdapter,
|
|
9
7
|
Selectable,
|
|
8
|
+
SelectableAdapter,
|
|
10
9
|
SelectableKeyType,
|
|
11
10
|
SelectableState,
|
|
12
11
|
} from 'hooks/useSelectable'
|
|
13
12
|
import { useSelectableReturn } from 'hooks/useSelectable/useSelectable.types'
|
|
13
|
+
import type { ChangeEvent, ComponentType, FocusEvent, HTMLAttributes } from 'react'
|
|
14
14
|
|
|
15
15
|
export type Option = Selectable
|
|
16
16
|
export interface GenericOption {
|
|
@@ -119,7 +119,7 @@ export type useSelectReturn = {
|
|
|
119
119
|
getDropdownProps: () => {
|
|
120
120
|
toggle: () => void
|
|
121
121
|
expanded: boolean
|
|
122
|
-
onBlur: () => void
|
|
122
|
+
onBlur: (event?: MouseEvent | TouchEvent | KeyboardEvent) => void
|
|
123
123
|
}
|
|
124
124
|
getCreatebleProps: () => CreatableProps
|
|
125
125
|
isCreatable: () => boolean
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
3
2
|
import { isFunction } from '@loadsmart/utils-function'
|
|
4
3
|
import { isNil } from '@loadsmart/utils-object'
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
5
5
|
|
|
6
|
-
import { GenericAdapter } from './Select.constants'
|
|
7
|
-
import { getValue, getDisplayValue, escapeRegExp, getAdapter } from './useSelect.helpers'
|
|
8
6
|
import { useDropdown } from 'components/Dropdown'
|
|
7
|
+
import { useDidMount } from 'hooks/useDidMount'
|
|
9
8
|
import { useFocusTrap } from 'hooks/useFocusTrap'
|
|
10
9
|
import { SelectableKeyType } from 'hooks/useSelectable'
|
|
11
|
-
import { useSelectable } from './Select.context'
|
|
12
10
|
import to from 'utils/toolset/awaitTo'
|
|
13
|
-
import toArray from 'utils/toolset/toArray'
|
|
14
11
|
import { isThenable } from 'utils/toolset/isThenable'
|
|
15
|
-
import
|
|
12
|
+
import toArray from 'utils/toolset/toArray'
|
|
13
|
+
import { GenericAdapter } from './Select.constants'
|
|
14
|
+
import { useSelectable } from './Select.context'
|
|
15
|
+
import { escapeRegExp, getAdapter, getDisplayValue, getValue } from './useSelect.helpers'
|
|
16
16
|
|
|
17
17
|
import type { ChangeEvent, FocusEvent } from 'react'
|
|
18
18
|
import type {
|
|
@@ -191,7 +191,7 @@ function useOptions<T = any>(props: { datasources: SelectDatasource<T>[]; adapte
|
|
|
191
191
|
*/
|
|
192
192
|
function useSelect(props: SelectProps): useSelectReturn {
|
|
193
193
|
const didMount = useDidMount()
|
|
194
|
-
const { multiple, onQueryChange, onChange, onCreate, id, name, disabled = false } = props
|
|
194
|
+
const { multiple, onQueryChange, onChange, onCreate, id, name, disabled = false, onBlur } = props
|
|
195
195
|
const dropdown = useDropdown(props)
|
|
196
196
|
|
|
197
197
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -264,17 +264,19 @@ function useSelect(props: SelectProps): useSelectReturn {
|
|
|
264
264
|
return {
|
|
265
265
|
toggle: dropdown.toggle,
|
|
266
266
|
expanded: dropdown.expanded,
|
|
267
|
-
onBlur() {
|
|
267
|
+
onBlur(event?: MouseEvent | TouchEvent | KeyboardEvent) {
|
|
268
268
|
if (!multiple) {
|
|
269
269
|
setQuery(getDisplayValue(adapters, selectable.selected, multiple))
|
|
270
270
|
} else {
|
|
271
271
|
setQuery('')
|
|
272
272
|
}
|
|
273
273
|
options.reset()
|
|
274
|
+
|
|
275
|
+
onBlur?.(event)
|
|
274
276
|
},
|
|
275
277
|
}
|
|
276
278
|
},
|
|
277
|
-
[adapters, dropdown.expanded, dropdown.toggle, multiple, options, selectable.selected]
|
|
279
|
+
[adapters, dropdown.expanded, dropdown.toggle, multiple, options, selectable.selected, onBlur]
|
|
278
280
|
)
|
|
279
281
|
|
|
280
282
|
const getTriggerProps = useCallback(
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import generator from '../../../tests/generator'
|
|
2
2
|
|
|
3
3
|
export const TABLE_COLUMNS = [
|
|
4
|
+
{
|
|
5
|
+
key: 'ref',
|
|
6
|
+
title: 'Reference',
|
|
7
|
+
},
|
|
4
8
|
{
|
|
5
9
|
key: 'product',
|
|
6
10
|
title: 'Product',
|
|
@@ -24,34 +28,40 @@ export const TABLE_COLUMNS = [
|
|
|
24
28
|
export const TABLE_ROWS = [
|
|
25
29
|
{
|
|
26
30
|
value: 1,
|
|
27
|
-
[TABLE_COLUMNS[0].key]: generator.word({
|
|
28
|
-
[TABLE_COLUMNS[1].key]: generator.
|
|
29
|
-
[TABLE_COLUMNS[2].key]: generator.
|
|
30
|
-
[TABLE_COLUMNS[3].key]: generator.
|
|
31
|
+
[TABLE_COLUMNS[0].key]: btoa(generator.word({ length: 5 })),
|
|
32
|
+
[TABLE_COLUMNS[1].key]: generator.word({ capitalize: true, length: 10 }),
|
|
33
|
+
[TABLE_COLUMNS[2].key]: generator.natural({ max: 10_000 }),
|
|
34
|
+
[TABLE_COLUMNS[3].key]: generator.date(),
|
|
35
|
+
[TABLE_COLUMNS[4].key]: generator.name(),
|
|
31
36
|
},
|
|
32
37
|
{
|
|
33
38
|
value: 2,
|
|
34
|
-
[TABLE_COLUMNS[0].key]: generator.word({
|
|
35
|
-
[TABLE_COLUMNS[1].key]: generator.
|
|
36
|
-
[TABLE_COLUMNS[2].key]: generator.
|
|
37
|
-
[TABLE_COLUMNS[3].key]: generator.
|
|
39
|
+
[TABLE_COLUMNS[0].key]: btoa(generator.word({ length: 5 })),
|
|
40
|
+
[TABLE_COLUMNS[1].key]: generator.word({ capitalize: true, length: 10 }),
|
|
41
|
+
[TABLE_COLUMNS[2].key]: generator.natural({ max: 10_000 }),
|
|
42
|
+
[TABLE_COLUMNS[3].key]: generator.date(),
|
|
43
|
+
[TABLE_COLUMNS[4].key]: generator.name(),
|
|
38
44
|
},
|
|
39
45
|
{
|
|
40
46
|
value: 3,
|
|
41
|
-
[TABLE_COLUMNS[0].key]: generator.word({
|
|
42
|
-
[TABLE_COLUMNS[1].key]: generator.
|
|
43
|
-
[TABLE_COLUMNS[2].key]: generator.
|
|
44
|
-
[TABLE_COLUMNS[3].key]: generator.
|
|
47
|
+
[TABLE_COLUMNS[0].key]: btoa(generator.word({ length: 5 })),
|
|
48
|
+
[TABLE_COLUMNS[1].key]: generator.word({ capitalize: true, length: 10 }),
|
|
49
|
+
[TABLE_COLUMNS[2].key]: generator.natural({ max: 10_000 }),
|
|
50
|
+
[TABLE_COLUMNS[3].key]: generator.date(),
|
|
51
|
+
[TABLE_COLUMNS[4].key]: generator.name(),
|
|
45
52
|
},
|
|
46
53
|
{
|
|
47
54
|
value: 4,
|
|
48
|
-
[TABLE_COLUMNS[0].key]: generator.word({
|
|
49
|
-
[TABLE_COLUMNS[1].key]: generator.
|
|
50
|
-
[TABLE_COLUMNS[2].key]: generator.
|
|
51
|
-
[TABLE_COLUMNS[3].key]: generator.
|
|
55
|
+
[TABLE_COLUMNS[0].key]: btoa(generator.word({ length: 5 })),
|
|
56
|
+
[TABLE_COLUMNS[1].key]: generator.word({ capitalize: true, length: 10 }),
|
|
57
|
+
[TABLE_COLUMNS[2].key]: generator.natural({ max: 10_000 }),
|
|
58
|
+
[TABLE_COLUMNS[3].key]: generator.date(),
|
|
59
|
+
[TABLE_COLUMNS[4].key]: generator.name(),
|
|
52
60
|
},
|
|
53
61
|
]
|
|
54
62
|
|
|
63
|
+
export type RowFixture = typeof TABLE_ROWS[number]
|
|
64
|
+
|
|
55
65
|
export const TEST_TABLE_COLUMNS = [
|
|
56
66
|
{
|
|
57
67
|
key: 'name',
|