@sanity/ui 1.4.0 → 1.5.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/index.cjs.mjs +0 -2
- package/dist/index.d.ts +1 -27
- package/dist/index.esm.js +31 -70
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +30 -71
- package/dist/index.js.map +1 -1
- package/package.json +38 -38
- package/src/components/menu/__workshop__/menuButton.tsx +2 -0
- package/src/components/menu/menuButton.tsx +10 -0
- package/src/primitives/popover/__workshop__/index.ts +0 -5
- package/src/primitives/popover/index.ts +0 -3
- package/src/primitives/popover/popover.tsx +0 -8
- package/src/primitives/popover/__workshop__/PositionStory.tsx +0 -103
- package/src/primitives/popover/popover.test.tsx +0 -164
- package/src/primitives/popover/popoverContext.tsx +0 -9
- package/src/primitives/popover/popoverProvider.tsx +0 -29
- package/src/primitives/popover/types.ts +0 -8
- package/src/primitives/popover/useOnForcedUpdate.ts +0 -15
- package/src/primitives/popover/usePopover.ts +0 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -50,45 +50,45 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@floating-ui/react-dom": "1.1.1",
|
|
53
|
-
"@sanity/color": "^2.2.
|
|
54
|
-
"@sanity/icons": "^2.
|
|
55
|
-
"csstype": "^3.1.
|
|
56
|
-
"framer-motion": "^10.
|
|
53
|
+
"@sanity/color": "^2.2.5",
|
|
54
|
+
"@sanity/icons": "^2.3.1",
|
|
55
|
+
"csstype": "^3.1.2",
|
|
56
|
+
"framer-motion": "^10.12.16",
|
|
57
57
|
"react-refractor": "^2.1.7"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@babel/core": "^7.
|
|
61
|
-
"@babel/preset-env": "^7.
|
|
62
|
-
"@babel/preset-react": "^7.
|
|
63
|
-
"@babel/preset-typescript": "^7.
|
|
64
|
-
"@commitlint/cli": "^17.
|
|
65
|
-
"@commitlint/config-conventional": "^17.
|
|
60
|
+
"@babel/core": "^7.22.1",
|
|
61
|
+
"@babel/preset-env": "^7.22.4",
|
|
62
|
+
"@babel/preset-react": "^7.22.3",
|
|
63
|
+
"@babel/preset-typescript": "^7.21.5",
|
|
64
|
+
"@commitlint/cli": "^17.6.5",
|
|
65
|
+
"@commitlint/config-conventional": "^17.6.5",
|
|
66
66
|
"@juggle/resize-observer": "^3.4.0",
|
|
67
|
-
"@sanity/pkg-utils": "^2.2
|
|
68
|
-
"@sanity/semantic-release-preset": "^4.1.
|
|
67
|
+
"@sanity/pkg-utils": "^2.3.2",
|
|
68
|
+
"@sanity/semantic-release-preset": "^4.1.1",
|
|
69
69
|
"@sanity/ui-workshop": "^1.2.1",
|
|
70
|
-
"@testing-library/dom": "^9.
|
|
70
|
+
"@testing-library/dom": "^9.3.0",
|
|
71
71
|
"@testing-library/jest-dom": "^5.16.5",
|
|
72
72
|
"@testing-library/react": "^14.0.0",
|
|
73
|
-
"@types/jest": "^29.
|
|
73
|
+
"@types/jest": "^29.5.2",
|
|
74
74
|
"@types/jest-axe": "^3.5.5",
|
|
75
|
-
"@types/node": "^18.
|
|
76
|
-
"@types/react": "^18.
|
|
77
|
-
"@types/react-dom": "^18.
|
|
78
|
-
"@types/react-is": "^18.
|
|
75
|
+
"@types/node": "^18.16.16",
|
|
76
|
+
"@types/react": "^18.2.9",
|
|
77
|
+
"@types/react-dom": "^18.2.4",
|
|
78
|
+
"@types/react-is": "^18.2.0",
|
|
79
79
|
"@types/refractor": "^3.0.2",
|
|
80
80
|
"@types/styled-components": "^5.1.26",
|
|
81
|
-
"@types/testing-library__jest-dom": "^5.14.
|
|
82
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
83
|
-
"@typescript-eslint/parser": "^5.
|
|
81
|
+
"@types/testing-library__jest-dom": "^5.14.6",
|
|
82
|
+
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
|
83
|
+
"@typescript-eslint/parser": "^5.59.9",
|
|
84
84
|
"commitizen": "^4.3.0",
|
|
85
|
-
"cypress": "^12.
|
|
86
|
-
"cypress-real-events": "^1.
|
|
85
|
+
"cypress": "^12.14.0",
|
|
86
|
+
"cypress-real-events": "^1.8.1",
|
|
87
87
|
"cz-conventional-changelog": "^3.3.0",
|
|
88
|
-
"esbuild": "^0.17.
|
|
88
|
+
"esbuild": "^0.17.19",
|
|
89
89
|
"esbuild-register": "^3.4.2",
|
|
90
|
-
"eslint": "^8.
|
|
91
|
-
"eslint-config-prettier": "^8.
|
|
90
|
+
"eslint": "^8.42.0",
|
|
91
|
+
"eslint-config-prettier": "^8.8.0",
|
|
92
92
|
"eslint-plugin-import": "^2.27.5",
|
|
93
93
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
94
94
|
"eslint-plugin-prettier": "^4.2.1",
|
|
@@ -96,22 +96,22 @@
|
|
|
96
96
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
97
97
|
"http-server": "^14.1.1",
|
|
98
98
|
"husky": "^8.0.3",
|
|
99
|
-
"jest": "^29.
|
|
100
|
-
"jest-axe": "^7.0.
|
|
101
|
-
"jest-environment-jsdom": "^29.
|
|
102
|
-
"lint-staged": "^13.
|
|
103
|
-
"module-alias": "^2.2.
|
|
99
|
+
"jest": "^29.5.0",
|
|
100
|
+
"jest-axe": "^7.0.1",
|
|
101
|
+
"jest-environment-jsdom": "^29.5.0",
|
|
102
|
+
"lint-staged": "^13.2.2",
|
|
103
|
+
"module-alias": "^2.2.3",
|
|
104
104
|
"npm-run-all": "^4.1.5",
|
|
105
|
-
"prettier": "^2.8.
|
|
105
|
+
"prettier": "^2.8.8",
|
|
106
106
|
"react": "^18.2.0",
|
|
107
107
|
"react-dom": "^18.2.0",
|
|
108
108
|
"react-is": "^18.2.0",
|
|
109
|
-
"rimraf": "^5.0.
|
|
110
|
-
"semantic-release": "^21.0.
|
|
109
|
+
"rimraf": "^5.0.1",
|
|
110
|
+
"semantic-release": "^21.0.3",
|
|
111
111
|
"start-server-and-test": "^2.0.0",
|
|
112
|
-
"styled-components": "^5.3.
|
|
113
|
-
"tsconfig-paths": "^4.
|
|
114
|
-
"typescript": "^5.
|
|
112
|
+
"styled-components": "^5.3.11",
|
|
113
|
+
"tsconfig-paths": "^4.2.0",
|
|
114
|
+
"typescript": "^5.1.3"
|
|
115
115
|
},
|
|
116
116
|
"peerDependencies": {
|
|
117
117
|
"react": "^18",
|
|
@@ -21,6 +21,7 @@ export interface MenuButtonProps {
|
|
|
21
21
|
id: string
|
|
22
22
|
menu?: React.ReactElement
|
|
23
23
|
onClose?: () => void
|
|
24
|
+
onOpen?: () => void
|
|
24
25
|
/**
|
|
25
26
|
* @deprecated Use `popover={{placement: 'top'}}` instead.
|
|
26
27
|
*/
|
|
@@ -59,6 +60,7 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
59
60
|
id,
|
|
60
61
|
menu: menuProp,
|
|
61
62
|
onClose,
|
|
63
|
+
onOpen,
|
|
62
64
|
placement: deprecated_placement,
|
|
63
65
|
popoverScheme: deprecated_popoverScheme,
|
|
64
66
|
portal: deprecated_portal = true,
|
|
@@ -72,6 +74,14 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
72
74
|
const [menuElements, setChildMenuElements] = useState<HTMLElement[]>([])
|
|
73
75
|
const openRef = useRef<boolean>(open)
|
|
74
76
|
|
|
77
|
+
// Notify consumers when the menu opens
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (onOpen && open && !openRef.current) {
|
|
80
|
+
onOpen()
|
|
81
|
+
}
|
|
82
|
+
}, [onOpen, open])
|
|
83
|
+
|
|
84
|
+
// Notify consumers when the menu closes
|
|
75
85
|
useEffect(() => {
|
|
76
86
|
if (onClose && !open && openRef.current) {
|
|
77
87
|
onClose()
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
} from './constants'
|
|
24
24
|
import {size} from './floating-ui/size'
|
|
25
25
|
import {PopoverCard} from './popoverCard'
|
|
26
|
-
import {useOnForcedUpdate} from './useOnForcedUpdate'
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
28
|
* @public
|
|
@@ -201,15 +200,10 @@ export const Popover = memo(
|
|
|
201
200
|
placement,
|
|
202
201
|
reference: referenceRef,
|
|
203
202
|
floating: floatingRef,
|
|
204
|
-
update: floatingUpdate,
|
|
205
203
|
middlewareData,
|
|
206
204
|
strategy,
|
|
207
205
|
} = useFloating(floatingProps)
|
|
208
206
|
|
|
209
|
-
const handleForcedUpdate = useCallback(() => {
|
|
210
|
-
floatingUpdate()
|
|
211
|
-
}, [floatingUpdate])
|
|
212
|
-
|
|
213
207
|
const referenceHidden = middlewareData.hide?.referenceHidden
|
|
214
208
|
|
|
215
209
|
const arrowX = middlewareData.arrow?.x
|
|
@@ -253,8 +247,6 @@ export const Popover = memo(
|
|
|
253
247
|
referenceRef(referenceElement || null)
|
|
254
248
|
}, [referenceRef, referenceElement])
|
|
255
249
|
|
|
256
|
-
useOnForcedUpdate(handleForcedUpdate)
|
|
257
|
-
|
|
258
250
|
if (disabled) {
|
|
259
251
|
return childProp || <></>
|
|
260
252
|
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import {useBoolean} from '@sanity/ui-workshop'
|
|
2
|
-
import {useCallback, useMemo, useState} from 'react'
|
|
3
|
-
import {BoundaryElementProvider} from '../../../utils'
|
|
4
|
-
import {Button} from '../../button'
|
|
5
|
-
import {Card} from '../../card'
|
|
6
|
-
import {Flex} from '../../flex'
|
|
7
|
-
import {Text} from '../../text'
|
|
8
|
-
import {Popover, PopoverProps} from '../popover'
|
|
9
|
-
import {PopoverProvider} from '../popoverProvider'
|
|
10
|
-
import {usePopover} from '../usePopover'
|
|
11
|
-
|
|
12
|
-
function PopoverComponent({
|
|
13
|
-
referenceElement,
|
|
14
|
-
boundaryElement,
|
|
15
|
-
}: {
|
|
16
|
-
referenceElement: PopoverProps['referenceElement']
|
|
17
|
-
boundaryElement: PopoverProps['boundaryElement']
|
|
18
|
-
}) {
|
|
19
|
-
return (
|
|
20
|
-
<Popover
|
|
21
|
-
open
|
|
22
|
-
content={
|
|
23
|
-
<Card padding={5} radius={3}>
|
|
24
|
-
<Text weight="semibold" muted>
|
|
25
|
-
I should follow my reference element <br />
|
|
26
|
-
when the parent container is resized.
|
|
27
|
-
</Text>
|
|
28
|
-
</Card>
|
|
29
|
-
}
|
|
30
|
-
referenceElement={referenceElement}
|
|
31
|
-
boundaryElement={boundaryElement}
|
|
32
|
-
/>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default function PositionStory() {
|
|
37
|
-
return (
|
|
38
|
-
<PopoverProvider>
|
|
39
|
-
<InnerStory />
|
|
40
|
-
</PopoverProvider>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function InnerStory() {
|
|
45
|
-
const [size, setSize] = useState(0.5)
|
|
46
|
-
const [referenceElement, setReferenceElement] = useState<PopoverProps['referenceElement']>(null)
|
|
47
|
-
const [boundaryElement, setBoundaryElement] = useState<PopoverProps['boundaryElement']>(null)
|
|
48
|
-
const updatePositionOnClick = useBoolean('Force popover update on size change', false, 'Props')
|
|
49
|
-
const {forceUpdate} = usePopover()
|
|
50
|
-
|
|
51
|
-
// Random number between 0.2 and 5
|
|
52
|
-
const handleSetSize = useCallback(() => {
|
|
53
|
-
const s = Math.random() * (0.5 - 0.2) + 0.2
|
|
54
|
-
|
|
55
|
-
setSize(s)
|
|
56
|
-
|
|
57
|
-
if (updatePositionOnClick) {
|
|
58
|
-
forceUpdate()
|
|
59
|
-
}
|
|
60
|
-
}, [updatePositionOnClick])
|
|
61
|
-
|
|
62
|
-
const element = useMemo(() => {
|
|
63
|
-
return (
|
|
64
|
-
<Card
|
|
65
|
-
as="span"
|
|
66
|
-
border
|
|
67
|
-
radius={2}
|
|
68
|
-
style={{display: 'inline', padding: '0.4, 1'}}
|
|
69
|
-
ref={setReferenceElement}
|
|
70
|
-
tone="primary"
|
|
71
|
-
>
|
|
72
|
-
nunc
|
|
73
|
-
</Card>
|
|
74
|
-
)
|
|
75
|
-
}, [])
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<>
|
|
79
|
-
<PopoverComponent referenceElement={referenceElement} boundaryElement={boundaryElement} />
|
|
80
|
-
|
|
81
|
-
<BoundaryElementProvider element={boundaryElement as HTMLDivElement}>
|
|
82
|
-
<Flex height="fill">
|
|
83
|
-
<Card borderRight flex={size} tone="transparent">
|
|
84
|
-
<Flex align="center" justify="center" height="fill">
|
|
85
|
-
<Button text="Change size" onClick={handleSetSize} />
|
|
86
|
-
</Flex>
|
|
87
|
-
</Card>
|
|
88
|
-
|
|
89
|
-
<Card flex={1} ref={setBoundaryElement}>
|
|
90
|
-
<Flex height="fill" padding={5}>
|
|
91
|
-
<Text>
|
|
92
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultricies, nisl ut
|
|
93
|
-
aliquet ultricies, nunc sapien ultricies tortor, nec tincidunt elit risus ac nunc.
|
|
94
|
-
Nulla facilisi. Sed aliquam, {element} eget aliquam ultricies, diam diam aliquam
|
|
95
|
-
augue, eget ultricies nisl nunc eget nunc. Nulla facilisi. Sed aliquam,
|
|
96
|
-
</Text>
|
|
97
|
-
</Flex>
|
|
98
|
-
</Card>
|
|
99
|
-
</Flex>
|
|
100
|
-
</BoundaryElementProvider>
|
|
101
|
-
</>
|
|
102
|
-
)
|
|
103
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/** @jest-environment jsdom */
|
|
2
|
-
|
|
3
|
-
import {fireEvent, waitFor, screen} from '@testing-library/react'
|
|
4
|
-
import {startTransition, useCallback, useEffect, useMemo, useState} from 'react'
|
|
5
|
-
import {render} from '../../../test'
|
|
6
|
-
import {PopoverContext} from './popoverContext'
|
|
7
|
-
import {PopoverContextValue} from './types'
|
|
8
|
-
import {useOnForcedUpdate} from './useOnForcedUpdate'
|
|
9
|
-
import {usePopover} from './usePopover'
|
|
10
|
-
|
|
11
|
-
describe('components/toast', () => {
|
|
12
|
-
describe('usePopover', () => {
|
|
13
|
-
it('should get context value', async () => {
|
|
14
|
-
const log = jest.fn()
|
|
15
|
-
|
|
16
|
-
function Debug() {
|
|
17
|
-
const popover = usePopover()
|
|
18
|
-
|
|
19
|
-
log(popover)
|
|
20
|
-
|
|
21
|
-
return <>debug</>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function Root() {
|
|
25
|
-
const value: PopoverContextValue = {
|
|
26
|
-
version: 0.0,
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
28
|
-
forceUpdate: () => {},
|
|
29
|
-
lastUpdateId: null,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<PopoverContext.Provider value={value}>
|
|
34
|
-
<Debug />
|
|
35
|
-
</PopoverContext.Provider>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
render(<Root />)
|
|
40
|
-
|
|
41
|
-
expect(log.mock.calls[0][0].version).toBe(0.0)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('should fail when no context value is provided', async () => {
|
|
45
|
-
const log = jest.fn()
|
|
46
|
-
|
|
47
|
-
function Debug() {
|
|
48
|
-
try {
|
|
49
|
-
usePopover()
|
|
50
|
-
} catch (err) {
|
|
51
|
-
log(err)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function Root() {
|
|
58
|
-
const value = undefined
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<PopoverContext.Provider value={value as any}>
|
|
62
|
-
<Debug />
|
|
63
|
-
</PopoverContext.Provider>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
render(<Root />)
|
|
68
|
-
|
|
69
|
-
expect(log.mock.calls[0][0].message).toEqual('usePopover(): missing context value')
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('should fail when context value is not compatible', async () => {
|
|
73
|
-
const log = jest.fn()
|
|
74
|
-
|
|
75
|
-
function Debug() {
|
|
76
|
-
try {
|
|
77
|
-
usePopover()
|
|
78
|
-
} catch (err) {
|
|
79
|
-
log(err)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return null
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function Root() {
|
|
86
|
-
// NOTE: we’re testing this because the context value may be a function in the future
|
|
87
|
-
const value = () => {
|
|
88
|
-
return {version: 1}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<PopoverContext.Provider value={value as any}>
|
|
93
|
-
<Debug />
|
|
94
|
-
</PopoverContext.Provider>
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
render(<Root />)
|
|
99
|
-
|
|
100
|
-
expect(log.mock.calls[0][0].message).toEqual(
|
|
101
|
-
'usePopover(): the context value is not compatible'
|
|
102
|
-
)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('should trigger hook when forceUpdate is called', async () => {
|
|
106
|
-
const log = jest.fn()
|
|
107
|
-
const forcedCallback = jest.fn()
|
|
108
|
-
|
|
109
|
-
function Popover() {
|
|
110
|
-
useOnForcedUpdate(forcedCallback)
|
|
111
|
-
|
|
112
|
-
return null
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function Debug() {
|
|
116
|
-
const popover = usePopover()
|
|
117
|
-
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
log(popover)
|
|
120
|
-
}, [popover])
|
|
121
|
-
|
|
122
|
-
const update = useCallback(() => {
|
|
123
|
-
popover.forceUpdate()
|
|
124
|
-
}, [popover])
|
|
125
|
-
|
|
126
|
-
return <button onClick={update}>Force position update</button>
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function Root() {
|
|
130
|
-
const [lastUpdateId, setLastUpdateId] = useState<string | null>(null)
|
|
131
|
-
const forceUpdate = useCallback(() => {
|
|
132
|
-
startTransition(() => {
|
|
133
|
-
setLastUpdateId('newid')
|
|
134
|
-
})
|
|
135
|
-
}, [])
|
|
136
|
-
const value: PopoverContextValue = useMemo(() => {
|
|
137
|
-
return {
|
|
138
|
-
version: 0.0,
|
|
139
|
-
forceUpdate,
|
|
140
|
-
lastUpdateId,
|
|
141
|
-
}
|
|
142
|
-
}, [forceUpdate, lastUpdateId])
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<PopoverContext.Provider value={value}>
|
|
146
|
-
<Debug />
|
|
147
|
-
<Popover />
|
|
148
|
-
</PopoverContext.Provider>
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
render(<Root />)
|
|
153
|
-
|
|
154
|
-
fireEvent.click(screen.getByText('Force position update'))
|
|
155
|
-
|
|
156
|
-
await waitFor(() => {
|
|
157
|
-
expect(log).toHaveBeenCalledTimes(3)
|
|
158
|
-
expect(log.mock.calls[0][0].lastUpdateId).toBeNull()
|
|
159
|
-
expect(log.mock.calls[2][0].lastUpdateId).not.toBeNull()
|
|
160
|
-
expect(forcedCallback).toHaveBeenCalledTimes(1)
|
|
161
|
-
})
|
|
162
|
-
})
|
|
163
|
-
})
|
|
164
|
-
})
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import {createContext} from 'react'
|
|
2
|
-
import {globalScope} from '../../lib/globalScope'
|
|
3
|
-
import type {PopoverContextValue} from './types'
|
|
4
|
-
|
|
5
|
-
const key = Symbol.for('@sanity/ui/context/popover')
|
|
6
|
-
|
|
7
|
-
globalScope[key] = globalScope[key] || createContext<PopoverContextValue | null>(null)
|
|
8
|
-
|
|
9
|
-
export const PopoverContext: React.Context<PopoverContextValue | null> = globalScope[key]
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React, {useState, useCallback, useMemo} from 'react'
|
|
2
|
-
import {PopoverContext} from './popoverContext'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export interface PopoverProviderProps {
|
|
8
|
-
children?: React.ReactNode
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
export const PopoverProvider = ({children}: PopoverProviderProps): React.ReactElement => {
|
|
15
|
-
const [lastUpdateId, setUpdateId] = useState<string | null>(null)
|
|
16
|
-
|
|
17
|
-
const forceUpdate = useCallback(() => {
|
|
18
|
-
// Generate a new random ID
|
|
19
|
-
const newId = Math.random().toString(36).substr(2, 9)
|
|
20
|
-
setUpdateId(newId)
|
|
21
|
-
}, [])
|
|
22
|
-
|
|
23
|
-
const value = useMemo(
|
|
24
|
-
() => ({version: 0.0, lastUpdateId, forceUpdate}),
|
|
25
|
-
[lastUpdateId, forceUpdate]
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
return <PopoverContext.Provider value={value}>{children}</PopoverContext.Provider>
|
|
29
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import {useContext, useEffect} from 'react'
|
|
2
|
-
import {PopoverContext} from './popoverContext'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export const useOnForcedUpdate = (eventHandler: () => void): void => {
|
|
8
|
-
const contextValue = useContext(PopoverContext)
|
|
9
|
-
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
if (contextValue?.lastUpdateId !== null) {
|
|
12
|
-
eventHandler?.()
|
|
13
|
-
}
|
|
14
|
-
}, [contextValue?.lastUpdateId])
|
|
15
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {useContext} from 'react'
|
|
2
|
-
import {isRecord} from '../../lib/isRecord'
|
|
3
|
-
import {PopoverContext} from './popoverContext'
|
|
4
|
-
import type {PopoverContextValue} from './types'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
export function usePopover(): PopoverContextValue {
|
|
10
|
-
const value = useContext(PopoverContext)
|
|
11
|
-
|
|
12
|
-
if (!value) {
|
|
13
|
-
throw new Error('usePopover(): missing context value')
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// NOTE: This check is for future-compatiblity
|
|
17
|
-
// - If the value is not an object, it’s not compatible with the current version
|
|
18
|
-
// - If the value is an object, but doesn’t have `version: 0.0`, it’s not compatible with the current version
|
|
19
|
-
if (!isRecord(value) || value.version !== 0.0) {
|
|
20
|
-
throw new Error('usePopover(): the context value is not compatible')
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return value
|
|
24
|
-
}
|