@wordpress/components 25.10.0 → 25.11.1-next.f8d8eceb.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/CHANGELOG.md +16 -0
- package/build/autocomplete/index.js +104 -52
- package/build/autocomplete/index.js.map +1 -1
- package/build/dropdown-menu-v2-ariakit/index.js +217 -0
- package/build/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/styles.js +157 -0
- package/build/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/types.js +6 -0
- package/build/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build/input-control/styles/input-control-styles.js +23 -23
- package/build/input-control/styles/input-control-styles.js.map +1 -1
- package/build/mobile/global-styles-context/utils.native.js +1 -1
- package/build/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build/private-apis.js +9 -1
- package/build/private-apis.js.map +1 -1
- package/build/select-control/styles/select-control-styles.js +8 -8
- package/build/select-control/styles/select-control-styles.js.map +1 -1
- package/build/tabs/index.js +2 -2
- package/build/tabs/index.js.map +1 -1
- package/build/tooltip/index.js +2 -2
- package/build/tooltip/index.js.map +1 -1
- package/build-module/autocomplete/index.js +104 -52
- package/build-module/autocomplete/index.js.map +1 -1
- package/build-module/dropdown-menu-v2-ariakit/index.js +199 -0
- package/build-module/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js +136 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js +2 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build-module/input-control/styles/input-control-styles.js +23 -23
- package/build-module/input-control/styles/input-control-styles.js.map +1 -1
- package/build-module/mobile/global-styles-context/utils.native.js +2 -2
- package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build-module/private-apis.js +9 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/select-control/styles/select-control-styles.js +8 -8
- package/build-module/select-control/styles/select-control-styles.js.map +1 -1
- package/build-module/tabs/index.js +3 -3
- package/build-module/tabs/index.js.map +1 -1
- package/build-module/tooltip/index.js +2 -2
- package/build-module/tooltip/index.js.map +1 -1
- package/build-style/style-rtl.css +1 -1
- package/build-style/style.css +1 -1
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts +11 -0
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts +16 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts +88 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts +2 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts +174 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts.map +1 -0
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/tooltip/index.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/autocomplete/index.tsx +136 -77
- package/src/dimension-control/test/__snapshots__/index.test.js.snap +8 -8
- package/src/dropdown-menu-v2-ariakit/README.md +324 -0
- package/src/dropdown-menu-v2-ariakit/index.tsx +318 -0
- package/src/dropdown-menu-v2-ariakit/stories/index.story.tsx +506 -0
- package/src/dropdown-menu-v2-ariakit/styles.ts +297 -0
- package/src/dropdown-menu-v2-ariakit/test/index.tsx +1139 -0
- package/src/dropdown-menu-v2-ariakit/types.ts +186 -0
- package/src/input-control/styles/input-control-styles.tsx +2 -2
- package/src/mobile/global-styles-context/utils.native.js +2 -2
- package/src/private-apis.ts +16 -0
- package/src/select-control/styles/select-control-styles.ts +2 -2
- package/src/tabs/index.tsx +3 -3
- package/src/tabs/test/index.tsx +12 -3
- package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +8 -0
- package/src/tooltip/index.tsx +2 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
// eslint-disable-next-line no-restricted-imports
|
|
5
|
+
import * as Ariakit from '@ariakit/react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WordPress dependencies
|
|
9
|
+
*/
|
|
10
|
+
import {
|
|
11
|
+
forwardRef,
|
|
12
|
+
createContext,
|
|
13
|
+
useContext,
|
|
14
|
+
useMemo,
|
|
15
|
+
cloneElement,
|
|
16
|
+
isValidElement,
|
|
17
|
+
} from '@wordpress/element';
|
|
18
|
+
import { isRTL } from '@wordpress/i18n';
|
|
19
|
+
import { check, chevronRightSmall } from '@wordpress/icons';
|
|
20
|
+
import { SVG, Circle } from '@wordpress/primitives';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Internal dependencies
|
|
24
|
+
*/
|
|
25
|
+
import { useContextSystem, contextConnect } from '../context';
|
|
26
|
+
import type { WordPressComponentProps } from '../context';
|
|
27
|
+
import Icon from '../icon';
|
|
28
|
+
import type {
|
|
29
|
+
DropdownMenuContext as DropdownMenuContextType,
|
|
30
|
+
DropdownMenuProps,
|
|
31
|
+
DropdownMenuGroupProps,
|
|
32
|
+
DropdownMenuGroupLabelProps,
|
|
33
|
+
DropdownMenuItemProps,
|
|
34
|
+
DropdownMenuCheckboxItemProps,
|
|
35
|
+
DropdownMenuRadioItemProps,
|
|
36
|
+
DropdownMenuSeparatorProps,
|
|
37
|
+
} from './types';
|
|
38
|
+
import * as Styled from './styles';
|
|
39
|
+
|
|
40
|
+
export const DropdownMenuContext = createContext<
|
|
41
|
+
DropdownMenuContextType | undefined
|
|
42
|
+
>( undefined );
|
|
43
|
+
|
|
44
|
+
export const DropdownMenuItem = forwardRef<
|
|
45
|
+
HTMLDivElement,
|
|
46
|
+
WordPressComponentProps< DropdownMenuItemProps, 'div', false >
|
|
47
|
+
>( function DropdownMenuItem(
|
|
48
|
+
{ prefix, suffix, children, hideOnClick = true, ...props },
|
|
49
|
+
ref
|
|
50
|
+
) {
|
|
51
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Styled.DropdownMenuItem
|
|
55
|
+
ref={ ref }
|
|
56
|
+
{ ...props }
|
|
57
|
+
hideOnClick={ hideOnClick }
|
|
58
|
+
store={ dropdownMenuContext?.store }
|
|
59
|
+
>
|
|
60
|
+
{ prefix && (
|
|
61
|
+
<Styled.ItemPrefixWrapper>{ prefix }</Styled.ItemPrefixWrapper>
|
|
62
|
+
) }
|
|
63
|
+
{ children }
|
|
64
|
+
{ suffix && (
|
|
65
|
+
<Styled.ItemSuffixWrapper>{ suffix }</Styled.ItemSuffixWrapper>
|
|
66
|
+
) }
|
|
67
|
+
</Styled.DropdownMenuItem>
|
|
68
|
+
);
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
export const DropdownMenuCheckboxItem = forwardRef<
|
|
72
|
+
HTMLDivElement,
|
|
73
|
+
WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false >
|
|
74
|
+
>( function DropdownMenuCheckboxItem(
|
|
75
|
+
{ suffix, children, hideOnClick = false, ...props },
|
|
76
|
+
ref
|
|
77
|
+
) {
|
|
78
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Styled.DropdownMenuCheckboxItem
|
|
82
|
+
ref={ ref }
|
|
83
|
+
{ ...props }
|
|
84
|
+
hideOnClick={ hideOnClick }
|
|
85
|
+
store={ dropdownMenuContext?.store }
|
|
86
|
+
>
|
|
87
|
+
<Ariakit.MenuItemCheck
|
|
88
|
+
store={ dropdownMenuContext?.store }
|
|
89
|
+
render={ <Styled.ItemPrefixWrapper /> }
|
|
90
|
+
>
|
|
91
|
+
<Icon icon={ check } size={ 24 } />
|
|
92
|
+
</Ariakit.MenuItemCheck>
|
|
93
|
+
|
|
94
|
+
{ children }
|
|
95
|
+
{ suffix && (
|
|
96
|
+
<Styled.ItemSuffixWrapper>{ suffix }</Styled.ItemSuffixWrapper>
|
|
97
|
+
) }
|
|
98
|
+
</Styled.DropdownMenuCheckboxItem>
|
|
99
|
+
);
|
|
100
|
+
} );
|
|
101
|
+
|
|
102
|
+
export const DropdownMenuRadioItem = forwardRef<
|
|
103
|
+
HTMLDivElement,
|
|
104
|
+
WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false >
|
|
105
|
+
>( function DropdownMenuRadioItem(
|
|
106
|
+
{ suffix, children, hideOnClick = false, ...props },
|
|
107
|
+
ref
|
|
108
|
+
) {
|
|
109
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<Styled.DropdownMenuRadioItem
|
|
113
|
+
ref={ ref }
|
|
114
|
+
{ ...props }
|
|
115
|
+
hideOnClick={ hideOnClick }
|
|
116
|
+
store={ dropdownMenuContext?.store }
|
|
117
|
+
>
|
|
118
|
+
<Ariakit.MenuItemCheck
|
|
119
|
+
store={ dropdownMenuContext?.store }
|
|
120
|
+
render={ <Styled.ItemPrefixWrapper /> }
|
|
121
|
+
>
|
|
122
|
+
<SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
123
|
+
<Circle
|
|
124
|
+
cx={ 12 }
|
|
125
|
+
cy={ 12 }
|
|
126
|
+
r={ 3 }
|
|
127
|
+
fill="currentColor"
|
|
128
|
+
></Circle>
|
|
129
|
+
</SVG>
|
|
130
|
+
</Ariakit.MenuItemCheck>
|
|
131
|
+
{ children }
|
|
132
|
+
{ suffix }
|
|
133
|
+
</Styled.DropdownMenuRadioItem>
|
|
134
|
+
);
|
|
135
|
+
} );
|
|
136
|
+
|
|
137
|
+
export const DropdownMenuGroup = forwardRef<
|
|
138
|
+
HTMLDivElement,
|
|
139
|
+
WordPressComponentProps< DropdownMenuGroupProps, 'div', false >
|
|
140
|
+
>( function DropdownMenuGroup( props, ref ) {
|
|
141
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
142
|
+
return (
|
|
143
|
+
<Styled.DropdownMenuGroup
|
|
144
|
+
ref={ ref }
|
|
145
|
+
{ ...props }
|
|
146
|
+
store={ dropdownMenuContext?.store }
|
|
147
|
+
/>
|
|
148
|
+
);
|
|
149
|
+
} );
|
|
150
|
+
|
|
151
|
+
export const DropdownMenuGroupLabel = forwardRef<
|
|
152
|
+
HTMLDivElement,
|
|
153
|
+
WordPressComponentProps< DropdownMenuGroupLabelProps, 'div', false >
|
|
154
|
+
>( function DropdownMenuGroupLabel( props, ref ) {
|
|
155
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
156
|
+
return (
|
|
157
|
+
<Styled.DropdownMenuGroupLabel
|
|
158
|
+
ref={ ref }
|
|
159
|
+
{ ...props }
|
|
160
|
+
store={ dropdownMenuContext?.store }
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
|
+
} );
|
|
164
|
+
|
|
165
|
+
const UnconnectedDropdownMenu = (
|
|
166
|
+
props: WordPressComponentProps< DropdownMenuProps, 'div', false >,
|
|
167
|
+
ref: React.ForwardedRef< HTMLDivElement >
|
|
168
|
+
) => {
|
|
169
|
+
const {
|
|
170
|
+
// Store props
|
|
171
|
+
open,
|
|
172
|
+
defaultOpen = false,
|
|
173
|
+
onOpenChange,
|
|
174
|
+
placement,
|
|
175
|
+
|
|
176
|
+
// Menu trigger props
|
|
177
|
+
trigger,
|
|
178
|
+
|
|
179
|
+
// Menu props
|
|
180
|
+
gutter,
|
|
181
|
+
children,
|
|
182
|
+
shift,
|
|
183
|
+
modal = true,
|
|
184
|
+
hideOnEscape = true,
|
|
185
|
+
|
|
186
|
+
// From internal components context
|
|
187
|
+
variant,
|
|
188
|
+
|
|
189
|
+
// Rest
|
|
190
|
+
...otherProps
|
|
191
|
+
} = useContextSystem<
|
|
192
|
+
typeof props & Pick< DropdownMenuContextType, 'variant' >
|
|
193
|
+
>( props, 'DropdownMenu' );
|
|
194
|
+
|
|
195
|
+
const parentContext = useContext( DropdownMenuContext );
|
|
196
|
+
|
|
197
|
+
const computedDirection = isRTL() ? 'rtl' : 'ltr';
|
|
198
|
+
|
|
199
|
+
// If an explicit value for the `placement` prop is not passed,
|
|
200
|
+
// apply a default placement of `bottom-start` for the root dropdown,
|
|
201
|
+
// and of `right-start` for nested dropdowns.
|
|
202
|
+
let computedPlacement =
|
|
203
|
+
props.placement ??
|
|
204
|
+
( parentContext?.store ? 'right-start' : 'bottom-start' );
|
|
205
|
+
// Swap left/right in case of RTL direction
|
|
206
|
+
if ( computedDirection === 'rtl' ) {
|
|
207
|
+
if ( /right/.test( computedPlacement ) ) {
|
|
208
|
+
computedPlacement = computedPlacement.replace(
|
|
209
|
+
'right',
|
|
210
|
+
'left'
|
|
211
|
+
) as typeof computedPlacement;
|
|
212
|
+
} else if ( /left/.test( computedPlacement ) ) {
|
|
213
|
+
computedPlacement = computedPlacement.replace(
|
|
214
|
+
'left',
|
|
215
|
+
'right'
|
|
216
|
+
) as typeof computedPlacement;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const dropdownMenuStore = Ariakit.useMenuStore( {
|
|
221
|
+
parent: parentContext?.store,
|
|
222
|
+
open,
|
|
223
|
+
defaultOpen,
|
|
224
|
+
placement: computedPlacement,
|
|
225
|
+
focusLoop: true,
|
|
226
|
+
setOpen( willBeOpen ) {
|
|
227
|
+
onOpenChange?.( willBeOpen );
|
|
228
|
+
},
|
|
229
|
+
rtl: computedDirection === 'rtl',
|
|
230
|
+
} );
|
|
231
|
+
|
|
232
|
+
const contextValue = useMemo(
|
|
233
|
+
() => ( { store: dropdownMenuStore, variant } ),
|
|
234
|
+
[ dropdownMenuStore, variant ]
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Extract the side from the applied placement — useful for animations.
|
|
238
|
+
const appliedPlacementSide = dropdownMenuStore
|
|
239
|
+
.useState( 'placement' )
|
|
240
|
+
.split( '-' )[ 0 ];
|
|
241
|
+
|
|
242
|
+
if (
|
|
243
|
+
dropdownMenuStore.parent &&
|
|
244
|
+
! ( isValidElement( trigger ) && DropdownMenuItem === trigger.type )
|
|
245
|
+
) {
|
|
246
|
+
// eslint-disable-next-line no-console
|
|
247
|
+
console.warn(
|
|
248
|
+
'For nested DropdownMenus, the `trigger` should always be a `DropdownMenuItem`.'
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<>
|
|
254
|
+
{ /* Menu trigger */ }
|
|
255
|
+
<Ariakit.MenuButton
|
|
256
|
+
ref={ ref }
|
|
257
|
+
store={ dropdownMenuStore }
|
|
258
|
+
render={
|
|
259
|
+
dropdownMenuStore.parent
|
|
260
|
+
? cloneElement( trigger, {
|
|
261
|
+
// Add submenu arrow, unless a `suffix` is explicitly specified
|
|
262
|
+
suffix: trigger.props.suffix ?? (
|
|
263
|
+
<Styled.SubmenuChevronIcon
|
|
264
|
+
aria-hidden="true"
|
|
265
|
+
icon={ chevronRightSmall }
|
|
266
|
+
size={ 24 }
|
|
267
|
+
/>
|
|
268
|
+
),
|
|
269
|
+
} )
|
|
270
|
+
: trigger
|
|
271
|
+
}
|
|
272
|
+
/>
|
|
273
|
+
|
|
274
|
+
{ /* Menu popover */ }
|
|
275
|
+
<Styled.DropdownMenu
|
|
276
|
+
{ ...otherProps }
|
|
277
|
+
modal={ modal }
|
|
278
|
+
store={ dropdownMenuStore }
|
|
279
|
+
gutter={ gutter ?? ( dropdownMenuStore.parent ? 16 : 8 ) }
|
|
280
|
+
shift={ shift ?? ( dropdownMenuStore.parent ? -8 : 0 ) }
|
|
281
|
+
hideOnHoverOutside={ false }
|
|
282
|
+
data-side={ appliedPlacementSide }
|
|
283
|
+
variant={ variant }
|
|
284
|
+
wrapperProps={ {
|
|
285
|
+
dir: computedDirection,
|
|
286
|
+
style: {
|
|
287
|
+
direction: computedDirection,
|
|
288
|
+
},
|
|
289
|
+
} }
|
|
290
|
+
hideOnEscape={ hideOnEscape }
|
|
291
|
+
unmountOnHide
|
|
292
|
+
>
|
|
293
|
+
<DropdownMenuContext.Provider value={ contextValue }>
|
|
294
|
+
{ children }
|
|
295
|
+
</DropdownMenuContext.Provider>
|
|
296
|
+
</Styled.DropdownMenu>
|
|
297
|
+
</>
|
|
298
|
+
);
|
|
299
|
+
};
|
|
300
|
+
export const DropdownMenu = contextConnect(
|
|
301
|
+
UnconnectedDropdownMenu,
|
|
302
|
+
'DropdownMenu'
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
export const DropdownMenuSeparator = forwardRef<
|
|
306
|
+
HTMLHRElement,
|
|
307
|
+
WordPressComponentProps< DropdownMenuSeparatorProps, 'hr', false >
|
|
308
|
+
>( function DropdownMenuSeparator( props, ref ) {
|
|
309
|
+
const dropdownMenuContext = useContext( DropdownMenuContext );
|
|
310
|
+
return (
|
|
311
|
+
<Styled.DropdownMenuSeparator
|
|
312
|
+
ref={ ref }
|
|
313
|
+
{ ...props }
|
|
314
|
+
store={ dropdownMenuContext?.store }
|
|
315
|
+
variant={ dropdownMenuContext?.variant }
|
|
316
|
+
/>
|
|
317
|
+
);
|
|
318
|
+
} );
|