@graphprotocol/gds-react 0.2.2 → 0.2.4
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/Address.d.ts +6 -4
- package/dist/components/Address.d.ts.map +1 -1
- package/dist/components/Address.js.map +1 -1
- package/dist/components/Avatar.d.ts +6 -4
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Breadcrumbs.parts.d.ts +6 -4
- package/dist/components/Breadcrumbs.parts.d.ts.map +1 -1
- package/dist/components/Breadcrumbs.parts.js.map +1 -1
- package/dist/components/Button.d.ts +6 -4
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Card.d.ts +3 -5
- package/dist/components/Card.d.ts.map +1 -1
- package/dist/components/Chip.parts.d.ts +10 -6
- package/dist/components/Chip.parts.d.ts.map +1 -1
- package/dist/components/Chip.parts.js.map +1 -1
- package/dist/components/Cluster.d.ts +3 -5
- package/dist/components/Cluster.d.ts.map +1 -1
- package/dist/components/Cluster.js.map +1 -1
- package/dist/components/Icon.d.ts +2 -1
- package/dist/components/Icon.d.ts.map +1 -1
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/Link.d.ts +7 -5
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js.map +1 -1
- package/dist/components/Menu.parts.d.ts +23 -15
- package/dist/components/Menu.parts.d.ts.map +1 -1
- package/dist/components/Menu.parts.js +112 -106
- package/dist/components/Menu.parts.js.map +1 -1
- package/dist/components/Modal.parts.d.ts.map +1 -1
- package/dist/components/Modal.parts.js +2 -2
- package/dist/components/Modal.parts.js.map +1 -1
- package/dist/components/Pane.parts.d.ts +3 -3
- package/dist/components/Pane.parts.d.ts.map +1 -1
- package/dist/components/Pane.parts.js +8 -5
- package/dist/components/Pane.parts.js.map +1 -1
- package/dist/components/Tooltip.parts.d.ts.map +1 -1
- package/dist/components/Tooltip.parts.js +7 -6
- package/dist/components/Tooltip.parts.js.map +1 -1
- package/dist/components/base/ButtonOrLink.parts.d.ts +3 -3
- package/dist/components/base/ButtonOrLink.parts.d.ts.map +1 -1
- package/dist/components/base/ButtonOrLink.parts.js +3 -3
- package/dist/components/base/ButtonOrLink.parts.js.map +1 -1
- package/dist/components/base/MaybeButtonOrLink.d.ts +2 -2
- package/dist/components/base/MaybeButtonOrLink.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js.map +1 -1
- package/package.json +17 -17
- package/src/components/Address.tsx +8 -4
- package/src/components/Avatar.tsx +5 -4
- package/src/components/Breadcrumbs.parts.tsx +5 -4
- package/src/components/Button.tsx +5 -4
- package/src/components/Card.tsx +4 -4
- package/src/components/Chip.parts.tsx +8 -7
- package/src/components/Cluster.tsx +6 -4
- package/src/components/Icon.tsx +3 -1
- package/src/components/Link.tsx +5 -5
- package/src/components/Menu.parts.tsx +59 -27
- package/src/components/Modal.parts.tsx +3 -2
- package/src/components/Pane.parts.tsx +16 -8
- package/src/components/Tooltip.parts.tsx +18 -15
- package/src/components/base/ButtonOrLink.parts.tsx +9 -12
- package/src/components/base/MaybeButtonOrLink.tsx +2 -2
- package/src/components/index.ts +1 -1
|
@@ -17,7 +17,7 @@ import { ChipGroupMeta, ChipMeta } from './Chip.meta.ts'
|
|
|
17
17
|
type ExtractFn<T> = T extends (...args: infer A) => infer R ? (...args: A) => R : never
|
|
18
18
|
|
|
19
19
|
export declare namespace ChipProps {
|
|
20
|
-
interface
|
|
20
|
+
interface OwnProps {
|
|
21
21
|
/** Name used to submit the chip's value when inside a `<Chip.Group type="checkbox">` in a form. */
|
|
22
22
|
name?: string | undefined
|
|
23
23
|
/** Value used to identify this chip when inside a `<Chip.Group>`. */
|
|
@@ -26,13 +26,14 @@ export declare namespace ChipProps {
|
|
|
26
26
|
addonAfter?: AddonValue | undefined
|
|
27
27
|
count?: ReactNode | undefined
|
|
28
28
|
}
|
|
29
|
+
interface CommonProps extends OwnProps, GDSComponentProps<typeof ChipMeta> {}
|
|
29
30
|
interface ButtonProps
|
|
30
31
|
extends
|
|
31
|
-
|
|
32
|
+
CommonProps,
|
|
32
33
|
Omit<ButtonOrLinkProps.ButtonProps, 'value'>,
|
|
33
34
|
ButtonOrLinkProps.DisableableProps {}
|
|
34
35
|
interface LinkProps
|
|
35
|
-
extends
|
|
36
|
+
extends CommonProps, ButtonOrLinkProps.LinkProps, ButtonOrLinkProps.DisableableProps {}
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
export type ChipProps = ChipProps.ButtonProps | ChipProps.LinkProps
|
|
@@ -222,9 +223,9 @@ function ChipAddon({
|
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
export declare namespace ChipGroupProps {
|
|
225
|
-
interface
|
|
226
|
-
|
|
227
|
-
interface CheckboxProps extends
|
|
226
|
+
interface HTMLProps extends Omit<ComponentProps<'div'>, 'onChange'> {}
|
|
227
|
+
interface CommonProps extends HTMLProps, GDSComponentProps<typeof ChipGroupMeta> {}
|
|
228
|
+
interface CheckboxProps extends CommonProps {
|
|
228
229
|
type: 'checkbox'
|
|
229
230
|
name?: undefined
|
|
230
231
|
/** Array of checked/selected chip values. */
|
|
@@ -232,7 +233,7 @@ export declare namespace ChipGroupProps {
|
|
|
232
233
|
defaultValue?: string[] | undefined
|
|
233
234
|
onChange?: ((value: string[]) => void) | undefined
|
|
234
235
|
}
|
|
235
|
-
interface RadioProps extends
|
|
236
|
+
interface RadioProps extends CommonProps {
|
|
236
237
|
type: 'radio'
|
|
237
238
|
/** Name used to submit the checked/selected chip value when inside a form. */
|
|
238
239
|
name?: string | undefined
|
|
@@ -8,10 +8,12 @@ import { MaybeButtonOrLink, type MaybeButtonOrLinkProps } from './base/MaybeButt
|
|
|
8
8
|
import { ClusterMeta } from './Cluster.meta.ts'
|
|
9
9
|
|
|
10
10
|
export declare namespace ClusterProps {
|
|
11
|
-
interface
|
|
12
|
-
|
|
13
|
-
interface LinkProps
|
|
14
|
-
|
|
11
|
+
interface ButtonProps
|
|
12
|
+
extends GDSComponentProps<typeof ClusterMeta>, MaybeButtonOrLinkProps.ButtonProps {}
|
|
13
|
+
interface LinkProps
|
|
14
|
+
extends GDSComponentProps<typeof ClusterMeta>, MaybeButtonOrLinkProps.LinkProps {}
|
|
15
|
+
interface OtherElementProps
|
|
16
|
+
extends GDSComponentProps<typeof ClusterMeta>, MaybeButtonOrLinkProps.OtherElementProps {}
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export type ClusterProps =
|
package/src/components/Icon.tsx
CHANGED
|
@@ -27,8 +27,10 @@ export interface IconProps
|
|
|
27
27
|
alt: string | undefined
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export type IconSrc = ReactElement | ComponentType
|
|
31
|
+
|
|
30
32
|
export interface IconPropsWithSrc extends IconProps {
|
|
31
|
-
src:
|
|
33
|
+
src: IconSrc
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export function Icon({ src, alt, size, color, className, style, ...props }: IconPropsWithSrc) {
|
package/src/components/Link.tsx
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { ComponentProps, CSSProperties } from 'react'
|
|
4
4
|
|
|
5
|
+
import type { GDSComponentProps } from '@graphprotocol/gds-css'
|
|
5
6
|
import { ArrowUpRightInteractiveIcon } from '@graphprotocol/gds-react/icons'
|
|
6
7
|
|
|
7
8
|
import { useCSSPropsPolyfill, useCSSState, useGDS } from '../hooks/index.ts'
|
|
@@ -11,23 +12,22 @@ import { ButtonOrLink, type ButtonOrLinkProps } from './base/ButtonOrLink.tsx'
|
|
|
11
12
|
import { LinkMeta } from './Link.meta.ts'
|
|
12
13
|
|
|
13
14
|
export declare namespace LinkProps {
|
|
14
|
-
interface
|
|
15
|
-
/** @default 'primary' */
|
|
16
|
-
variant?: 'primary' | 'secondary' | undefined
|
|
15
|
+
interface OwnProps {
|
|
17
16
|
addonBefore?: AddonValue | undefined
|
|
18
17
|
/** Defaults to `ArrowUpRightInteractiveIcon` if `href` is defined and `target` is `_blank` */
|
|
19
18
|
addonAfter?: AddonValue | undefined
|
|
20
19
|
}
|
|
20
|
+
interface CommonProps extends OwnProps, GDSComponentProps<typeof LinkMeta> {}
|
|
21
21
|
interface ButtonProps
|
|
22
22
|
extends
|
|
23
|
-
|
|
23
|
+
CommonProps,
|
|
24
24
|
Omit<ButtonOrLinkProps.ButtonProps, 'href'>,
|
|
25
25
|
ButtonOrLinkProps.DisableableProps {
|
|
26
26
|
// We want to make `href` required, while still allowing to render this component as a button if needed
|
|
27
27
|
href: undefined
|
|
28
28
|
}
|
|
29
29
|
interface LinkProps
|
|
30
|
-
extends
|
|
30
|
+
extends CommonProps, ButtonOrLinkProps.LinkProps, ButtonOrLinkProps.DisableableProps {}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export type LinkProps = LinkProps.LinkProps | LinkProps.ButtonProps
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useLayoutEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
type ComponentProps,
|
|
9
|
+
type ReactNode,
|
|
10
|
+
} from 'react'
|
|
11
|
+
import { Menu, type MenuRootActions } from '@base-ui/react/menu'
|
|
5
12
|
import { useMergedRefs } from '@base-ui/utils/useMergedRefs'
|
|
6
13
|
import type { Merge } from 'type-fest'
|
|
7
14
|
|
|
@@ -36,16 +43,16 @@ const MenuTriggerContext = createContext<boolean>(false)
|
|
|
36
43
|
type MenuItemType = 'plain' | 'checkbox' | 'radio'
|
|
37
44
|
|
|
38
45
|
declare namespace GroupProps {
|
|
39
|
-
interface
|
|
46
|
+
interface CommonProps {
|
|
40
47
|
label?: ReactNode | undefined
|
|
41
48
|
}
|
|
42
|
-
interface NonRadioProps extends
|
|
49
|
+
interface NonRadioProps extends CommonProps {
|
|
43
50
|
type?: Exclude<MenuItemType, 'radio'> | undefined
|
|
44
51
|
value?: undefined
|
|
45
52
|
defaultValue?: undefined
|
|
46
53
|
onChange?: undefined
|
|
47
54
|
}
|
|
48
|
-
interface RadioProps<T extends OptionValue> extends
|
|
55
|
+
interface RadioProps<T extends OptionValue> extends CommonProps {
|
|
49
56
|
type: 'radio'
|
|
50
57
|
value?: T | undefined
|
|
51
58
|
defaultValue?: T | undefined
|
|
@@ -53,11 +60,9 @@ declare namespace GroupProps {
|
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
declare namespace MenuProps {
|
|
57
|
-
interface
|
|
58
|
-
|
|
59
|
-
Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange'>,
|
|
60
|
-
GDSComponentProps<typeof MenuMeta> {
|
|
63
|
+
export declare namespace MenuProps {
|
|
64
|
+
interface HTMLProps extends Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange'> {}
|
|
65
|
+
interface OwnProps {
|
|
61
66
|
/**
|
|
62
67
|
* Element that opens the menu when clicked or hovered (depending on `triggerMode`), or a
|
|
63
68
|
* function that returns such an element. If not provided, the menu is rendered inline rather
|
|
@@ -83,8 +88,9 @@ declare namespace MenuProps {
|
|
|
83
88
|
header?: ReactNode | undefined
|
|
84
89
|
footer?: ReactNode | undefined
|
|
85
90
|
}
|
|
86
|
-
interface
|
|
87
|
-
interface
|
|
91
|
+
interface CommonProps extends HTMLProps, OwnProps, GDSComponentProps<typeof MenuMeta> {}
|
|
92
|
+
interface NonRadioProps extends CommonProps, GroupProps.NonRadioProps {}
|
|
93
|
+
interface RadioProps<T extends OptionValue> extends CommonProps, GroupProps.RadioProps<T> {}
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
export type MenuProps<T extends OptionValue = OptionValue> =
|
|
@@ -120,6 +126,7 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
120
126
|
|
|
121
127
|
const { rootProps, nestedProps } = splitProps(props)
|
|
122
128
|
|
|
129
|
+
const actionsRef = useRef<MenuRootActions>(null)
|
|
123
130
|
const portalRef = useRef<HTMLDivElement>(null)
|
|
124
131
|
|
|
125
132
|
const [cssPropsPolyfillRef, cssPropsPolyfillAttributes, cssProps] = useCSSPropsPolyfill(
|
|
@@ -192,7 +199,6 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
192
199
|
|
|
193
200
|
return (
|
|
194
201
|
<div
|
|
195
|
-
ref={cssPropsPolyfillRef}
|
|
196
202
|
data-is-submenu={isSubmenu || undefined}
|
|
197
203
|
data-has-trigger={hasTrigger || undefined}
|
|
198
204
|
className={cn(
|
|
@@ -215,8 +221,15 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
215
221
|
{...cssPropsPolyfillAttributes}
|
|
216
222
|
{...rootProps}
|
|
217
223
|
>
|
|
224
|
+
{/**
|
|
225
|
+
* Ensure changes to CSS props are detected even when the menu is hidden (not closed, but rendered
|
|
226
|
+
* in a `hidden` element). This is necessary because of a `style-observer` bug (or limitation?)
|
|
227
|
+
* related to `display: contents` (see https://github.com/LeaVerou/style-observer/issues/140).
|
|
228
|
+
*/}
|
|
229
|
+
<span ref={cssPropsPolyfillRef} className="invisible absolute" />
|
|
218
230
|
<MenuRoot
|
|
219
231
|
key={`${hasTrigger}-${triggerMode}`}
|
|
232
|
+
actionsRef={actionsRef}
|
|
220
233
|
open={open}
|
|
221
234
|
onOpenChange={(newOpen) => {
|
|
222
235
|
// A menu with no trigger can still be opened/closed by the consumer, but it should not send events
|
|
@@ -279,7 +292,7 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
279
292
|
sideOffset={twToPx(cssProps.gap)}
|
|
280
293
|
align={cssProps.align}
|
|
281
294
|
alignOffset={twToPx(cssProps.alignOffset)}
|
|
282
|
-
collisionPadding={
|
|
295
|
+
collisionPadding={4}
|
|
283
296
|
collisionAvoidance={{
|
|
284
297
|
side: 'flip',
|
|
285
298
|
align: 'flip',
|
|
@@ -300,6 +313,7 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
300
313
|
u:rounded-12
|
|
301
314
|
u:data-has-trigger:max-h-(--available-height-but-not-too-small)
|
|
302
315
|
u:data-has-trigger:max-w-(--available-width)
|
|
316
|
+
i:data-anchor-hidden:hidden
|
|
303
317
|
u:i:data-[match-trigger-height=at-least]:min-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
|
|
304
318
|
u:i:data-[match-trigger-height=at-most]:max-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
|
|
305
319
|
u:i:data-[match-trigger-height=true]:h-(--anchor-height)
|
|
@@ -309,8 +323,19 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
309
323
|
className,
|
|
310
324
|
)}
|
|
311
325
|
{...dirProps}
|
|
312
|
-
render={(renderProps) => (
|
|
313
|
-
|
|
326
|
+
render={(renderProps, state) => (
|
|
327
|
+
<>
|
|
328
|
+
<div {...renderProps} style={hasTrigger ? renderProps.style : undefined} />
|
|
329
|
+
{/**
|
|
330
|
+
* The `data-anchor-hidden:hidden` class above hides the menu if it's open when the trigger gets
|
|
331
|
+
* hidden, but this actually closes it to restore pointer interactions outside the menu (though the
|
|
332
|
+
* class is still necessary to prevent a flash of incorrect menu position). We're doing it in an
|
|
333
|
+
* effect to prevent a "Cannot update a component while rendering a different component" error.
|
|
334
|
+
*/}
|
|
335
|
+
{hasTrigger && state.open && state.anchorHidden && actionsRef.current ? (
|
|
336
|
+
<LayoutEffect effect={actionsRef.current.close} />
|
|
337
|
+
) : null}
|
|
338
|
+
</>
|
|
314
339
|
)}
|
|
315
340
|
>
|
|
316
341
|
<Menu.Popup
|
|
@@ -478,6 +503,11 @@ export function MenuRoot<T extends OptionValue>({
|
|
|
478
503
|
}
|
|
479
504
|
MenuRoot.displayName = 'Menu'
|
|
480
505
|
|
|
506
|
+
function LayoutEffect({ effect }: { effect: () => void }) {
|
|
507
|
+
useLayoutEffect(effect, [effect])
|
|
508
|
+
return null
|
|
509
|
+
}
|
|
510
|
+
|
|
481
511
|
const MenuGroupContext = createContext<
|
|
482
512
|
| {
|
|
483
513
|
type: MenuItemType
|
|
@@ -486,10 +516,10 @@ const MenuGroupContext = createContext<
|
|
|
486
516
|
| null
|
|
487
517
|
>(null)
|
|
488
518
|
|
|
489
|
-
declare namespace MenuGroupProps {
|
|
490
|
-
interface
|
|
491
|
-
interface NonRadioProps extends
|
|
492
|
-
interface RadioProps<T extends OptionValue> extends
|
|
519
|
+
export declare namespace MenuGroupProps {
|
|
520
|
+
interface HTMLProps extends Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange'> {}
|
|
521
|
+
interface NonRadioProps extends HTMLProps, GroupProps.NonRadioProps {}
|
|
522
|
+
interface RadioProps<T extends OptionValue> extends HTMLProps, GroupProps.RadioProps<T> {}
|
|
493
523
|
}
|
|
494
524
|
|
|
495
525
|
export type MenuGroupProps<T extends OptionValue = OptionValue> =
|
|
@@ -545,15 +575,17 @@ export function MenuGroup<T extends OptionValue>({
|
|
|
545
575
|
MenuGroup.displayName = 'Menu.Group'
|
|
546
576
|
|
|
547
577
|
export declare namespace MenuItemProps {
|
|
548
|
-
interface
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
578
|
+
interface HTMLProps extends Omit<
|
|
579
|
+
ComponentProps<'div'>,
|
|
580
|
+
'defaultChecked' | 'defaultValue' | 'onChange'
|
|
581
|
+
> {}
|
|
582
|
+
interface OwnProps {
|
|
552
583
|
addonBefore?: AddonValue | undefined
|
|
553
584
|
addonAfter?: AddonValue | undefined
|
|
554
585
|
disabled?: boolean | undefined
|
|
555
586
|
}
|
|
556
|
-
interface
|
|
587
|
+
interface CommonProps extends HTMLProps, OwnProps, GDSComponentProps<typeof MenuItemMeta> {}
|
|
588
|
+
interface PlainProps extends CommonProps {
|
|
557
589
|
type?: 'plain' | undefined
|
|
558
590
|
variant?: 'default' | 'danger' | undefined
|
|
559
591
|
loading?: boolean | undefined
|
|
@@ -564,7 +596,7 @@ export declare namespace MenuItemProps {
|
|
|
564
596
|
onChange?: undefined
|
|
565
597
|
value?: undefined
|
|
566
598
|
}
|
|
567
|
-
interface CheckboxProps extends
|
|
599
|
+
interface CheckboxProps extends CommonProps {
|
|
568
600
|
type?: 'checkbox' | undefined
|
|
569
601
|
checked?: boolean | 'indeterminate' | undefined
|
|
570
602
|
defaultChecked?: boolean | 'indeterminate' | undefined
|
|
@@ -575,7 +607,7 @@ export declare namespace MenuItemProps {
|
|
|
575
607
|
target?: undefined
|
|
576
608
|
value?: undefined
|
|
577
609
|
}
|
|
578
|
-
interface RadioProps<T extends OptionValue = OptionValue> extends
|
|
610
|
+
interface RadioProps<T extends OptionValue = OptionValue> extends CommonProps {
|
|
579
611
|
type?: 'radio' | undefined
|
|
580
612
|
value?: T | undefined
|
|
581
613
|
variant?: undefined
|
|
@@ -213,11 +213,12 @@ export const ModalRoot = <
|
|
|
213
213
|
<Portal>
|
|
214
214
|
<div
|
|
215
215
|
ref={cssPropsPolyfillRef}
|
|
216
|
-
className={cn('gds-modal i:invisible', cssPropsClassName, className)}
|
|
216
|
+
className={cn('gds-modal i:invisible i:block', cssPropsClassName, className)}
|
|
217
217
|
{...cssPropsAttributes}
|
|
218
218
|
{...cssPropsPolyfillAttributes}
|
|
219
219
|
{...dirProps}
|
|
220
220
|
{...props}
|
|
221
|
+
hidden={undefined}
|
|
221
222
|
/>
|
|
222
223
|
</Portal>
|
|
223
224
|
<Dialog.Portal>
|
|
@@ -233,7 +234,7 @@ export const ModalRoot = <
|
|
|
233
234
|
* root, then it returns 100vw because 100cqi, even 9999 times, is 0.
|
|
234
235
|
*/
|
|
235
236
|
className={cn(
|
|
236
|
-
|
|
237
|
+
'gds-modal @container-[size] pointer-events-none absolute top-0 left-0 u:text-16 u:text-muted i:invisible i:*:visible',
|
|
237
238
|
cssPropsClassName,
|
|
238
239
|
className,
|
|
239
240
|
)}
|
|
@@ -87,7 +87,7 @@ function createPaneStore(storeId: string) {
|
|
|
87
87
|
: { ...initial, id, layout: PaneMeta.cssProps.layout.defaultValue, registrants },
|
|
88
88
|
)
|
|
89
89
|
// Defer notification to avoid updating components during render
|
|
90
|
-
window.queueMicrotask(notify)
|
|
90
|
+
if (typeof window !== 'undefined') window.queueMicrotask(notify)
|
|
91
91
|
},
|
|
92
92
|
unregister: (name: string, registrantId: string) => {
|
|
93
93
|
const pane = panes.get(name)
|
|
@@ -316,10 +316,10 @@ export function PaneRoot({
|
|
|
316
316
|
const duration = parseDuration(styleValues['--tw-duration']) ?? DEFAULT_DURATION
|
|
317
317
|
const rootPassedRef = useMergedRefs(rootRef, passedRef, styleCallbackRef)
|
|
318
318
|
|
|
319
|
-
const [
|
|
319
|
+
const [cssPropsPolyfillRef, cssPropsPolyfillAttributes, cssProps] = useCSSPropsPolyfill(
|
|
320
320
|
PaneMeta,
|
|
321
321
|
{ layout, side },
|
|
322
|
-
{
|
|
322
|
+
{ returnPropValues: { layout, side } },
|
|
323
323
|
)
|
|
324
324
|
|
|
325
325
|
// Sync layout to store, resetting `overlayOpen` when switching from overlay to docked
|
|
@@ -430,7 +430,7 @@ export function PaneRoot({
|
|
|
430
430
|
|
|
431
431
|
return (
|
|
432
432
|
<Element
|
|
433
|
-
ref={
|
|
433
|
+
ref={rootPassedRef}
|
|
434
434
|
id={pane.id}
|
|
435
435
|
data-gds-exposed-open={open}
|
|
436
436
|
className={cn(
|
|
@@ -445,6 +445,12 @@ export function PaneRoot({
|
|
|
445
445
|
{...cssPropsPolyfillAttributes}
|
|
446
446
|
{...props}
|
|
447
447
|
>
|
|
448
|
+
{/**
|
|
449
|
+
* Ensure changes to CSS props are detected even when the pane is hidden (not closed, but rendered
|
|
450
|
+
* in a `hidden` element). This is necessary because of a `style-observer` bug (or limitation?)
|
|
451
|
+
* related to `display: contents` (see https://github.com/LeaVerou/style-observer/issues/140).
|
|
452
|
+
*/}
|
|
453
|
+
<span ref={cssPropsPolyfillRef} className="invisible absolute" />
|
|
448
454
|
{overlayModal ? (
|
|
449
455
|
<div
|
|
450
456
|
aria-hidden
|
|
@@ -520,7 +526,9 @@ export function PaneRoot({
|
|
|
520
526
|
}
|
|
521
527
|
data-hidden-style={hiddenStyle || undefined}
|
|
522
528
|
data-hidden-if-overlay={
|
|
523
|
-
(
|
|
529
|
+
(!pane.overlayOpen &&
|
|
530
|
+
(cssProps.layout === 'docked' || beforeFirstTransition.current)) ||
|
|
531
|
+
undefined
|
|
524
532
|
}
|
|
525
533
|
data-layout={cssProps.layout}
|
|
526
534
|
data-side={cssProps.side}
|
|
@@ -632,12 +640,12 @@ type PaneToggleButtonState = {
|
|
|
632
640
|
open: boolean
|
|
633
641
|
}
|
|
634
642
|
|
|
635
|
-
interface
|
|
643
|
+
interface PaneToggleButtonCommonProps extends ComponentProps<'button'> {
|
|
636
644
|
/** Name of the pane to toggle. */
|
|
637
645
|
name: string
|
|
638
646
|
}
|
|
639
647
|
|
|
640
|
-
interface PaneToggleButtonWithRenderProps extends
|
|
648
|
+
interface PaneToggleButtonWithRenderProps extends PaneToggleButtonCommonProps {
|
|
641
649
|
/** Element or render function for the toggle button. */
|
|
642
650
|
render: RenderProp<PaneToggleButtonState>
|
|
643
651
|
variant?: never
|
|
@@ -650,7 +658,7 @@ interface PaneToggleButtonWithRenderProps extends PaneToggleButtonBaseProps {
|
|
|
650
658
|
|
|
651
659
|
interface PaneToggleButtonWithoutRenderProps
|
|
652
660
|
extends
|
|
653
|
-
|
|
661
|
+
PaneToggleButtonCommonProps,
|
|
654
662
|
Pick<
|
|
655
663
|
ToggleButtonProps,
|
|
656
664
|
'variant' | 'size' | 'hideLabel' | 'tooltip' | 'addonBefore' | 'addonAfter'
|
|
@@ -123,8 +123,8 @@ export function TooltipRoot({
|
|
|
123
123
|
const triggerPassedRef = useMergedRefs(
|
|
124
124
|
/**
|
|
125
125
|
* Conditionally setting the ref to force the tooltip to refresh its position when `enabled`
|
|
126
|
-
* changes, preventing it from moving to the
|
|
127
|
-
* `CopyButton` returns to its default tooltip).
|
|
126
|
+
* changes, preventing it from moving to the top left corner of the viewport in some cases (e.g.
|
|
127
|
+
* when `CopyButton` returns to its default tooltip).
|
|
128
128
|
*/
|
|
129
129
|
enabled ? triggerRef : undefined,
|
|
130
130
|
(passedTriggerProps === 'forward' ? passedRef : passedTriggerProps?.ref) as
|
|
@@ -207,10 +207,22 @@ export function TooltipRoot({
|
|
|
207
207
|
render={children}
|
|
208
208
|
{...renderProps}
|
|
209
209
|
disabled={triggerDisabled}
|
|
210
|
-
onClick={triggerProps?.onClick} // Prevent the tooltip
|
|
210
|
+
onClick={triggerProps?.onClick} // Prevent re-opening the tooltip after clicking e.g. a `Menu` trigger
|
|
211
211
|
/>
|
|
212
212
|
)}
|
|
213
213
|
/>
|
|
214
|
+
{/* Ensure changes to CSS props are detected even when the tooltip is not mounted */}
|
|
215
|
+
<Portal>
|
|
216
|
+
<span
|
|
217
|
+
ref={cssPropsPolyfillRef}
|
|
218
|
+
className={cn('gds-tooltip i:invisible i:block', className)}
|
|
219
|
+
{...cssPropsAttributes}
|
|
220
|
+
{...cssPropsPolyfillAttributes}
|
|
221
|
+
{...dirProps}
|
|
222
|
+
{...popupProps}
|
|
223
|
+
hidden={undefined}
|
|
224
|
+
/>
|
|
225
|
+
</Portal>
|
|
214
226
|
<Tooltip.Portal>
|
|
215
227
|
<Tooltip.Positioner
|
|
216
228
|
key={getReactNodeKey(content)} // Refresh the tooltip's position when the content changes (see `WithDynamicContent` story)
|
|
@@ -224,9 +236,10 @@ export function TooltipRoot({
|
|
|
224
236
|
sideOffset={twToPx(cssProps.gap)}
|
|
225
237
|
align={cssProps.align}
|
|
226
238
|
alignOffset={twToPx(cssProps.alignOffset)}
|
|
227
|
-
collisionPadding={
|
|
228
|
-
disableAnchorTracking //
|
|
239
|
+
collisionPadding={4}
|
|
240
|
+
disableAnchorTracking // Feels weird for a tooltip to follow e.g. a pane's X button when closing the pane
|
|
229
241
|
{...dirProps}
|
|
242
|
+
className="i:data-anchor-hidden:hidden" // Prevent moving to the top left corner when the trigger is hidden or unmounted
|
|
230
243
|
>
|
|
231
244
|
<Tooltip.Popup
|
|
232
245
|
ref={popupRef}
|
|
@@ -251,16 +264,6 @@ export function TooltipRoot({
|
|
|
251
264
|
</Tooltip.Popup>
|
|
252
265
|
</Tooltip.Positioner>
|
|
253
266
|
</Tooltip.Portal>
|
|
254
|
-
{/* Ensure changes to CSS props are detected even when the tooltip is not mounted */}
|
|
255
|
-
<Portal>
|
|
256
|
-
<span
|
|
257
|
-
ref={cssPropsPolyfillRef}
|
|
258
|
-
className={cn('gds-tooltip i:invisible', className)}
|
|
259
|
-
{...cssPropsAttributes}
|
|
260
|
-
{...cssPropsPolyfillAttributes}
|
|
261
|
-
{...popupProps}
|
|
262
|
-
/>
|
|
263
|
-
</Portal>
|
|
264
267
|
</Tooltip.Root>
|
|
265
268
|
</TooltipContext.Provider>
|
|
266
269
|
)
|
|
@@ -60,7 +60,7 @@ export declare namespace InternalButtonOrLinkProps {
|
|
|
60
60
|
interface DisableableProps {
|
|
61
61
|
disabled?: boolean | 'focusable' | undefined
|
|
62
62
|
}
|
|
63
|
-
interface
|
|
63
|
+
interface CommonProps {
|
|
64
64
|
/**
|
|
65
65
|
* Whether to render the element inline instead of block-level. For buttons, renders a `span`
|
|
66
66
|
* that behaves like an accessible button. For links, this prop has no effect as anchor elements
|
|
@@ -77,7 +77,7 @@ export declare namespace InternalButtonOrLinkProps {
|
|
|
77
77
|
}
|
|
78
78
|
interface ButtonProps
|
|
79
79
|
extends
|
|
80
|
-
|
|
80
|
+
CommonProps,
|
|
81
81
|
DisableableProps,
|
|
82
82
|
Omit<ComponentProps<'button'>, 'defaultValue' | 'disabled'> {
|
|
83
83
|
href?: undefined
|
|
@@ -91,7 +91,7 @@ export declare namespace InternalButtonOrLinkProps {
|
|
|
91
91
|
defaultChecked?: boolean | undefined
|
|
92
92
|
}
|
|
93
93
|
interface LinkProps
|
|
94
|
-
extends
|
|
94
|
+
extends CommonProps, DisableableProps, Omit<ComponentProps<'a'>, 'defaultValue'> {
|
|
95
95
|
href: string
|
|
96
96
|
type?: undefined
|
|
97
97
|
checked?: undefined
|
|
@@ -135,15 +135,12 @@ type WithContextComponent<T extends ElementType> = (
|
|
|
135
135
|
props: Merge<ComponentProps<T>, ButtonOrLinkRenderElementProps>,
|
|
136
136
|
) => ReactElement
|
|
137
137
|
|
|
138
|
-
const memoizedWithContextComponents = new Map<ElementType,
|
|
138
|
+
const memoizedWithContextComponents = new Map<ElementType, unknown>()
|
|
139
139
|
|
|
140
140
|
function withContext<T extends ElementType>(Element: T): WithContextComponent<T> {
|
|
141
141
|
const cached = memoizedWithContextComponents.get(Element)
|
|
142
|
-
if (cached) return cached
|
|
143
|
-
const newWithContextComponent: WithContextComponent<
|
|
144
|
-
buttonOrLinkState,
|
|
145
|
-
...props
|
|
146
|
-
}) => (
|
|
142
|
+
if (cached) return cached as WithContextComponent<T>
|
|
143
|
+
const newWithContextComponent: WithContextComponent<T> = ({ buttonOrLinkState, ...props }) => (
|
|
147
144
|
<ButtonOrLinkContext.Provider value={buttonOrLinkState}>
|
|
148
145
|
<Element {...(props as ComponentProps<T>)} />
|
|
149
146
|
</ButtonOrLinkContext.Provider>
|
|
@@ -202,7 +199,7 @@ export const ButtonOrLinkRoot = (passedProps: InternalButtonOrLinkProps) => {
|
|
|
202
199
|
render: passedRender,
|
|
203
200
|
className: passedClassName,
|
|
204
201
|
children,
|
|
205
|
-
...
|
|
202
|
+
...specificProps
|
|
206
203
|
} = props
|
|
207
204
|
const manuallyDisabledEventProps = {
|
|
208
205
|
onClick: undefined,
|
|
@@ -246,7 +243,7 @@ export const ButtonOrLinkRoot = (passedProps: InternalButtonOrLinkProps) => {
|
|
|
246
243
|
href: _href,
|
|
247
244
|
target: _target,
|
|
248
245
|
...remainingProps
|
|
249
|
-
} =
|
|
246
|
+
} = specificProps
|
|
250
247
|
|
|
251
248
|
if (defaultChecked !== undefined) {
|
|
252
249
|
// oxlint-disable-next-line no-console
|
|
@@ -309,7 +306,7 @@ export const ButtonOrLinkRoot = (passedProps: InternalButtonOrLinkProps) => {
|
|
|
309
306
|
checked: _checked,
|
|
310
307
|
defaultChecked: _defaultChecked,
|
|
311
308
|
...remainingProps
|
|
312
|
-
} =
|
|
309
|
+
} = specificProps
|
|
313
310
|
|
|
314
311
|
let linkProps: ComponentProps<'a'> = {
|
|
315
312
|
role: disabled || role !== 'link' ? role : undefined,
|
|
@@ -42,7 +42,7 @@ export declare namespace MaybeButtonOrLinkProps {
|
|
|
42
42
|
render?: RenderFn<MaybeButtonOrLinkRenderState> | undefined
|
|
43
43
|
}
|
|
44
44
|
export type OtherElementProps =
|
|
45
|
-
OmitInternalButtonOrLinkProps<InternalButtonOrLinkProps.
|
|
45
|
+
OmitInternalButtonOrLinkProps<InternalButtonOrLinkProps.CommonProps> &
|
|
46
46
|
ComponentProps<'span'> & {
|
|
47
47
|
onClick?: InternalButtonOrLinkProps.ButtonProps['onClick'] // Not technically correct, but prevents the event from being `any` when `as` is not specified
|
|
48
48
|
as?: ElementType | undefined
|
|
@@ -63,7 +63,7 @@ export type MaybeButtonOrLinkProps =
|
|
|
63
63
|
|
|
64
64
|
type InternalMaybeButtonOrLinkProps = MaybeButtonOrLinkProps &
|
|
65
65
|
InternalButtonOrLinkProps.DisableableProps &
|
|
66
|
-
Omit<InternalButtonOrLinkProps.
|
|
66
|
+
Omit<InternalButtonOrLinkProps.CommonProps, 'render'>
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Renders a `ButtonOrLink` if one of `href` or `onClick` is passed along with no `as`. Otherwise,
|
package/src/components/index.ts
CHANGED
|
@@ -34,7 +34,7 @@ export {
|
|
|
34
34
|
export { DescriptionListItemMeta, DescriptionListMeta } from './DescriptionList.meta.ts'
|
|
35
35
|
export { Divider, type DividerProps } from './Divider.tsx'
|
|
36
36
|
export { DividerMeta } from './Divider.meta.ts'
|
|
37
|
-
export { Icon, type IconProps, type IconPropsWithSrc } from './Icon.tsx'
|
|
37
|
+
export { Icon, type IconProps, type IconSrc, type IconPropsWithSrc } from './Icon.tsx'
|
|
38
38
|
export { IconMeta } from './Icon.meta.ts'
|
|
39
39
|
export { Input, type InputProps, type InputState } from './Input.tsx'
|
|
40
40
|
export { InputMeta } from './Input.meta.ts'
|