@sanity/ui 1.1.0-beta.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +1 -1
  2. package/dist/index.cjs.mjs +120 -0
  3. package/dist/index.d.ts +26 -4
  4. package/dist/{index.cjs → index.esm.js} +1987 -1946
  5. package/dist/index.esm.js.map +1 -0
  6. package/dist/index.js +2114 -1819
  7. package/dist/index.js.map +1 -1
  8. package/package.json +47 -44
  9. package/src/components/dialog/__workshop__/activate.tsx +134 -0
  10. package/src/components/dialog/__workshop__/index.ts +3 -0
  11. package/src/components/dialog/__workshop__/nested.tsx +14 -3
  12. package/src/components/dialog/__workshop__/panes.tsx +86 -0
  13. package/src/components/dialog/__workshop__/wrapped.tsx +78 -0
  14. package/src/components/dialog/dialog.tsx +110 -25
  15. package/src/components/toast/toastProvider.tsx +55 -52
  16. package/src/constants.ts +2 -2
  17. package/src/helpers/element.ts +7 -0
  18. package/src/hooks/index.ts +1 -0
  19. package/src/hooks/useArrayProp.ts +2 -1
  20. package/src/hooks/useMediaIndex/useMediaIndex.test.tsx +31 -0
  21. package/src/hooks/useMediaIndex/useMediaIndex.ts +98 -6
  22. package/src/hooks/useMounted.ts +14 -0
  23. package/src/hooks/usePrefersDark.hydration.test.tsx +56 -0
  24. package/src/hooks/usePrefersDark.test.tsx +18 -0
  25. package/src/hooks/usePrefersDark.ts +51 -18
  26. package/src/hooks/usePrefersReducedMotion.hydration.test.tsx +56 -0
  27. package/src/hooks/usePrefersReducedMotion.test.tsx +18 -0
  28. package/src/hooks/usePrefersReducedMotion.ts +62 -0
  29. package/src/observers/resizeObserver.ts +1 -1
  30. package/src/primitives/code/styles.ts +6 -0
  31. package/src/primitives/heading/styles.ts +6 -0
  32. package/src/primitives/label/styles.ts +6 -0
  33. package/src/primitives/popover/__workshop__/OpenOnMountStory.tsx +11 -0
  34. package/src/primitives/popover/__workshop__/index.ts +5 -0
  35. package/src/primitives/text/styles.ts +6 -0
  36. package/src/utils/layer/__workshop__/_debug.tsx +9 -3
  37. package/src/utils/layer/__workshop__/index.ts +3 -3
  38. package/src/utils/layer/__workshop__/multipleRoots.tsx +2 -1
  39. package/src/utils/layer/__workshop__/{plain.tsx → nested.tsx} +14 -4
  40. package/src/utils/layer/getLayerContext.test.ts +30 -0
  41. package/src/utils/layer/getLayerContext.ts +21 -0
  42. package/src/utils/layer/layer.test.tsx +1 -0
  43. package/src/utils/layer/layer.tsx +49 -7
  44. package/src/utils/layer/layerContext.ts +2 -2
  45. package/src/utils/layer/layerProvider.tsx +73 -12
  46. package/src/utils/layer/types.ts +3 -4
  47. package/src/utils/layer/useLayer.ts +9 -8
  48. package/src/utils/portal/portalContext.ts +1 -1
  49. package/src/utils/portal/portalProvider.tsx +1 -1
  50. package/dist/index.cjs.map +0 -1
  51. package/src/hooks/useMediaIndex/lib/media.ts +0 -88
@@ -1,5 +1,6 @@
1
1
  import {useCallback, useContext, useEffect, useMemo, useState} from 'react'
2
2
  import {useMediaIndex, useArrayProp} from '../../hooks'
3
+ import {getLayerContext} from './getLayerContext'
3
4
  import {LayerContext} from './layerContext'
4
5
  import {LayerContextValue} from './types'
5
6
 
