@sanity/ui 2.3.7-canary.0 → 2.4.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 (67) hide show
  1. package/dist/_chunks-cjs/getTheme_v2.js +319 -0
  2. package/dist/_chunks-cjs/getTheme_v2.js.map +1 -0
  3. package/dist/_chunks-es/getTheme_v2.mjs +320 -0
  4. package/dist/_chunks-es/getTheme_v2.mjs.map +1 -0
  5. package/dist/_legacy/getTheme_v2.esm.js +320 -0
  6. package/dist/_legacy/getTheme_v2.esm.js.map +1 -0
  7. package/dist/index.d.mts +2 -13
  8. package/dist/index.d.ts +2 -13
  9. package/dist/index.esm.js +2301 -2237
  10. package/dist/index.esm.js.map +1 -1
  11. package/dist/index.js +2304 -2241
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +2301 -2237
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/theme.esm.js +4 -315
  16. package/dist/theme.esm.js.map +1 -1
  17. package/dist/theme.js +36 -349
  18. package/dist/theme.js.map +1 -1
  19. package/dist/theme.mjs +4 -315
  20. package/dist/theme.mjs.map +1 -1
  21. package/package.json +35 -31
  22. package/src/core/components/autocomplete/autocomplete.tsx +34 -31
  23. package/src/core/components/breadcrumbs/breadcrumbs.tsx +2 -3
  24. package/src/core/components/dialog/dialog.tsx +12 -23
  25. package/src/core/components/hotkeys/hotkeys.tsx +3 -3
  26. package/src/core/components/menu/menu.tsx +1 -5
  27. package/src/core/components/menu/menuButton.tsx +32 -17
  28. package/src/core/components/menu/menuGroup.tsx +5 -7
  29. package/src/core/components/menu/menuItem.tsx +6 -10
  30. package/src/core/components/skeleton/skeleton.tsx +11 -5
  31. package/src/core/components/skeleton/textSkeleton.tsx +7 -6
  32. package/src/core/components/toast/styles.ts +61 -0
  33. package/src/core/components/toast/toast.tsx +11 -16
  34. package/src/core/components/toast/toastProvider.tsx +25 -26
  35. package/src/core/components/tree/treeItem.tsx +44 -31
  36. package/src/core/hooks/useArrayProp.ts +10 -11
  37. package/src/core/primitives/avatar/avatar.tsx +15 -11
  38. package/src/core/primitives/avatar/avatarCounter.tsx +17 -11
  39. package/src/core/primitives/avatar/avatarStack.tsx +7 -3
  40. package/src/core/primitives/badge/badge.tsx +4 -7
  41. package/src/core/primitives/box/box.tsx +27 -53
  42. package/src/core/primitives/button/button.tsx +12 -11
  43. package/src/core/primitives/card/card.tsx +9 -17
  44. package/src/core/primitives/code/code.tsx +3 -4
  45. package/src/core/primitives/container/container.tsx +11 -4
  46. package/src/core/primitives/flex/flex.tsx +7 -13
  47. package/src/core/primitives/grid/grid.tsx +10 -19
  48. package/src/core/primitives/heading/heading.tsx +4 -7
  49. package/src/core/primitives/inline/inline.tsx +2 -3
  50. package/src/core/primitives/kbd/kbd.tsx +3 -4
  51. package/src/core/primitives/label/label.tsx +4 -7
  52. package/src/core/primitives/popover/popover.tsx +49 -49
  53. package/src/core/primitives/select/select.tsx +6 -12
  54. package/src/core/primitives/stack/stack.tsx +3 -4
  55. package/src/core/primitives/text/text.tsx +4 -7
  56. package/src/core/primitives/textArea/textArea.tsx +6 -12
  57. package/src/core/primitives/textInput/textInput.tsx +5 -6
  58. package/src/core/primitives/tooltip/tooltip.tsx +7 -14
  59. package/src/core/theme/themeProvider.tsx +6 -4
  60. package/src/core/utils/elementQuery/elementQuery.tsx +3 -4
  61. package/src/core/utils/layer/getLayerContext.test.ts +4 -0
  62. package/src/core/utils/layer/layer.test.tsx +2 -0
  63. package/src/core/utils/layer/layerProvider.tsx +43 -35
  64. package/src/core/utils/layer/types.ts +1 -0
  65. package/dist/index.compiled.mjs +0 -7488
  66. package/dist/index.compiled.mjs.map +0 -1
  67. package/src/core/components/tree/treeItem.styles.ts +0 -21
