@primer/components 31.2.0-rc.c285489d → 31.2.0-rc.c7f73427
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/browser.esm.js +180 -178
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +182 -180
- package/dist/browser.umd.js.map +1 -1
- package/docs/content/FilterList.md +2 -2
- package/docs/content/theming.md +23 -0
- package/docs/src/@primer/gatsby-theme-doctocat/components/hero.js +1 -3
- package/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js +1 -1
- package/lib/ActionList/Header.js +1 -1
- package/lib/Overlay.js +3 -1
- package/lib/Portal/Portal.js +3 -2
- package/lib/_TextInputWrapper.js +2 -2
- package/lib/__tests__/AnchoredOverlay.test.js +4 -2
- package/lib/__tests__/KeyPaths.types.test.d.ts +2 -1
- package/lib/__tests__/TextInputWithTokens.test.js +1 -10
- package/lib/hooks/useAnchoredPosition.js +3 -2
- package/lib/hooks/useCombinedRefs.d.ts +2 -2
- package/lib/hooks/useCombinedRefs.js +4 -6
- package/lib/hooks/useResizeObserver.js +2 -2
- package/lib/stories/TextInput.stories.js +144 -0
- package/lib/stories/Token.stories.js +19 -2
- package/lib/utils/types/KeyPaths.d.ts +1 -1
- package/lib/utils/useIsomorphicLayoutEffect.d.ts +3 -0
- package/lib/utils/useIsomorphicLayoutEffect.js +12 -0
- package/lib-esm/ActionList/Header.js +1 -1
- package/lib-esm/Overlay.js +2 -1
- package/lib-esm/Portal/Portal.js +2 -1
- package/lib-esm/_TextInputWrapper.js +2 -2
- package/lib-esm/__tests__/AnchoredOverlay.test.js +4 -2
- package/lib-esm/__tests__/KeyPaths.types.test.d.ts +2 -1
- package/lib-esm/__tests__/TextInputWithTokens.test.js +1 -10
- package/lib-esm/hooks/useAnchoredPosition.js +2 -1
- package/lib-esm/hooks/useCombinedRefs.d.ts +2 -2
- package/lib-esm/hooks/useCombinedRefs.js +3 -2
- package/lib-esm/hooks/useResizeObserver.js +2 -2
- package/lib-esm/stories/TextInput.stories.js +117 -0
- package/lib-esm/stories/Token.stories.js +14 -1
- package/lib-esm/utils/types/KeyPaths.d.ts +1 -1
- package/lib-esm/utils/useIsomorphicLayoutEffect.d.ts +3 -0
- package/lib-esm/utils/useIsomorphicLayoutEffect.js +3 -0
- package/migrating.md +1 -1
- package/package-lock.json +15 -2
- package/package.json +3 -2
- package/script/build +2 -0
- package/src/ActionList/Header.tsx +1 -1
- package/src/Overlay.tsx +2 -1
- package/src/Portal/Portal.tsx +2 -1
- package/src/_TextInputWrapper.tsx +7 -0
- package/src/__tests__/AnchoredOverlay.test.tsx +2 -2
- package/src/__tests__/KeyPaths.types.test.ts +2 -1
- package/src/__tests__/TextInputWithTokens.test.tsx +0 -10
- package/src/__tests__/__snapshots__/AnchoredOverlay.test.tsx.snap +35 -135
- package/src/hooks/useAnchoredPosition.ts +2 -1
- package/src/hooks/useCombinedRefs.ts +3 -3
- package/src/hooks/useResizeObserver.ts +2 -2
- package/src/stories/Button.stories.tsx +1 -1
- package/src/stories/TextInput.stories.tsx +113 -0
- package/src/stories/Token.stories.tsx +12 -1
- package/src/utils/types/KeyPaths.ts +7 -1
- package/src/utils/useIsomorphicLayoutEffect.ts +10 -0
- package/stats.html +1 -1
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import { useRef } from 'react';
|
2
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect';
|
2
3
|
/**
|
3
4
|
* Creates a ref by combining multiple constituent refs. The ref returned by this hook
|
4
5
|
* should be passed as the ref for the element that needs to be shared. This is
|
@@ -10,7 +11,7 @@ import React, { useRef } from 'react';
|
|
10
11
|
|
11
12
|
export function useCombinedRefs(...refs) {
|
12
13
|
const combinedRef = useRef(null);
|
13
|
-
|
14
|
+
useLayoutEffect(() => {
|
14
15
|
function setRefs(current = null) {
|
15
16
|
for (const ref of refs) {
|
16
17
|
if (!ref) {
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import
|
1
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect';
|
2
2
|
export function useResizeObserver(callback) {
|
3
|
-
|
3
|
+
useLayoutEffect(() => {
|
4
4
|
const observer = new window.ResizeObserver(() => callback());
|
5
5
|
observer.observe(document.documentElement);
|
6
6
|
return () => {
|
@@ -0,0 +1,117 @@
|
|
1
|
+
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
|
3
|
+
import React, { useState } from 'react';
|
4
|
+
import { BaseStyles, Box, ThemeProvider, Text } from '..';
|
5
|
+
import TextInput from '../TextInput';
|
6
|
+
import { CheckIcon } from '@primer/octicons-react';
|
7
|
+
export default {
|
8
|
+
title: 'Forms/Text Input',
|
9
|
+
component: TextInput,
|
10
|
+
decorators: [Story => {
|
11
|
+
return /*#__PURE__*/React.createElement(ThemeProvider, null, /*#__PURE__*/React.createElement(BaseStyles, null, /*#__PURE__*/React.createElement(Box, {
|
12
|
+
paddingTop: 5
|
13
|
+
}, Story())));
|
14
|
+
}],
|
15
|
+
argTypes: {
|
16
|
+
sx: {
|
17
|
+
table: {
|
18
|
+
disable: true
|
19
|
+
}
|
20
|
+
},
|
21
|
+
block: {
|
22
|
+
name: 'Block',
|
23
|
+
defaultValue: false,
|
24
|
+
control: {
|
25
|
+
type: 'boolean'
|
26
|
+
}
|
27
|
+
},
|
28
|
+
disabled: {
|
29
|
+
name: 'Disabled',
|
30
|
+
defaultValue: false,
|
31
|
+
control: {
|
32
|
+
type: 'boolean'
|
33
|
+
}
|
34
|
+
},
|
35
|
+
variant: {
|
36
|
+
name: 'Variants',
|
37
|
+
options: ['small', 'medium', 'large'],
|
38
|
+
control: {
|
39
|
+
type: 'radio'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
};
|
44
|
+
|
45
|
+
const Label = ({
|
46
|
+
htmlFor,
|
47
|
+
children
|
48
|
+
}) => /*#__PURE__*/React.createElement(Text, {
|
49
|
+
as: "label",
|
50
|
+
htmlFor: htmlFor,
|
51
|
+
sx: {
|
52
|
+
fontWeight: 600,
|
53
|
+
fontSize: 14
|
54
|
+
}
|
55
|
+
}, children);
|
56
|
+
|
57
|
+
Label.displayName = "Label";
|
58
|
+
export const Default = args => {
|
59
|
+
const [value, setValue] = useState('');
|
60
|
+
|
61
|
+
const handleChange = event => {
|
62
|
+
setValue(event.target.value);
|
63
|
+
};
|
64
|
+
|
65
|
+
const inputId = 'basic-text-input';
|
66
|
+
return /*#__PURE__*/React.createElement("form", null, /*#__PURE__*/React.createElement("div", {
|
67
|
+
className: "form-group"
|
68
|
+
}, /*#__PURE__*/React.createElement("div", {
|
69
|
+
className: "form-group-header"
|
70
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
71
|
+
htmlFor: inputId
|
72
|
+
}, "Example label")), /*#__PURE__*/React.createElement("div", {
|
73
|
+
className: "form-group-body"
|
74
|
+
}, /*#__PURE__*/React.createElement(TextInput, _extends({
|
75
|
+
id: inputId,
|
76
|
+
value: value,
|
77
|
+
onChange: handleChange
|
78
|
+
}, args)))));
|
79
|
+
};
|
80
|
+
Default.displayName = "Default";
|
81
|
+
export const WithLeadingIcon = args => {
|
82
|
+
const [value, setValue] = useState('');
|
83
|
+
|
84
|
+
const handleChange = event => {
|
85
|
+
setValue(event.target.value);
|
86
|
+
};
|
87
|
+
|
88
|
+
const inputId = 'basic-text-input-with-leading-icon';
|
89
|
+
return /*#__PURE__*/React.createElement("form", null, /*#__PURE__*/React.createElement(Label, {
|
90
|
+
htmlFor: inputId
|
91
|
+
}, "Example label"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(TextInput, _extends({
|
92
|
+
icon: CheckIcon,
|
93
|
+
id: inputId,
|
94
|
+
value: value,
|
95
|
+
onChange: handleChange,
|
96
|
+
type: "password"
|
97
|
+
}, args)));
|
98
|
+
};
|
99
|
+
WithLeadingIcon.displayName = "WithLeadingIcon";
|
100
|
+
export const Password = args => {
|
101
|
+
const [value, setValue] = useState('');
|
102
|
+
|
103
|
+
const handleChange = event => {
|
104
|
+
setValue(event.target.value);
|
105
|
+
};
|
106
|
+
|
107
|
+
const inputId = 'basic-text-input-as-password';
|
108
|
+
return /*#__PURE__*/React.createElement("form", null, /*#__PURE__*/React.createElement(Label, {
|
109
|
+
htmlFor: inputId
|
110
|
+
}, "Password"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(TextInput, _extends({
|
111
|
+
type: "password",
|
112
|
+
id: inputId,
|
113
|
+
value: value,
|
114
|
+
onChange: handleChange
|
115
|
+
}, args)));
|
116
|
+
};
|
117
|
+
Password.displayName = "Password";
|
@@ -7,6 +7,7 @@ import { BaseStyles, ThemeProvider } from '..';
|
|
7
7
|
import Box from '../Box';
|
8
8
|
import Token from '../Token/Token';
|
9
9
|
import Text from '../Text';
|
10
|
+
import { GitBranchIcon } from '@primer/octicons-react';
|
10
11
|
export default {
|
11
12
|
title: 'Tokens/Default',
|
12
13
|
component: Token,
|
@@ -19,7 +20,7 @@ export default {
|
|
19
20
|
return /*#__PURE__*/React.createElement(ThemeProvider, null, /*#__PURE__*/React.createElement(BaseStyles, null, /*#__PURE__*/React.createElement(Story, null)));
|
20
21
|
}]
|
21
22
|
};
|
22
|
-
const excludedControlKeys = ['id', 'as', 'tabIndex', 'onRemove'];
|
23
|
+
const excludedControlKeys = ['id', 'as', 'tabIndex', 'onRemove', 'leadingVisual'];
|
23
24
|
|
24
25
|
const SingleExampleContainer = ({
|
25
26
|
children,
|
@@ -91,6 +92,18 @@ Interactive.parameters = {
|
|
91
92
|
exclude: [...excludedControlKeys, 'hideRemoveButton', 'text']
|
92
93
|
}
|
93
94
|
};
|
95
|
+
export const WithLeadingVisual = args => {
|
96
|
+
return /*#__PURE__*/React.createElement(ExampleCollectionContainer, null, /*#__PURE__*/React.createElement(Token, _extends({}, args, {
|
97
|
+
leadingVisual: () => /*#__PURE__*/React.createElement(GitBranchIcon, null)
|
98
|
+
})));
|
99
|
+
};
|
100
|
+
WithLeadingVisual.displayName = "WithLeadingVisual";
|
101
|
+
WithLeadingVisual.storyName = 'with leadingVisual';
|
102
|
+
WithLeadingVisual.parameters = {
|
103
|
+
controls: {
|
104
|
+
exclude: [...excludedControlKeys, 'hideRemoveButton']
|
105
|
+
}
|
106
|
+
};
|
94
107
|
export const WithOnRemoveFn = args => {
|
95
108
|
return /*#__PURE__*/React.createElement(ExampleCollectionContainer, null, /*#__PURE__*/React.createElement(SingleExampleContainer, {
|
96
109
|
label: "w/ onRemove passed"
|
@@ -1,3 +1,3 @@
|
|
1
1
|
export declare type KeyPaths<O extends Record<string, unknown>> = {
|
2
|
-
[K in keyof O]: K extends string ?
|
2
|
+
[K in keyof O]: K extends string ? O[K] extends string ? `${K}` : `${K}.${KeyPaths<O[K]>}` : never;
|
3
3
|
}[keyof O];
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { useEffect, useLayoutEffect } from 'react';
|
2
|
+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? useLayoutEffect : useEffect;
|
3
|
+
export default useIsomorphicLayoutEffect;
|
package/migrating.md
CHANGED
@@ -110,7 +110,7 @@ There are two ways to change the theme of @primer/components components:
|
|
110
110
|
|
111
111
|
export default () => (
|
112
112
|
<ThemeProvider theme={theme}>
|
113
|
-
<Block color
|
113
|
+
<Block sx={{color: 'bodytext', p: 4}}>
|
114
114
|
<Text fontSize={4}>Hello, world!</Text>
|
115
115
|
</Block>
|
116
116
|
</ThemeProvider>
|
package/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@primer/components",
|
3
|
-
"version": "31.0
|
3
|
+
"version": "31.1.0",
|
4
4
|
"lockfileVersion": 2,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "@primer/components",
|
9
|
-
"version": "31.0
|
9
|
+
"version": "31.1.0",
|
10
10
|
"license": "MIT",
|
11
11
|
"dependencies": {
|
12
12
|
"@primer/octicons-react": "^13.0.0",
|
@@ -100,6 +100,7 @@
|
|
100
100
|
"size-limit": "5.0.2",
|
101
101
|
"storybook-addon-performance": "0.16.1",
|
102
102
|
"styled-components": "4.4.1",
|
103
|
+
"ts-toolbelt": "9.6.0",
|
103
104
|
"typescript": "4.2.2"
|
104
105
|
},
|
105
106
|
"peerDependencies": {
|
@@ -35601,6 +35602,12 @@
|
|
35601
35602
|
}
|
35602
35603
|
}
|
35603
35604
|
},
|
35605
|
+
"node_modules/ts-toolbelt": {
|
35606
|
+
"version": "9.6.0",
|
35607
|
+
"resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
|
35608
|
+
"integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
|
35609
|
+
"dev": true
|
35610
|
+
},
|
35604
35611
|
"node_modules/tsconfig-paths": {
|
35605
35612
|
"version": "3.9.0",
|
35606
35613
|
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
|
@@ -64793,6 +64800,12 @@
|
|
64793
64800
|
"integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==",
|
64794
64801
|
"dev": true
|
64795
64802
|
},
|
64803
|
+
"ts-toolbelt": {
|
64804
|
+
"version": "9.6.0",
|
64805
|
+
"resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
|
64806
|
+
"integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
|
64807
|
+
"dev": true
|
64808
|
+
},
|
64796
64809
|
"tsconfig-paths": {
|
64797
64810
|
"version": "3.9.0",
|
64798
64811
|
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@primer/components",
|
3
|
-
"version": "31.2.0-rc.
|
3
|
+
"version": "31.2.0-rc.c7f73427",
|
4
4
|
"description": "Primer react components",
|
5
5
|
"main": "lib/index.js",
|
6
6
|
"module": "lib-esm/index.js",
|
@@ -15,7 +15,7 @@
|
|
15
15
|
"start": "concurrently npm:start:*",
|
16
16
|
"start:docs": "cd docs && npm run develop",
|
17
17
|
"start:storybook": "start-storybook -p 6006",
|
18
|
-
"lint": "eslint '**/*.{js,ts,tsx,md,mdx}'",
|
18
|
+
"lint": "eslint '**/*.{js,ts,tsx,md,mdx}' --max-warnings=0",
|
19
19
|
"lint:fix": "npm run lint -- --fix",
|
20
20
|
"test": "jest",
|
21
21
|
"test:update": "npm run test -- --updateSnapshot",
|
@@ -134,6 +134,7 @@
|
|
134
134
|
"size-limit": "5.0.2",
|
135
135
|
"storybook-addon-performance": "0.16.1",
|
136
136
|
"styled-components": "4.4.1",
|
137
|
+
"ts-toolbelt": "9.6.0",
|
137
138
|
"typescript": "4.2.2"
|
138
139
|
},
|
139
140
|
"peerDependencies": {
|
package/script/build
CHANGED
package/src/Overlay.tsx
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import styled from 'styled-components'
|
2
|
-
import React, {ReactElement, useEffect,
|
2
|
+
import React, {ReactElement, useEffect, useRef} from 'react'
|
3
3
|
import {get, COMMON, SystemPositionProps, SystemCommonProps} from './constants'
|
4
4
|
import {ComponentProps} from './utils/types'
|
5
|
+
import useLayoutEffect from './utils/useIsomorphicLayoutEffect'
|
5
6
|
import {useOverlay, TouchOrMouseEvent} from './hooks'
|
6
7
|
import Portal from './Portal'
|
7
8
|
import sx, {SxProp} from './sx'
|
package/src/Portal/Portal.tsx
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import {createPortal} from 'react-dom'
|
3
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
|
3
4
|
|
4
5
|
const PRIMER_PORTAL_ROOT_ID = '__primerPortalRoot__'
|
5
6
|
const DEFAULT_PORTAL_CONTAINER_NAME = '__default__'
|
@@ -69,7 +70,7 @@ export const Portal: React.FC<PortalProps> = ({children, onMount, containerName:
|
|
69
70
|
hostElement.style.zIndex = '1'
|
70
71
|
const elementRef = React.useRef(hostElement)
|
71
72
|
|
72
|
-
|
73
|
+
useLayoutEffect(() => {
|
73
74
|
let containerName = _containerName
|
74
75
|
if (containerName === undefined) {
|
75
76
|
containerName = DEFAULT_PORTAL_CONTAINER_NAME
|
@@ -91,6 +91,13 @@ const TextInputWrapper = styled.span<StyledWrapperProps>`
|
|
91
91
|
display: block;
|
92
92
|
width: 100%;
|
93
93
|
`}
|
94
|
+
|
95
|
+
${props =>
|
96
|
+
props.block &&
|
97
|
+
props.hasIcon &&
|
98
|
+
css`
|
99
|
+
display: flex;
|
100
|
+
`}
|
94
101
|
|
95
102
|
// Ensures inputs don't zoom on mobile but are body-font size on desktop
|
96
103
|
@media (min-width: ${get('breakpoints.1')}) {
|
@@ -144,7 +144,7 @@ describe('AnchoredOverlay', () => {
|
|
144
144
|
})
|
145
145
|
|
146
146
|
it('should render consistently when open', () => {
|
147
|
-
const
|
148
|
-
expect(
|
147
|
+
const {container} = HTMLRender(<AnchoredOverlayTestComponent initiallyOpen={true} />)
|
148
|
+
expect(container).toMatchSnapshot()
|
149
149
|
})
|
150
150
|
})
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import {Union} from 'ts-toolbelt'
|
1
2
|
import {KeyPaths} from '../utils/types/KeyPaths'
|
2
3
|
|
3
4
|
type NestedObject = {
|
@@ -8,6 +9,6 @@ type NestedObject = {
|
|
8
9
|
}
|
9
10
|
}
|
10
11
|
|
11
|
-
export function generatesKeyPathsFromObject(x: KeyPaths<NestedObject
|
12
|
+
export function generatesKeyPathsFromObject(x: Union.Diff<KeyPaths<NestedObject>, 'a' | 'b.b1' | 'b.b2'>): never {
|
12
13
|
return x
|
13
14
|
}
|
@@ -29,16 +29,6 @@ const LabelledTextInputWithTokens: React.FC<TextInputWithTokensProps> = ({onToke
|
|
29
29
|
</>
|
30
30
|
)
|
31
31
|
|
32
|
-
// describe('axe test', () => {
|
33
|
-
// it('should have no axe violations', async () => {
|
34
|
-
// const onRemoveMock = jest.fn()
|
35
|
-
// const {container} = HTMLRender(<LabelledTextInputWithTokens tokens={mockTokens} onTokenRemove={onRemoveMock} />)
|
36
|
-
// const results = await axe(container)
|
37
|
-
// expect(results).toHaveNoViolations()
|
38
|
-
// cleanup()
|
39
|
-
// })
|
40
|
-
// })
|
41
|
-
|
42
32
|
jest.useFakeTimers()
|
43
33
|
|
44
34
|
describe('TextInputWithTokens', () => {
|
@@ -94,9 +94,7 @@ exports[`AnchoredOverlay renders consistently 1`] = `
|
|
94
94
|
`;
|
95
95
|
|
96
96
|
exports[`AnchoredOverlay should render consistently when open 1`] = `
|
97
|
-
|
98
|
-
"asFragment": [Function],
|
99
|
-
"baseElement": .c0 {
|
97
|
+
.c0 {
|
100
98
|
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
|
101
99
|
line-height: 1.5;
|
102
100
|
color: #24292f;
|
@@ -187,146 +185,48 @@ Object {
|
|
187
185
|
outline: none;
|
188
186
|
}
|
189
187
|
|
190
|
-
<
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
</button>
|
207
|
-
<div
|
208
|
-
id="__primerPortalRoot__"
|
209
|
-
style="position: absolute; top: 0px; left: 0px;"
|
210
|
-
>
|
211
|
-
<div
|
212
|
-
style="position: relative; z-index: 1;"
|
213
|
-
>
|
214
|
-
<div
|
215
|
-
class="c2"
|
216
|
-
data-focus-trap="active"
|
217
|
-
height="auto"
|
218
|
-
role="none"
|
219
|
-
style="top: 4px; left: 0px; --styled-overlay-visibility: visible;"
|
220
|
-
width="auto"
|
221
|
-
>
|
222
|
-
<button
|
223
|
-
class="focus-visible"
|
224
|
-
data-focus-visible-added=""
|
225
|
-
tabindex="0"
|
226
|
-
type="button"
|
227
|
-
>
|
228
|
-
Focusable Child
|
229
|
-
</button>
|
230
|
-
</div>
|
231
|
-
</div>
|
232
|
-
</div>
|
233
|
-
</div>
|
234
|
-
</div>
|
235
|
-
</body>,
|
236
|
-
"container": <div>
|
188
|
+
<div>
|
189
|
+
<div
|
190
|
+
class="c0"
|
191
|
+
color="fg.default"
|
192
|
+
data-portal-root="true"
|
193
|
+
font-family="normal"
|
194
|
+
>
|
195
|
+
<button
|
196
|
+
aria-haspopup="true"
|
197
|
+
aria-labelledby="react-aria-1"
|
198
|
+
class="c1"
|
199
|
+
id="react-aria-1"
|
200
|
+
tabindex="0"
|
201
|
+
>
|
202
|
+
Anchor Button
|
203
|
+
</button>
|
237
204
|
<div
|
238
|
-
|
239
|
-
|
240
|
-
data-portal-root="true"
|
241
|
-
font-family="normal"
|
205
|
+
id="__primerPortalRoot__"
|
206
|
+
style="position: absolute; top: 0px; left: 0px;"
|
242
207
|
>
|
243
|
-
<button
|
244
|
-
aria-haspopup="true"
|
245
|
-
aria-labelledby="react-aria-1"
|
246
|
-
class="ButtonBase-sc-181ps9o-0 Button-xjtz72-0 iRqJHc"
|
247
|
-
id="react-aria-1"
|
248
|
-
tabindex="0"
|
249
|
-
>
|
250
|
-
Anchor Button
|
251
|
-
</button>
|
252
208
|
<div
|
253
|
-
|
254
|
-
style="position: absolute; top: 0px; left: 0px;"
|
209
|
+
style="position: relative; z-index: 1;"
|
255
210
|
>
|
256
211
|
<div
|
257
|
-
|
212
|
+
class="c2"
|
213
|
+
data-focus-trap="active"
|
214
|
+
height="auto"
|
215
|
+
role="none"
|
216
|
+
style="top: 4px; left: 0px; --styled-overlay-visibility: visible;"
|
217
|
+
width="auto"
|
258
218
|
>
|
259
|
-
<
|
260
|
-
class="
|
261
|
-
data-focus-
|
262
|
-
|
263
|
-
|
264
|
-
style="top: 4px; left: 0px; --styled-overlay-visibility: visible;"
|
265
|
-
width="auto"
|
219
|
+
<button
|
220
|
+
class="focus-visible"
|
221
|
+
data-focus-visible-added=""
|
222
|
+
tabindex="0"
|
223
|
+
type="button"
|
266
224
|
>
|
267
|
-
|
268
|
-
|
269
|
-
data-focus-visible-added=""
|
270
|
-
tabindex="0"
|
271
|
-
type="button"
|
272
|
-
>
|
273
|
-
Focusable Child
|
274
|
-
</button>
|
275
|
-
</div>
|
225
|
+
Focusable Child
|
226
|
+
</button>
|
276
227
|
</div>
|
277
228
|
</div>
|
278
229
|
</div>
|
279
|
-
</div
|
280
|
-
|
281
|
-
"findAllByAltText": [Function],
|
282
|
-
"findAllByDisplayValue": [Function],
|
283
|
-
"findAllByLabelText": [Function],
|
284
|
-
"findAllByPlaceholderText": [Function],
|
285
|
-
"findAllByRole": [Function],
|
286
|
-
"findAllByTestId": [Function],
|
287
|
-
"findAllByText": [Function],
|
288
|
-
"findAllByTitle": [Function],
|
289
|
-
"findByAltText": [Function],
|
290
|
-
"findByDisplayValue": [Function],
|
291
|
-
"findByLabelText": [Function],
|
292
|
-
"findByPlaceholderText": [Function],
|
293
|
-
"findByRole": [Function],
|
294
|
-
"findByTestId": [Function],
|
295
|
-
"findByText": [Function],
|
296
|
-
"findByTitle": [Function],
|
297
|
-
"getAllByAltText": [Function],
|
298
|
-
"getAllByDisplayValue": [Function],
|
299
|
-
"getAllByLabelText": [Function],
|
300
|
-
"getAllByPlaceholderText": [Function],
|
301
|
-
"getAllByRole": [Function],
|
302
|
-
"getAllByTestId": [Function],
|
303
|
-
"getAllByText": [Function],
|
304
|
-
"getAllByTitle": [Function],
|
305
|
-
"getByAltText": [Function],
|
306
|
-
"getByDisplayValue": [Function],
|
307
|
-
"getByLabelText": [Function],
|
308
|
-
"getByPlaceholderText": [Function],
|
309
|
-
"getByRole": [Function],
|
310
|
-
"getByTestId": [Function],
|
311
|
-
"getByText": [Function],
|
312
|
-
"getByTitle": [Function],
|
313
|
-
"queryAllByAltText": [Function],
|
314
|
-
"queryAllByDisplayValue": [Function],
|
315
|
-
"queryAllByLabelText": [Function],
|
316
|
-
"queryAllByPlaceholderText": [Function],
|
317
|
-
"queryAllByRole": [Function],
|
318
|
-
"queryAllByTestId": [Function],
|
319
|
-
"queryAllByText": [Function],
|
320
|
-
"queryAllByTitle": [Function],
|
321
|
-
"queryByAltText": [Function],
|
322
|
-
"queryByDisplayValue": [Function],
|
323
|
-
"queryByLabelText": [Function],
|
324
|
-
"queryByPlaceholderText": [Function],
|
325
|
-
"queryByRole": [Function],
|
326
|
-
"queryByTestId": [Function],
|
327
|
-
"queryByText": [Function],
|
328
|
-
"queryByTitle": [Function],
|
329
|
-
"rerender": [Function],
|
330
|
-
"unmount": [Function],
|
331
|
-
}
|
230
|
+
</div>
|
231
|
+
</div>
|
332
232
|
`;
|
@@ -2,6 +2,7 @@ import React from 'react'
|
|
2
2
|
import {PositionSettings, getAnchoredPosition, AnchorPosition} from '../behaviors/anchoredPosition'
|
3
3
|
import {useProvidedRefOrCreate} from './useProvidedRefOrCreate'
|
4
4
|
import {useResizeObserver} from './useResizeObserver'
|
5
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
|
5
6
|
|
6
7
|
export interface AnchoredPositionHookSettings extends Partial<PositionSettings> {
|
7
8
|
floatingElementRef?: React.RefObject<Element>
|
@@ -41,7 +42,7 @@ export function useAnchoredPosition(
|
|
41
42
|
[floatingElementRef, anchorElementRef, ...dependencies]
|
42
43
|
)
|
43
44
|
|
44
|
-
|
45
|
+
useLayoutEffect(updatePosition, [updatePosition])
|
45
46
|
|
46
47
|
useResizeObserver(updatePosition)
|
47
48
|
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import {ForwardedRef, useRef} from 'react'
|
2
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
|
2
3
|
|
3
4
|
/**
|
4
5
|
* Creates a ref by combining multiple constituent refs. The ref returned by this hook
|
@@ -11,7 +12,7 @@ import React, {ForwardedRef, useRef} from 'react'
|
|
11
12
|
export function useCombinedRefs<T>(...refs: (ForwardedRef<T> | null | undefined)[]) {
|
12
13
|
const combinedRef = useRef<T | null>(null)
|
13
14
|
|
14
|
-
|
15
|
+
useLayoutEffect(() => {
|
15
16
|
function setRefs(current: T | null = null) {
|
16
17
|
for (const ref of refs) {
|
17
18
|
if (!ref) {
|
@@ -32,7 +33,6 @@ export function useCombinedRefs<T>(...refs: (ForwardedRef<T> | null | undefined)
|
|
32
33
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
33
34
|
setRefs(combinedRef.current)
|
34
35
|
}
|
35
|
-
|
36
36
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
37
37
|
}, [...refs, combinedRef.current])
|
38
38
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import
|
1
|
+
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
|
2
2
|
|
3
3
|
export function useResizeObserver(callback: () => void) {
|
4
|
-
|
4
|
+
useLayoutEffect(() => {
|
5
5
|
const observer = new window.ResizeObserver(() => callback())
|
6
6
|
observer.observe(document.documentElement)
|
7
7
|
return () => {
|
@@ -77,7 +77,7 @@ export const buttonGroup = (args: StrictButtonStyleProps) => (
|
|
77
77
|
export const buttonTableList = (args: ButtonStyleProps) => (
|
78
78
|
<ButtonTableList {...args}>Button Table List</ButtonTableList>
|
79
79
|
)
|
80
|
-
export const disabledButton = (args:
|
80
|
+
export const disabledButton = (args: StrictButtonStyleProps) => {
|
81
81
|
const props = {disabled: true, ...args}
|
82
82
|
return <Button {...props}>Disabled</Button>
|
83
83
|
}
|