@@ -16,30 +17,90 @@ export interface LayerProviderProps {
16
17
  */
17
18
  export function LayerProvider(props: LayerProviderProps): React.ReactElement {
18
19
  const {children, zOffset: zOffsetProp = 0} = props
19
- const parent = useContext(LayerContext)
20
+
21
+ // Get parent context values
22
+ const parentContextValue = useContext(LayerContext)
23
+ const parent = parentContextValue && getLayerContext(parentContextValue)
24
+ const parentRegisterChild = parent?.registerChild
25
+ const parentLevel = parent?.level ?? 0
26
+
27
+ // Get level
28
+ const level = parentLevel + 1
29
+
30
+ // Get z-index offset
20
31
  const zOffset = useArrayProp(zOffsetProp)
32
+
33
+ // Get responsive z-index value
21
34
  const maxMediaIndex = zOffset.length - 1
22
35
  const mediaIndex = Math.min(useMediaIndex(), maxMediaIndex)
23
36
  const zIndex = parent ? parent.zIndex + zOffset[mediaIndex] : zOffset[mediaIndex]
37
+
38
+ // A state value that is used to keep track of the number of child layers on each level
39
+ const [, setChildLayers] = useState<Record<number, number>>({})
40
+
41
+ // A state value that is used to keep track of the number of child levels
24
42
  const [size, setSize] = useState(0)
25
43
 
26
- const registerChild = useCallback(() => {
27
- setSize((v) => v + 1)
44
+ const isTopLayer = size === 0
28
45
 
29
- return () => setSize((v) => v - 1)
30
- }, [])
46
+ const registerChild = useCallback(
47
+ (childLevel?: number) => {
48
+ // Register child layers to the parent layer
49
+ const parentDispose = parentRegisterChild?.(childLevel)
31
50
 
32
- const parentRegisterChild = parent?.registerChild
51
+ if (childLevel !== undefined) {
52
+ setChildLayers((state) => {
53
+ const prevLen = state[childLevel] ?? 0
54
+ const nextState = {...state, [childLevel]: prevLen + 1}
33
55
 
34
- useEffect(() => {
35
- if (!parentRegisterChild) return
56
+ setSize(Object.keys(nextState).length)
57
+
58
+ return nextState
59
+ })
60
+ } else {
61
+ // Legacy behavior: if no child level is provided, increment the size by 1
62
+ setSize((v) => v + 1)
63
+ }
64
+
65
+ return () => {
66
+ if (childLevel !== undefined) {
67
+ setChildLayers((state) => {
68
+ const nextState = {...state}
69
+
70
+ if (nextState[childLevel] === 1) {
71
+ delete nextState[childLevel]
72
+
73
+ setSize(Object.keys(nextState).length)
74
+ } else {
75
+ nextState[childLevel] -= 1
76
+ }
77
+
78
+ return nextState
79
+ })
80
+ } else {
81
+ // Legacy behavior: if no child level is provided, decrement the size by 1
82
+ setSize((v) => v - 1)
83
+ }
84
+
85
+ parentDispose?.()
86
+ }
87
+ },
88
+ [parentRegisterChild]
89
+ )
36
90
 
37
- return parentRegisterChild()
38
- }, [parentRegisterChild])
91
+ // Register this layer on mount
92
+ useEffect(() => parentRegisterChild?.(level), [level, parentRegisterChild])
39
93
 
40
94
  const value: LayerContextValue = useMemo(
41
- () => ({version: 0.0, isTopLayer: size === 0, registerChild, size, zIndex}),
42
- [size, registerChild, zIndex]
95
+ () => ({
96
+ version: 0.0,
97
+ isTopLayer,
98
+ level,
99
+ registerChild,
100
+ size,
101
+ zIndex,
102
+ }),
103
+ [isTopLayer, level, registerChild, size, zIndex]
43
104
  )
44
105
 
45
106
  return <LayerContext.Provider value={value}>{children}</LayerContext.Provider>
@@ -1,10 +1,9 @@
1
- /**
2
- * @public
3
- */
1
+ /** @public */
4
2
  export interface LayerContextValue {
5
3
  version: 0.0
6
4
  isTopLayer: boolean
7
- registerChild: () => () => void
5
+ level?: number
6
+ registerChild: (childLevel?: number) => () => void
8
7
  size: number
9
8
  zIndex: number
10
9
  }
@@ -1,5 +1,5 @@
1
1
  import {useContext} from 'react'
2
- import {isRecord} from '../../lib/isRecord'
2
+ import {getLayerContext} from './getLayerContext'
3
3
  import {LayerContext} from './layerContext'
4
4
  import {LayerContextValue} from './types'
5
5
 
@@ -13,12 +13,13 @@ export function useLayer(): LayerContextValue {
13
13
  throw new Error('useLayer(): missing context value')
14
14
  }
15
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('useLayer(): the context value is not compatible')
16
+ try {
17
+ return getLayerContext(value)
18
+ } catch (err) {
19
+ if (err instanceof Error) {
20
+ throw new Error(`useLayer(): ${err.message}`)
21
+ } else {
22
+ throw new Error(`useLayer(): ${err}`)
23
+ }
21
24
  }
22
-
23
- return value
24
25
  }
@@ -11,7 +11,7 @@ export const defaultContextValue: PortalContextValue = {
11
11
  version: 0.0,
12
12
  boundaryElement: null,
13
13
  get element() {
14
- if (typeof window === 'undefined') {
14
+ if (typeof document === 'undefined') {
15
15
  return null
16
16
  }
17
17
 
@@ -19,7 +19,7 @@ export interface PortalProviderProps {
19
19
  __unstable_elements?: Record<string, HTMLElement | null | undefined>
20
20
  }
21
21
 
22
- const __BROWSER__ = typeof window !== 'undefined'
22
+ const __BROWSER__ = typeof document !== 'undefined'
23
23
 
24
24
  /**
25
25
  * @public