@@ -0,0 +1,61 @@
1
+ import {styled, keyframes, css} from 'styled-components'
2
+ import {ThemeColorStateToneKey, getTheme_v2} from '../../../theme'
3
+ import {POPOVER_MOTION_CONTENT_OPACITY_PROPERTY} from '../../constants'
4
+ import {Flex} from '../../primitives'
5
+ import {ThemeProps} from '../../styles'
6
+
7
+ export const TextBox = styled(Flex)`
8
+ overflow-x: auto;
9
+ `
10
+
11
+ const loadingAnimation = keyframes`
12
+ 0% {
13
+ width: 0;
14
+ }
15
+ 100% {
16
+ width: 100%;
17
+ }
18
+ `
19
+
20
+ const LOADING_BAR_HEIGHT = 2
21
+
22
+ export function rootStyles(
23
+ props: {$duration?: number; tone: ThemeColorStateToneKey} & ThemeProps,
24
+ ): ReturnType<typeof css> {
25
+ const {color} = getTheme_v2(props.theme)
26
+
27
+ const loadingBarColor = color.button.default[props.tone].enabled.bg
28
+
29
+ if (!props.$duration)
30
+ return css`
31
+ pointer-events: all;
32
+ & > * {
33
+ opacity: var(${POPOVER_MOTION_CONTENT_OPACITY_PROPERTY}, 1);
34
+ will-change: opacity;
35
+ }
36
+ `
37
+
38
+ return css`
39
+ pointer-events: all;
40
+ width: 100%;
41
+ position: relative;
42
+ overflow: hidden;
43
+ overflow: clip;
44
+ padding-bottom: ${LOADING_BAR_HEIGHT}px;
45
+ &::before {
46
+ content: '';
47
+ position: absolute;
48
+ bottom: 0px;
49
+ height: ${LOADING_BAR_HEIGHT}px;
50
+ background: ${loadingBarColor};
51
+ animation-name: ${loadingAnimation};
52
+ animation-duration: ${props.$duration}ms;
53
+ animation-fill-mode: both;
54
+ }
55
+
56
+ & > * {
57
+ opacity: var(${POPOVER_MOTION_CONTENT_OPACITY_PROPERTY}, 1);
58
+ will-change: opacity;
59
+ }
60
+ `
61
+ }
@@ -1,9 +1,10 @@
1
1
  import {CloseIcon} from '@sanity/icons'
2
- import {ThemeColorToneKey} from '@sanity/ui/theme'
2
+ import {ThemeColorStateToneKey} from '@sanity/ui/theme'
3
3
  import {styled} from 'styled-components'
4
- import {POPOVER_MOTION_CONTENT_OPACITY_PROPERTY} from '../../constants'
5
- import {Box, Button, Card, Flex, Stack, Text} from '../../primitives'
4
+ import {Box, Button, Flex, Stack, Text, Card} from '../../primitives'
5
+ import {ThemeProps} from '../../styles'
6
6
  import type {ButtonTone} from '../../types'
7
+ import {rootStyles, TextBox} from './styles'
7
8
 
