@charcoal-ui/react 6.1.0-beta.0 → 6.1.0-beta.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/dist/components/Notification/NotificationItem.cjs +30 -0
- package/dist/components/Notification/NotificationItem.cjs.map +1 -0
- package/dist/components/Notification/NotificationItem.d.ts +15 -0
- package/dist/components/Notification/NotificationItem.d.ts.map +1 -0
- package/dist/components/Notification/NotificationItem.js +30 -0
- package/dist/components/Notification/NotificationItem.js.map +1 -0
- package/dist/components/Notification/NotificationRegion.cjs +50 -0
- package/dist/components/Notification/NotificationRegion.cjs.map +1 -0
- package/dist/components/Notification/NotificationRegion.d.ts +14 -0
- package/dist/components/Notification/NotificationRegion.d.ts.map +1 -0
- package/dist/components/Notification/NotificationRegion.js +50 -0
- package/dist/components/Notification/NotificationRegion.js.map +1 -0
- package/dist/components/Notification/Snackbar/index.d.ts +45 -0
- package/dist/components/Notification/Snackbar/index.d.ts.map +1 -0
- package/dist/components/Notification/Snackbar/index2.cjs +99 -0
- package/dist/components/Notification/Snackbar/index2.cjs.map +1 -0
- package/dist/components/Notification/Snackbar/index2.js +94 -0
- package/dist/components/Notification/Snackbar/index2.js.map +1 -0
- package/dist/components/Notification/Toast/index.d.ts +28 -0
- package/dist/components/Notification/Toast/index.d.ts.map +1 -0
- package/dist/components/Notification/Toast/index2.cjs +86 -0
- package/dist/components/Notification/Toast/index2.cjs.map +1 -0
- package/dist/components/Notification/Toast/index2.js +81 -0
- package/dist/components/Notification/Toast/index2.js.map +1 -0
- package/dist/components/Notification/types.d.ts +27 -0
- package/dist/components/Notification/types.d.ts.map +1 -0
- package/dist/components/Notification/useNotificationQueue.cjs +155 -0
- package/dist/components/Notification/useNotificationQueue.cjs.map +1 -0
- package/dist/components/Notification/useNotificationQueue.d.ts +16 -0
- package/dist/components/Notification/useNotificationQueue.d.ts.map +1 -0
- package/dist/components/Notification/useNotificationQueue.js +155 -0
- package/dist/components/Notification/useNotificationQueue.js.map +1 -0
- package/dist/index.cjs +4 -1
- package/dist/index.css +1315 -1250
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/layered.css +1315 -1250
- package/dist/layered.css.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/css-output.test.ts +39 -6
- package/src/components/Notification/NotificationItem.tsx +51 -0
- package/src/components/Notification/NotificationRegion.tsx +76 -0
- package/src/components/{Snackbar → Notification/Snackbar}/__snapshots__/index.css.snap +1 -42
- package/src/components/{Snackbar → Notification/Snackbar}/index.css +1 -43
- package/src/components/{Snackbar → Notification/Snackbar}/index.story.tsx +52 -23
- package/src/components/{Snackbar → Notification/Snackbar}/index.test.tsx +61 -11
- package/src/components/Notification/Snackbar/index.tsx +131 -0
- package/src/components/Notification/Toast/__snapshots__/index.css.snap +62 -0
- package/src/components/Notification/Toast/index.css +61 -0
- package/src/components/Notification/Toast/index.story.tsx +174 -0
- package/src/components/Notification/Toast/index.test.tsx +263 -0
- package/src/components/Notification/Toast/index.tsx +86 -0
- package/src/components/Notification/__snapshots__/layout.css.snap +47 -0
- package/src/components/Notification/layout.css +46 -0
- package/src/components/Notification/types.ts +28 -0
- package/src/components/Notification/useNotificationQueue.ts +235 -0
- package/src/index.ts +14 -2
- package/dist/components/Snackbar/index.d.ts +0 -52
- package/dist/components/Snackbar/index.d.ts.map +0 -1
- package/dist/components/Snackbar/index2.cjs +0 -268
- package/dist/components/Snackbar/index2.cjs.map +0 -1
- package/dist/components/Snackbar/index2.js +0 -263
- package/dist/components/Snackbar/index2.js.map +0 -1
- package/src/components/Snackbar/index.tsx +0 -455
|
@@ -1,455 +0,0 @@
|
|
|
1
|
-
import './index.css'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
forwardRef,
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect,
|
|
7
|
-
useImperativeHandle,
|
|
8
|
-
useRef,
|
|
9
|
-
} from 'react'
|
|
10
|
-
import type { ElementType, ReactNode, RefObject } from 'react'
|
|
11
|
-
import { Overlay } from 'react-aria/Overlay'
|
|
12
|
-
import { useToast, useToastRegion } from 'react-aria/useToast'
|
|
13
|
-
import {
|
|
14
|
-
useToastState,
|
|
15
|
-
type QueuedToast,
|
|
16
|
-
type ToastState,
|
|
17
|
-
} from 'react-stately/useToastState'
|
|
18
|
-
import { useClassNames } from '../../_lib/useClassNames'
|
|
19
|
-
import Button, { type ButtonProps } from '../Button'
|
|
20
|
-
|
|
21
|
-
const DEFAULT_DURATION_MS = 5000
|
|
22
|
-
const DEFAULT_Z_INDEX = 20
|
|
23
|
-
const ENTER_ANIMATION_DURATION_MS = 300
|
|
24
|
-
const EXIT_ANIMATION_DURATION_MS = 300
|
|
25
|
-
|
|
26
|
-
type SnackbarPosition = 'top' | 'bottom'
|
|
27
|
-
|
|
28
|
-
type SnackbarButtonOption<T extends ElementType = 'button'> = Omit<
|
|
29
|
-
ButtonProps<T>,
|
|
30
|
-
'component' | 'className' | 'size'
|
|
31
|
-
> & {
|
|
32
|
-
/**
|
|
33
|
-
* ボタンのルート要素として使用するコンポーネント。ページ遷移を伴う場合は `Link` を指定する
|
|
34
|
-
* @default 'button'
|
|
35
|
-
* @example 'Link'
|
|
36
|
-
*/
|
|
37
|
-
component?: T
|
|
38
|
-
} & ('button' extends T ? unknown : { component: T })
|
|
39
|
-
|
|
40
|
-
export type SnackbarShowOptions<T extends ElementType = 'button'> = {
|
|
41
|
-
/**
|
|
42
|
-
* Snackbar を表示する時間(ミリ秒)。負の値は 0、数値でない値は 5000 として扱う
|
|
43
|
-
* @default 5000
|
|
44
|
-
*/
|
|
45
|
-
duration?: number
|
|
46
|
-
/**
|
|
47
|
-
* Snackbar の右側に表示するボタン
|
|
48
|
-
*/
|
|
49
|
-
button?: SnackbarButtonOption<T>
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type SnackbarHandler = {
|
|
53
|
-
show: <T extends ElementType = 'button'>(
|
|
54
|
-
message: ReactNode,
|
|
55
|
-
options?: SnackbarShowOptions<T>,
|
|
56
|
-
) => void
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export type SnackbarProps = {
|
|
60
|
-
/**
|
|
61
|
-
* Snackbar の表示位置。ボタン付きの場合は `bottom` に固定される
|
|
62
|
-
* @default 'bottom'
|
|
63
|
-
*/
|
|
64
|
-
position?: SnackbarPosition
|
|
65
|
-
/**
|
|
66
|
-
* 画面端からの距離(ピクセル)
|
|
67
|
-
* @default 16
|
|
68
|
-
*/
|
|
69
|
-
offset?: number
|
|
70
|
-
/**
|
|
71
|
-
* 暗い背景色
|
|
72
|
-
* @default false
|
|
73
|
-
*/
|
|
74
|
-
dim?: boolean
|
|
75
|
-
zIndex?: number
|
|
76
|
-
portalContainer?: HTMLElement
|
|
77
|
-
className?: string
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
type SnackbarContent = {
|
|
81
|
-
message: ReactNode
|
|
82
|
-
button?: SnackbarButtonContent
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
type QueuedSnackbar = SnackbarContent & {
|
|
86
|
-
duration: number
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
type SnackbarButtonContent = Omit<SnackbarButtonOption, 'component'> & {
|
|
90
|
-
component?: ElementType
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const Snackbar = forwardRef<SnackbarHandler, SnackbarProps>(function Snackbar(
|
|
94
|
-
{
|
|
95
|
-
position = 'bottom',
|
|
96
|
-
offset = 16,
|
|
97
|
-
dim = false,
|
|
98
|
-
zIndex = DEFAULT_Z_INDEX,
|
|
99
|
-
portalContainer,
|
|
100
|
-
className,
|
|
101
|
-
},
|
|
102
|
-
ref,
|
|
103
|
-
) {
|
|
104
|
-
'use memo'
|
|
105
|
-
|
|
106
|
-
const snackbarRef = useRef<HTMLDivElement>(null)
|
|
107
|
-
const queueRef = useRef<QueuedSnackbar[]>([])
|
|
108
|
-
const isShowingRef = useRef(false)
|
|
109
|
-
const hoverRef = useRef({
|
|
110
|
-
active: false,
|
|
111
|
-
pending: undefined as (() => void) | undefined,
|
|
112
|
-
})
|
|
113
|
-
// wrapUpdate を固定したまま、後から定義する playNext の最新版を呼ぶ
|
|
114
|
-
const playNextRef = useRef<(() => void) | undefined>(undefined)
|
|
115
|
-
|
|
116
|
-
// wrapUpdate の参照が変わると useToastState が ToastQueue を作り直すため useCallback で固定する
|
|
117
|
-
const wrapToastUpdate = useCallback(function wrapToastUpdate(
|
|
118
|
-
update: () => void,
|
|
119
|
-
action: 'add' | 'remove' | 'clear',
|
|
120
|
-
) {
|
|
121
|
-
if (action !== 'remove') {
|
|
122
|
-
update()
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function finish() {
|
|
127
|
-
update()
|
|
128
|
-
playNextRef.current?.()
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (hoverRef.current.active) {
|
|
132
|
-
hoverRef.current.pending = () => wrapToastUpdate(update, 'remove')
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (snackbarRef.current === null) {
|
|
137
|
-
finish()
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
const snackbar: HTMLDivElement = snackbarRef.current
|
|
141
|
-
|
|
142
|
-
// allow-discreteが Newly Available で使えないので、要素の削除をアニメーション完了まで待つ
|
|
143
|
-
snackbar.dataset.exiting = 'true'
|
|
144
|
-
let completed = false
|
|
145
|
-
let fallbackTimer = 0 // complete 内で clearTimeout(setTimeout(...)) すると新規タイマーを即キャンセルしてしまう
|
|
146
|
-
function handleAnimationEnd(event: AnimationEvent) {
|
|
147
|
-
if (
|
|
148
|
-
event.target === snackbar &&
|
|
149
|
-
event.animationName === 'charcoal-snackbar-exit'
|
|
150
|
-
) {
|
|
151
|
-
complete()
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
function complete() {
|
|
155
|
-
if (completed) return
|
|
156
|
-
completed = true
|
|
157
|
-
snackbar.removeEventListener('animationend', handleAnimationEnd)
|
|
158
|
-
window.clearTimeout(fallbackTimer)
|
|
159
|
-
finish()
|
|
160
|
-
}
|
|
161
|
-
snackbar.addEventListener('animationend', handleAnimationEnd)
|
|
162
|
-
fallbackTimer = window.setTimeout(
|
|
163
|
-
complete,
|
|
164
|
-
EXIT_ANIMATION_DURATION_MS + 100,
|
|
165
|
-
)
|
|
166
|
-
if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {
|
|
167
|
-
complete()
|
|
168
|
-
}
|
|
169
|
-
}, [])
|
|
170
|
-
|
|
171
|
-
const state = useToastState<SnackbarContent>({
|
|
172
|
-
maxVisibleToasts: 1,
|
|
173
|
-
wrapUpdate: wrapToastUpdate,
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
useEffect(() => {
|
|
177
|
-
return () => {
|
|
178
|
-
queueRef.current = []
|
|
179
|
-
isShowingRef.current = false
|
|
180
|
-
}
|
|
181
|
-
}, [])
|
|
182
|
-
|
|
183
|
-
function playNext() {
|
|
184
|
-
const next = queueRef.current.shift()
|
|
185
|
-
if (next === undefined) {
|
|
186
|
-
isShowingRef.current = false
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const { duration, ...content } = next
|
|
191
|
-
isShowingRef.current = true
|
|
192
|
-
const enterMs = window.matchMedia?.('(prefers-reduced-motion: reduce)')
|
|
193
|
-
.matches
|
|
194
|
-
? 0
|
|
195
|
-
: ENTER_ANIMATION_DURATION_MS
|
|
196
|
-
state.add(content, {
|
|
197
|
-
// react-stately は 0 を「タイマーなし」と扱うため、最小の正数を渡す
|
|
198
|
-
timeout: Math.max(1, duration + enterMs),
|
|
199
|
-
})
|
|
200
|
-
}
|
|
201
|
-
playNextRef.current = playNext
|
|
202
|
-
|
|
203
|
-
function show<T extends ElementType = 'button'>(
|
|
204
|
-
message: ReactNode,
|
|
205
|
-
options: SnackbarShowOptions<T> = {},
|
|
206
|
-
) {
|
|
207
|
-
const { duration: durationOption = DEFAULT_DURATION_MS, button } = options
|
|
208
|
-
const duration =
|
|
209
|
-
typeof durationOption === 'number' && Number.isFinite(durationOption)
|
|
210
|
-
? Math.max(0, durationOption)
|
|
211
|
-
: DEFAULT_DURATION_MS
|
|
212
|
-
|
|
213
|
-
queueRef.current.push({
|
|
214
|
-
message,
|
|
215
|
-
button: button as SnackbarButtonContent | undefined,
|
|
216
|
-
duration,
|
|
217
|
-
})
|
|
218
|
-
if (!isShowingRef.current) {
|
|
219
|
-
playNext()
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
useImperativeHandle(ref, () => ({ show }))
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<SnackbarRegion
|
|
227
|
-
state={state}
|
|
228
|
-
position={position}
|
|
229
|
-
offset={offset}
|
|
230
|
-
dim={dim}
|
|
231
|
-
zIndex={zIndex}
|
|
232
|
-
portalContainer={portalContainer}
|
|
233
|
-
className={className}
|
|
234
|
-
snackbarRef={snackbarRef}
|
|
235
|
-
onHoverStart={() => {
|
|
236
|
-
hoverRef.current.active = true
|
|
237
|
-
}}
|
|
238
|
-
onHoverEnd={() => {
|
|
239
|
-
hoverRef.current.active = false
|
|
240
|
-
const pending = hoverRef.current.pending
|
|
241
|
-
hoverRef.current.pending = undefined
|
|
242
|
-
pending?.()
|
|
243
|
-
}}
|
|
244
|
-
onActionClose={() => {
|
|
245
|
-
hoverRef.current.active = false
|
|
246
|
-
hoverRef.current.pending = undefined
|
|
247
|
-
}}
|
|
248
|
-
/>
|
|
249
|
-
)
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
export default Snackbar
|
|
253
|
-
|
|
254
|
-
export function useSnackbar(props: SnackbarProps = {}) {
|
|
255
|
-
'use memo'
|
|
256
|
-
|
|
257
|
-
const { position, offset, dim, zIndex, portalContainer, className } = props
|
|
258
|
-
const snackbarHandlerRef = useRef<SnackbarHandler>(null)
|
|
259
|
-
const element = (
|
|
260
|
-
<Snackbar
|
|
261
|
-
ref={snackbarHandlerRef}
|
|
262
|
-
position={position}
|
|
263
|
-
offset={offset}
|
|
264
|
-
dim={dim}
|
|
265
|
-
zIndex={zIndex}
|
|
266
|
-
portalContainer={portalContainer}
|
|
267
|
-
className={className}
|
|
268
|
-
/>
|
|
269
|
-
)
|
|
270
|
-
function show<T extends ElementType = 'button'>(
|
|
271
|
-
message: ReactNode,
|
|
272
|
-
options?: SnackbarShowOptions<T>,
|
|
273
|
-
) {
|
|
274
|
-
snackbarHandlerRef.current?.show(message, options)
|
|
275
|
-
}
|
|
276
|
-
return [element, show] as const
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function SnackbarRegion({
|
|
280
|
-
state,
|
|
281
|
-
position,
|
|
282
|
-
offset,
|
|
283
|
-
dim,
|
|
284
|
-
zIndex,
|
|
285
|
-
portalContainer,
|
|
286
|
-
className,
|
|
287
|
-
snackbarRef,
|
|
288
|
-
onHoverStart,
|
|
289
|
-
onHoverEnd,
|
|
290
|
-
onActionClose,
|
|
291
|
-
}: {
|
|
292
|
-
state: ToastState<SnackbarContent>
|
|
293
|
-
position: SnackbarPosition
|
|
294
|
-
offset: number
|
|
295
|
-
dim: boolean
|
|
296
|
-
zIndex: number
|
|
297
|
-
portalContainer?: HTMLElement
|
|
298
|
-
className?: string
|
|
299
|
-
snackbarRef: RefObject<HTMLDivElement>
|
|
300
|
-
onHoverStart: () => void
|
|
301
|
-
onHoverEnd: () => void
|
|
302
|
-
onActionClose: () => void
|
|
303
|
-
}) {
|
|
304
|
-
const regionRef = useRef<HTMLDivElement>(null)
|
|
305
|
-
const pausedByFocusRef = useRef(false)
|
|
306
|
-
const timerState: ToastState<SnackbarContent> = {
|
|
307
|
-
...state,
|
|
308
|
-
pauseAll() {
|
|
309
|
-
if (regionRef.current?.contains(document.activeElement)) {
|
|
310
|
-
pausedByFocusRef.current = true
|
|
311
|
-
state.pauseAll()
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
resumeAll() {
|
|
315
|
-
if (pausedByFocusRef.current) {
|
|
316
|
-
pausedByFocusRef.current = false
|
|
317
|
-
state.resumeAll()
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
}
|
|
321
|
-
const { regionProps } = useToastRegion({}, timerState, regionRef)
|
|
322
|
-
const classNames = useClassNames('charcoal-snackbar-region', className)
|
|
323
|
-
|
|
324
|
-
if (state.visibleToasts.length === 0) {
|
|
325
|
-
return null
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// ボタン付きの Snackbar は常に下部に表示される
|
|
329
|
-
const hasButton = state.visibleToasts.some(
|
|
330
|
-
(toast) => toast.content.button !== undefined,
|
|
331
|
-
)
|
|
332
|
-
const effectivePosition = hasButton ? 'bottom' : position
|
|
333
|
-
|
|
334
|
-
return (
|
|
335
|
-
<Overlay disableFocusManagement portalContainer={portalContainer}>
|
|
336
|
-
<div
|
|
337
|
-
{...regionProps}
|
|
338
|
-
ref={regionRef}
|
|
339
|
-
className={classNames}
|
|
340
|
-
data-position={effectivePosition}
|
|
341
|
-
style={{
|
|
342
|
-
zIndex,
|
|
343
|
-
'--charcoal-snackbar-offset': `${offset}px`,
|
|
344
|
-
}}
|
|
345
|
-
>
|
|
346
|
-
{state.visibleToasts.map((toast) => (
|
|
347
|
-
<SnackbarItem
|
|
348
|
-
key={toast.key}
|
|
349
|
-
toast={toast}
|
|
350
|
-
state={state}
|
|
351
|
-
dim={dim}
|
|
352
|
-
snackbarRef={snackbarRef}
|
|
353
|
-
onHoverStart={onHoverStart}
|
|
354
|
-
onHoverEnd={onHoverEnd}
|
|
355
|
-
onActionClose={() => {
|
|
356
|
-
onActionClose()
|
|
357
|
-
state.close(toast.key)
|
|
358
|
-
}}
|
|
359
|
-
/>
|
|
360
|
-
))}
|
|
361
|
-
</div>
|
|
362
|
-
</Overlay>
|
|
363
|
-
)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function SnackbarItem({
|
|
367
|
-
toast,
|
|
368
|
-
state,
|
|
369
|
-
dim,
|
|
370
|
-
snackbarRef,
|
|
371
|
-
onHoverStart,
|
|
372
|
-
onHoverEnd,
|
|
373
|
-
onActionClose,
|
|
374
|
-
}: {
|
|
375
|
-
toast: QueuedToast<SnackbarContent>
|
|
376
|
-
state: ToastState<SnackbarContent>
|
|
377
|
-
dim: boolean
|
|
378
|
-
snackbarRef: RefObject<HTMLDivElement>
|
|
379
|
-
onHoverStart: () => void
|
|
380
|
-
onHoverEnd: () => void
|
|
381
|
-
onActionClose: () => void
|
|
382
|
-
}) {
|
|
383
|
-
const { toastProps, contentProps, titleProps } = useToast(
|
|
384
|
-
{ toast },
|
|
385
|
-
state,
|
|
386
|
-
snackbarRef,
|
|
387
|
-
)
|
|
388
|
-
const { message, button } = toast.content
|
|
389
|
-
|
|
390
|
-
return (
|
|
391
|
-
<div
|
|
392
|
-
{...toastProps}
|
|
393
|
-
ref={snackbarRef}
|
|
394
|
-
className="charcoal-snackbar"
|
|
395
|
-
data-dim={dim}
|
|
396
|
-
data-with-button={button !== undefined}
|
|
397
|
-
onPointerEnter={onHoverStart}
|
|
398
|
-
onPointerLeave={onHoverEnd}
|
|
399
|
-
>
|
|
400
|
-
<div
|
|
401
|
-
{...contentProps}
|
|
402
|
-
role="status"
|
|
403
|
-
className="charcoal-snackbar-content"
|
|
404
|
-
>
|
|
405
|
-
<div {...titleProps} className="charcoal-snackbar-label">
|
|
406
|
-
{message}
|
|
407
|
-
</div>
|
|
408
|
-
</div>
|
|
409
|
-
{button !== undefined && (
|
|
410
|
-
<SnackbarAction button={button} dim={dim} onClose={onActionClose} />
|
|
411
|
-
)}
|
|
412
|
-
</div>
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function SnackbarAction({
|
|
417
|
-
button,
|
|
418
|
-
dim,
|
|
419
|
-
onClose,
|
|
420
|
-
}: {
|
|
421
|
-
button: SnackbarButtonContent
|
|
422
|
-
dim: boolean
|
|
423
|
-
onClose: () => void
|
|
424
|
-
}) {
|
|
425
|
-
const { onClick, variant, children: buttonChildren, ...buttonProps } = button
|
|
426
|
-
|
|
427
|
-
function handleButtonClick(
|
|
428
|
-
event: Parameters<NonNullable<ButtonProps<'button'>['onClick']>>[0],
|
|
429
|
-
) {
|
|
430
|
-
onClick?.(event)
|
|
431
|
-
onClose()
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
return (
|
|
435
|
-
<PolymorphicButton
|
|
436
|
-
{...buttonProps}
|
|
437
|
-
size="S"
|
|
438
|
-
variant={variant ?? (dim ? 'Navigation' : undefined)}
|
|
439
|
-
onClick={handleButtonClick}
|
|
440
|
-
>
|
|
441
|
-
{buttonChildren}
|
|
442
|
-
</PolymorphicButton>
|
|
443
|
-
)
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function PolymorphicButton({
|
|
447
|
-
component,
|
|
448
|
-
...props
|
|
449
|
-
}: Omit<ButtonProps, 'component'> & { component?: ElementType }) {
|
|
450
|
-
if (component === undefined || component === 'button') {
|
|
451
|
-
return <Button {...props} />
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return <Button {...props} component={component} />
|
|
455
|
-
}
|