8
9
  /**
9
10
  * @public
@@ -15,9 +16,10 @@ export interface ToastProps {
15
16
  radius?: number | number[]
16
17
  title?: React.ReactNode
17
18
  status?: 'error' | 'warning' | 'success' | 'info'
19
+ duration?: number
18
20
  }
19
21
 
20
- const STATUS_CARD_TONE: {[key: string]: ThemeColorToneKey} = {
22
+ const STATUS_CARD_TONE: {[key: string]: ThemeColorStateToneKey} = {
21
23
  error: 'critical',
22
24
  warning: 'caution',
23
25
  success: 'positive',
@@ -38,17 +40,9 @@ const ROLES = {
38
40
  info: 'alert',
39
41
  } as const
40
42
 
41
- const Root = styled(Card)`
42
- pointer-events: all;
43
- & > * {
44
- opacity: var(${POPOVER_MOTION_CONTENT_OPACITY_PROPERTY}, 1);
45
- will-change: opacity;
46
- }
47
- `
48
-
49
- const TextBox = styled(Flex)`
50
- overflow-x: auto;
51
- `
43
+ const Root = styled(Card)<{$duration?: number; tone: ThemeColorStateToneKey} & ThemeProps>(
44
+ rootStyles,
45
+ )
52
46
 
53
47
  /**
54
48
  * The `Toast` component gives feedback to users when an action has taken place.
@@ -60,7 +54,7 @@ const TextBox = styled(Flex)`
60
54
  export function Toast(
61
55
  props: ToastProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height' | 'ref' | 'title'>,
62
56
  ): React.ReactElement {
63
- const {closable, description, onClose, radius = 3, title, status, ...restProps} = props
57
+ const {closable, description, duration, onClose, radius = 3, title, status, ...restProps} = props
64
58
  const cardTone = status ? STATUS_CARD_TONE[status] : 'default'
65
59
  const buttonTone = status ? BUTTON_TONE[status] : 'default'
66
60
  const role = status ? ROLES[status] : 'status'
@@ -74,6 +68,7 @@ export function Toast(
74
68
  radius={radius}
75
69
  shadow={2}
76
70
  tone={cardTone}
71
+ $duration={duration}
77
72
  >
78
73
  <Flex align="flex-start">
79
74
  <TextBox flex={1} padding={3}>
@@ -45,6 +45,8 @@ const ToastContainer = styled.div`
45
45
  width: 100%;
46
46
  `
47
47
 
48
+ let toastId = 0
49
+
48
50
  /**
49
51
  * @public
50
52
  */
@@ -55,7 +57,27 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
55
57
  const mounted = useMounted()
56
58
  const prefersReducedMotion = usePrefersReducedMotion()
57
59
  const variants = useMemo<Variants>(
58
- () => getVariants(prefersReducedMotion),
60
+ () => ({
61
+ initial: {
62
+ opacity: 0,
63
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: 0,
64
+ y: 32,
65
+ scale: 0.25,
66
+ willChange: 'transform',
67
+ },
68
+ animate: {
69
+ opacity: [0, 1, 1],
70
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [0, 0, 1],
71
+ y: 0,
72
+ scale: 1,
73
+ },
74
+ exit: {
75
+ opacity: [1, 1, 0],
76
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [1, 0, 0],
77
+ scale: 0.5,
78
+ transition: prefersReducedMotion ? {duration: 0} : {duration: 0.2},
79
+ },
80
+ }),
59
81
  [prefersReducedMotion],
60
82
  )
61
83
 
@@ -64,7 +86,7 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
64
86
  // Wrap setState in startTransition to allow React to give input state updates higher priority
65
87
  const setState: typeof _setState = (state) => startTransition(() => _setState(state))
66
88
 
67
- const id = params.id || crypto.randomUUID()
89
+ const id = params.id || String(toastId++)
68
90
  const duration = params.duration || 5000
69
91
 
70
92
  const dismiss = () => {
@@ -155,6 +177,7 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
155
177
  onClose={dismiss}
156
178
  status={params.status}
157
179
  title={params.title}
180
+ duration={params.duration}
158
181
  />
159
182
  </motion.div>
160
183
  ))}
@@ -166,27 +189,3 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
166
189
  </ToastContext.Provider>
167
190
  )
168
191
  }
169
-
170
- function getVariants(prefersReducedMotion: boolean) {
171
- return {
172
- initial: {
173
- opacity: 0,
174
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: 0,
175
- y: 32,
176
- scale: 0.25,
177
- willChange: 'transform',
178
- },
179
- animate: {
180
- opacity: [0, 1, 1],
181
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [0, 0, 1],
182
- y: 0,
183
- scale: 1,
184
- },
185
- exit: {
186
- opacity: [1, 1, 0],
187
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [1, 0, 0],
188
- scale: 0.5,
189
- transition: {duration: prefersReducedMotion ? 0 : 0.2},
190
- },
191
- }
192
- }
@@ -1,10 +1,16 @@
1
1
  import {ToggleArrowRightIcon} from '@sanity/icons'
2
2
  import {ThemeFontWeightKey} from '@sanity/ui/theme'
3
3
  import {memo, useCallback, useEffect, useId, useMemo, useRef} from 'react'
4
+ import {styled} from 'styled-components'
4
5
  import {Box, BoxProps, Flex, Text} from '../../primitives'
6
+ import {
7
+ treeItemRootStyle,
8
+ treeItemRootColorStyle,
9
+ treeItemBoxStyle,
10
+ TreeItemBoxStyleProps,
11
+ } from './style'
5
12
  import {TreeContext} from './treeContext'
6
13
  import {TreeGroup} from './treeGroup'
7
- import {Root, ToggleArrowText, TreeItemBox} from './treeItem.styles'
8
14
  import {useTree} from './useTree'
9
15
 
10
16
  /**
@@ -24,6 +30,16 @@ export interface TreeItemProps {
24
30
  weight?: ThemeFontWeightKey
25
31
  }
26
32
 
33
+ const Root = memo(styled.li(treeItemRootStyle, treeItemRootColorStyle))
34
+
35
+ const TreeItemBox = styled(Box).attrs({forwardedAs: 'a'})<TreeItemBoxStyleProps>(treeItemBoxStyle)
36
+
37
+ const ToggleArrowText = styled(Text)`
38
+ & > svg {
39
+ transition: transform 100ms;
40
+ }
41
+ `
42
+
27
43
  /**
28
44
  * This API might change. DO NOT USE IN PRODUCTION.
29
45
  * @beta
@@ -54,7 +70,7 @@ export const TreeItem = memo(function TreeItem(
54
70
  const {path, registerItem, setExpanded, setFocusedElement} = tree
55
71
  const _id = useId()
56
72
  const id = idProp || _id
57
- const itemPath = useMemo(() => [...path, id || ''], [id, path])
73
+ const itemPath = useMemo(() => path.concat([id || '']), [id, path])
58
74
  const itemKey = itemPath.join('/')
59
75
  const itemState = tree.state[itemKey]
60
76
  const focused = tree.focusedElement === rootRef.current
@@ -67,7 +83,7 @@ export const TreeItem = memo(function TreeItem(
67
83
 
68
84
  const handleClick = useCallback(
69
85
  (event: React.MouseEvent<HTMLLIElement>) => {
70
- onClick?.(event)
86
+ if (onClick) onClick(event)
71
87
 
72
88
  const target = event.target
73
89
 
@@ -101,35 +117,32 @@ export const TreeItem = memo(function TreeItem(
101
117
  return registerItem(rootRef.current, itemPath.join('/'), expanded, selected)
102
118
  }, [expanded, itemPath, registerItem, selected])
103
119
 
104
- const content = useMemo(
105
- () => (
106
- <Flex padding={padding}>
107
- <Box
108
- marginRight={space}
109
- style={{
110
- visibility: IconComponent || children ? 'visible' : 'hidden',
111
- pointerEvents: 'none',
112
- }}
113
- >
114
- {IconComponent && (
115
- <Text muted={muted} size={fontSize} weight={weight}>
116
- <IconComponent />
117
- </Text>
118
- )}
119
- {!IconComponent && (
120
- <ToggleArrowText muted={muted} size={fontSize} weight={weight}>
121
- <ToggleArrowRightIcon style={{transform: expanded ? 'rotate(90deg)' : undefined}} />
122
- </ToggleArrowText>
123
- )}
124
- </Box>
125
- <Box flex={1}>
126
- <Text muted={muted} size={fontSize} textOverflow="ellipsis" weight={weight}>
127
- {text}
120
+ const content = (
121
+ <Flex padding={padding}>
122
+ <Box
123
+ marginRight={space}
124
+ style={{
125
+ visibility: IconComponent || children ? 'visible' : 'hidden',
126
+ pointerEvents: 'none',
127
+ }}
128
+ >
129
+ {IconComponent && (
130
+ <Text muted={muted} size={fontSize} weight={weight}>
131
+ <IconComponent />
128
132
  </Text>
129
- </Box>
130
- </Flex>
131
- ),
132
- [IconComponent, children, expanded, fontSize, muted, padding, space, text, weight],
133
+ )}
134
+ {!IconComponent && (
135
+ <ToggleArrowText muted={muted} size={fontSize} weight={weight}>
136
+ <ToggleArrowRightIcon style={{transform: expanded ? 'rotate(90deg)' : undefined}} />
137
+ </ToggleArrowText>
138
+ )}
139
+ </Box>
140
+ <Box flex={1}>
141
+ <Text muted={muted} size={fontSize} textOverflow="ellipsis" weight={weight}>
142
+ {text}
143
+ </Text>
144
+ </Box>
145
+ </Flex>
133
146
  )
134
147
 
135
148
  if (href) {
@@ -7,20 +7,19 @@ export type ArrayPropPrimitive = string | number | boolean | undefined | null
7
7
  /**
8
8
  * This API might change. DO NOT USE IN PRODUCTION.
9
9
  * @beta
10
- * @deprecated use `_getArrayProp` and `useMemo` directly instead
11
- * @example
12
- * ```diff
13
- * -import {useArrayProp} from '@sanity/ui'
14
- * +import {_getArrayProp} from '@sanity/ui'
15
- * +import {useMemo} from 'react'
16
- *
17
- * -const width = useArrayProp(props.width)
18
- * +const width = useMemo(() => _getArrayProp(props.width), [props.width])
19
- * ```
20
10
  */
21
11
  export function useArrayProp<T extends ArrayPropPrimitive = ArrayPropPrimitive>(
22
12
  val: T | T[] | undefined,
23
13
  defaultVal?: T[],
24
14
  ): T[] {
25
- return useMemo(() => _getArrayProp(val, defaultVal), [defaultVal, val])
15
+ // JSON.stringify is fast, but it's not faster than useMemo's referencial equality check
16
+ const __perf_hash__ = useMemo(() => JSON.stringify(val ?? defaultVal), [defaultVal, val])
17
+
18
+ return useMemo(
19
+ () => _getArrayProp(val, defaultVal),
20
+
21
+ // Improve performance: Keep object identify for a given hash of the value
22
+ // eslint-disable-next-line react-hooks/exhaustive-deps
23
+ [__perf_hash__],
24
+ )
26
25
  }
@@ -1,8 +1,8 @@
1
1
  import {ThemeColorAvatarColorKey} from '@sanity/ui/theme'
2
- import {forwardRef, useCallback, useEffect, useId, useState} from 'react'
3
- import {isValidElementType} from 'react-is'
2
+ import {forwardRef, useCallback, useEffect, useId, useMemo, useState} from 'react'
3
+ import ReactIs from 'react-is'
4
4
  import {styled} from 'styled-components'
5
- import {_getArrayProp} from '../../styles'
5
+ import {useArrayProp} from '../../hooks'
6
6
  import {useTheme_v2} from '../../theme'
7
7
  import {AvatarPosition, AvatarSize, AvatarStatus} from '../../types'
8
8
  import {Label} from '../label'
@@ -73,8 +73,8 @@ export const Avatar = forwardRef(function Avatar(
73
73
  ...restProps
74
74
  } = props
75
75
  const {avatar} = useTheme_v2()
76
- const as = isValidElementType(asProp) ? asProp : 'div'
77
- const size = _getArrayProp(sizeProp)
76
+ const as = ReactIs.isValidElementType(asProp) ? asProp : 'div'
77
+ const size = useArrayProp(sizeProp)
78
78
 
79
79
  // @todo: remove this
80
80
  const avatarSize = avatar.sizes[size[0]] || avatar.sizes[0]
@@ -111,13 +111,17 @@ export const Avatar = forwardRef(function Avatar(
111
111
  }
112
112
  }, [onImageLoadError])
113
113
 
114
- const initialsSize = size.map((s) => {
115
- if (s === 1) return 1
116
- if (s === 2) return 3
117
- if (s === 3) return 5
114
+ const initialsSize = useMemo(
115
+ () =>
116
+ size.map((s) => {
117
+ if (s === 1) return 1
118
+ if (s === 2) return 3
119
+ if (s === 3) return 5
118
120
 
119
- return 0
120
- })
121
+ return 0
122
+ }),
123
+ [size],
124
+ )
121
125
 
122
126
  return (
123
127
  <Root
@@ -1,8 +1,9 @@
1
1
  import {getTheme_v2} from '@sanity/ui/theme'
2
- import {forwardRef} from 'react'
2
+ import {forwardRef, useMemo} from 'react'
3
3
  import {styled, css} from 'styled-components'
4
4
  import {EMPTY_RECORD} from '../../constants'
5
- import {rem, _responsive, ThemeProps, _getArrayProp} from '../../styles'
5
+ import {useArrayProp} from '../../hooks'
6
+ import {rem, _responsive, ThemeProps} from '../../styles'
6
7
  import {AvatarSize} from '../../types'
7
8
  import {Label} from '../label'
8
9
 
@@ -66,18 +67,23 @@ export const AvatarCounter = forwardRef(function AvatarCounter(
66
67
  props: AvatarCounterProps,
67
68
  ref: React.Ref<HTMLDivElement>,
68
69
  ) {
69
- const {count, size} = props
70
- const $size = _getArrayProp(size ?? 1)
71
- const fontSize = $size.map((s) => {
72
- if (s === 1) return 1
73
- if (s === 2) return 3
74
- if (s === 3) return 5
70
+ const {count, size: sizeProp = 1} = props
71
+ const size = useArrayProp(sizeProp)
75
72
 
76
- return 0
77
- })
73
+ const fontSize = useMemo(
74
+ () =>
75
+ size.map((s) => {
76
+ if (s === 1) return 1
77
+ if (s === 2) return 3
78
+ if (s === 3) return 5
79
+
80
+ return 0
81
+ }),
82
+ [size],
83
+ )
78
84
 
79
85
  return (
80
- <Root $size={$size} data-ui="AvatarCounter" ref={ref}>
86
+ <Root $size={size} data-ui="AvatarCounter" ref={ref}>
81
87
  <Label as="span" size={fontSize} weight="medium">
82
88
  {count}
83
89
  </Label>
@@ -2,7 +2,8 @@ import {getTheme_v2} from '@sanity/ui/theme'
2
2
  import {Children, cloneElement, forwardRef, isValidElement, useMemo} from 'react'
3
3
  import {styled, css} from 'styled-components'
4
4
  import {EMPTY_RECORD} from '../../constants'
5
- import {rem, _responsive, ThemeProps, _getArrayProp} from '../../styles'
5
+ import {useArrayProp} from '../../hooks'
6
+ import {rem, _responsive, ThemeProps} from '../../styles'
6
7
  import {AvatarSize} from '../../types'
7
8
  import {AvatarCounter} from './avatarCounter'
8
9
 
@@ -64,9 +65,12 @@ export const AvatarStack = forwardRef(function AvatarStack(
64
65
  size: sizeProp = 1,
65
66
  ...restProps
66
67
  } = props
67
- const children: React.ReactElement[] = Children.toArray(childrenProp).filter(isValidElement)
68
+ const children = useMemo<React.ReactElement[]>(
69
+ () => Children.toArray(childrenProp).filter(isValidElement),
70
+ [childrenProp],
71
+ )
68
72
  const maxLength = Math.max(maxLengthProp, 0)
69
- const size = useMemo(() => _getArrayProp(sizeProp), [sizeProp])
73
+ const size = useArrayProp(sizeProp)
70
74
 
71
75
  const len = children.length
72
76
  const visibleCount = maxLength - 1
@@ -1,6 +1,6 @@
1
- import {forwardRef, useMemo} from 'react'
1
+ import {forwardRef} from 'react'
2
2
  import {styled} from 'styled-components'
3
- import {_getArrayProp} from '../../styles'
3
+ import {useArrayProp} from '../../hooks'
4
4
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
5
5
  import {BadgeMode, BadgeTone} from '../../types'
6
6
  import {Box, BoxProps} from '../box'
@@ -45,16 +45,13 @@ export const Badge = forwardRef(function Badge(
45
45
  ...restProps
46
46
  } = props
47
47
 
48
- const $radius = useMemo(() => _getArrayProp(radius), [radius])
49
- const $padding = useMemo(() => _getArrayProp(padding), [padding])
50
-
51
48
  return (
52
49
  <Root
53
50
  data-ui="Badge"
54
51
  {...restProps}
55
52
  $tone={tone}
56
- $radius={$radius}
57
- padding={$padding}
53
+ $radius={useArrayProp(radius)}
54
+ padding={useArrayProp(padding)}
58
55
  ref={ref}
59
56
  >
60
57
  <Text size={fontSize}>{children}</Text>
@@ -1,6 +1,6 @@
1
- import {forwardRef, useMemo} from 'react'
1
+ import {forwardRef} from 'react'
2
2
  import {styled} from 'styled-components'
3
- import {_getArrayProp} from '../../styles'
3
+ import {useArrayProp} from '../../hooks'
4
4
  import {
5
5
  boxStyle,
6
6
  flexItemStyle,
@@ -90,62 +90,36 @@ export const Box = forwardRef(function Box(
90
90
  ...restProps
91
91
  } = props
92
92
 
93
- const $column = useMemo(() => _getArrayProp(column), [column])
94
- const $columnStart = useMemo(() => _getArrayProp(columnStart), [columnStart])
95
- const $columnEnd = useMemo(() => _getArrayProp(columnEnd), [columnEnd])
96
- const $display = useMemo(() => _getArrayProp(display), [display])
97
- const $flex = useMemo(() => _getArrayProp(flex), [flex])
98
- const $height = useMemo(() => _getArrayProp(height), [height])
99
- const $margin = useMemo(() => _getArrayProp(margin), [margin])
100
- const $marginX = useMemo(() => _getArrayProp(marginX), [marginX])
101
- const $marginY = useMemo(() => _getArrayProp(marginY), [marginY])
102
- const $marginTop = useMemo(() => _getArrayProp(marginTop), [marginTop])
103
- const $marginRight = useMemo(() => _getArrayProp(marginRight), [marginRight])
104
- const $marginBottom = useMemo(() => _getArrayProp(marginBottom), [marginBottom])
105
- const $marginLeft = useMemo(() => _getArrayProp(marginLeft), [marginLeft])
106
- const $overflow = useMemo(() => _getArrayProp(overflow), [overflow])
107
- const $padding = useMemo(() => _getArrayProp(padding), [padding])
108
- const $paddingX = useMemo(() => _getArrayProp(paddingX), [paddingX])
109
- const $paddingY = useMemo(() => _getArrayProp(paddingY), [paddingY])
110
- const $paddingTop = useMemo(() => _getArrayProp(paddingTop), [paddingTop])
111
- const $paddingRight = useMemo(() => _getArrayProp(paddingRight), [paddingRight])
112
- const $paddingBottom = useMemo(() => _getArrayProp(paddingBottom), [paddingBottom])
113
- const $paddingLeft = useMemo(() => _getArrayProp(paddingLeft), [paddingLeft])
114
- const $row = useMemo(() => _getArrayProp(row), [row])
115
- const $rowStart = useMemo(() => _getArrayProp(rowStart), [rowStart])
116
- const $rowEnd = useMemo(() => _getArrayProp(rowEnd), [rowEnd])
117
- const $sizing = useMemo(() => _getArrayProp(sizing), [sizing])
118
-
119
93
  return (
120
94
  <Root
121
95
  data-as={typeof asProp === 'string' ? asProp : undefined}
122
96
  data-ui="Box"
123
97
  {...restProps}
124
- $column={$column}
125
- $columnStart={$columnStart}
126
- $columnEnd={$columnEnd}
127
- $display={$display}
128
- $flex={$flex}
129
- $height={$height}
130
- $margin={$margin}
131
- $marginX={$marginX}
132
- $marginY={$marginY}
133
- $marginTop={$marginTop}
134
- $marginRight={$marginRight}
135
- $marginBottom={$marginBottom}
136
- $marginLeft={$marginLeft}
137
- $overflow={$overflow}
138
- $padding={$padding}
139
- $paddingX={$paddingX}
140
- $paddingY={$paddingY}
141
- $paddingTop={$paddingTop}
142
- $paddingRight={$paddingRight}
143
- $paddingBottom={$paddingBottom}
144
- $paddingLeft={$paddingLeft}
145
- $row={$row}
146
- $rowStart={$rowStart}
147
- $rowEnd={$rowEnd}
148
- $sizing={$sizing}
98
+ $column={useArrayProp(column)}
99
+ $columnStart={useArrayProp(columnStart)}
100
+ $columnEnd={useArrayProp(columnEnd)}
101
+ $display={useArrayProp(display)}
102
+ $flex={useArrayProp(flex)}
103
+ $height={useArrayProp(height)}
104
+ $margin={useArrayProp(margin)}
105
+ $marginX={useArrayProp(marginX)}
106
+ $marginY={useArrayProp(marginY)}
107
+ $marginTop={useArrayProp(marginTop)}
108
+ $marginRight={useArrayProp(marginRight)}
109
+ $marginBottom={useArrayProp(marginBottom)}
110
+ $marginLeft={useArrayProp(marginLeft)}
111
+ $overflow={useArrayProp(overflow)}
112
+ $padding={useArrayProp(padding)}
113
+ $paddingX={useArrayProp(paddingX)}
114
+ $paddingY={useArrayProp(paddingY)}
115
+ $paddingTop={useArrayProp(paddingTop)}
116
+ $paddingRight={useArrayProp(paddingRight)}
117
+ $paddingBottom={useArrayProp(paddingBottom)}
118
+ $paddingLeft={useArrayProp(paddingLeft)}
119
+ $row={useArrayProp(row)}
120
+ $rowStart={useArrayProp(rowStart)}
121
+ $rowEnd={useArrayProp(rowEnd)}
122
+ $sizing={useArrayProp(sizing)}
149
123
  as={asProp}
150
124
  ref={ref}
151
125
  >
@@ -1,7 +1,8 @@
1
1
  import {forwardRef, isValidElement, useMemo} from 'react'
2
2
  import {isValidElementType} from 'react-is'
3
3
  import {styled} from 'styled-components'
4
- import {ThemeProps, _getArrayProp} from '../../styles'
4
+ import {useArrayProp} from '../../hooks'
5
+ import {ThemeProps} from '../../styles'
5
6
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
6
7
  import {useTheme_v2} from '../../theme'
7
8
  import {ButtonMode, ButtonTextAlign, ButtonTone, ButtonWidth, FlexJustify} from '../../types'
@@ -92,16 +93,16 @@ export const Button = forwardRef(function Button(
92
93
  } = props
93
94
  const {button} = useTheme_v2()
94
95
 
95
- const justify = useMemo(() => _getArrayProp(justifyProp), [justifyProp])
96
- const padding = useMemo(() => _getArrayProp(paddingProp), [paddingProp])
97
- const paddingX = useMemo(() => _getArrayProp(paddingXProp), [paddingXProp])
98
- const paddingY = useMemo(() => _getArrayProp(paddingYProp), [paddingYProp])
99
- const paddingTop = useMemo(() => _getArrayProp(paddingTopProp), [paddingTopProp])
100
- const paddingBottom = useMemo(() => _getArrayProp(paddingBottomProp), [paddingBottomProp])
101
- const paddingLeft = useMemo(() => _getArrayProp(paddingLeftProp), [paddingLeftProp])
102
- const paddingRight = useMemo(() => _getArrayProp(paddingRightProp), [paddingRightProp])
103
- const radius = useMemo(() => _getArrayProp(radiusProp), [radiusProp])
104
- const space = useMemo(() => _getArrayProp(spaceProp), [spaceProp])
96
+ const justify = useArrayProp(justifyProp)
97
+ const padding = useArrayProp(paddingProp)
98
+ const paddingX = useArrayProp(paddingXProp)
99
+ const paddingY = useArrayProp(paddingYProp)
100
+ const paddingTop = useArrayProp(paddingTopProp)
101
+ const paddingBottom = useArrayProp(paddingBottomProp)
102
+ const paddingLeft = useArrayProp(paddingLeftProp)
103
+ const paddingRight = useArrayProp(paddingRightProp)
104
+ const radius = useArrayProp(radiusProp)
105
+ const space = useArrayProp(spaceProp)
105
106
 
106
107
  const boxProps = useMemo(
107
108
  () => ({