@cdx-ui/components 0.0.1-beta.159 → 0.0.1-beta.160
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/coverage.svg +1 -1
- package/lib/commonjs/components/Menu/index.js +499 -0
- package/lib/commonjs/components/Menu/index.js.map +1 -0
- package/lib/commonjs/components/Menu/styles.js +100 -0
- package/lib/commonjs/components/Menu/styles.js.map +1 -0
- package/lib/commonjs/components/Select/index.js +57 -22
- package/lib/commonjs/components/Select/index.js.map +1 -1
- package/lib/commonjs/components/Select/styles.js +1 -40
- package/lib/commonjs/components/Select/styles.js.map +1 -1
- package/lib/commonjs/components/Slider/getSliderPopupPosition.js +16 -6
- package/lib/commonjs/components/Slider/getSliderPopupPosition.js.map +1 -1
- package/lib/commonjs/components/Slider/index.js +17 -5
- package/lib/commonjs/components/Slider/index.js.map +1 -1
- package/lib/commonjs/components/Toast/index.js +1 -1
- package/lib/commonjs/components/Toast/index.js.map +1 -1
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/components/picker/surfaces.js +16 -9
- package/lib/commonjs/components/picker/surfaces.js.map +1 -1
- package/lib/commonjs/figma/Menu.Item.figma.js +52 -0
- package/lib/commonjs/figma/Menu.Item.figma.js.map +1 -0
- package/lib/commonjs/figma/Menu.figma.js +29 -0
- package/lib/commonjs/figma/Menu.figma.js.map +1 -0
- package/lib/commonjs/providers/forge-design/provider.js +25 -11
- package/lib/commonjs/providers/forge-design/provider.js.map +1 -1
- package/lib/commonjs/providers/toast/insets-container.js +4 -1
- package/lib/commonjs/providers/toast/insets-container.js.map +1 -1
- package/lib/commonjs/providers/toast/provider.js +126 -45
- package/lib/commonjs/providers/toast/provider.js.map +1 -1
- package/lib/commonjs/providers/toast/toast-item-renderer.js +2 -1
- package/lib/commonjs/providers/toast/toast-item-renderer.js.map +1 -1
- package/lib/module/components/Menu/index.js +495 -0
- package/lib/module/components/Menu/index.js.map +1 -0
- package/lib/module/components/Menu/styles.js +96 -0
- package/lib/module/components/Menu/styles.js.map +1 -0
- package/lib/module/components/Select/index.js +55 -20
- package/lib/module/components/Select/index.js.map +1 -1
- package/lib/module/components/Select/styles.js +0 -39
- package/lib/module/components/Select/styles.js.map +1 -1
- package/lib/module/components/Slider/getSliderPopupPosition.js +16 -6
- package/lib/module/components/Slider/getSliderPopupPosition.js.map +1 -1
- package/lib/module/components/Slider/index.js +20 -8
- package/lib/module/components/Slider/index.js.map +1 -1
- package/lib/module/components/Toast/index.js +1 -1
- package/lib/module/components/Toast/index.js.map +1 -1
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/picker/surfaces.js +18 -11
- package/lib/module/components/picker/surfaces.js.map +1 -1
- package/lib/module/figma/Menu.Item.figma.js +46 -0
- package/lib/module/figma/Menu.Item.figma.js.map +1 -0
- package/lib/module/figma/Menu.figma.js +23 -0
- package/lib/module/figma/Menu.figma.js.map +1 -0
- package/lib/module/providers/forge-design/provider.js +26 -12
- package/lib/module/providers/forge-design/provider.js.map +1 -1
- package/lib/module/providers/toast/insets-container.js +5 -2
- package/lib/module/providers/toast/insets-container.js.map +1 -1
- package/lib/module/providers/toast/provider.js +126 -45
- package/lib/module/providers/toast/provider.js.map +1 -1
- package/lib/module/providers/toast/toast-item-renderer.js +2 -1
- package/lib/module/providers/toast/toast-item-renderer.js.map +1 -1
- package/lib/typescript/components/Menu/index.d.ts +119 -0
- package/lib/typescript/components/Menu/index.d.ts.map +1 -0
- package/lib/typescript/components/Menu/styles.d.ts +24 -0
- package/lib/typescript/components/Menu/styles.d.ts.map +1 -0
- package/lib/typescript/components/Select/index.d.ts.map +1 -1
- package/lib/typescript/components/Select/styles.d.ts +0 -7
- package/lib/typescript/components/Select/styles.d.ts.map +1 -1
- package/lib/typescript/components/Slider/getSliderPopupPosition.d.ts +1 -1
- package/lib/typescript/components/Slider/getSliderPopupPosition.d.ts.map +1 -1
- package/lib/typescript/components/Slider/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/types.d.ts +2 -2
- package/lib/typescript/components/Toast/types.d.ts.map +1 -1
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/components/picker/surfaces.d.ts.map +1 -1
- package/lib/typescript/figma/Menu.Item.figma.d.ts +8 -0
- package/lib/typescript/figma/Menu.Item.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Menu.figma.d.ts +8 -0
- package/lib/typescript/figma/Menu.figma.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/provider.d.ts.map +1 -1
- package/lib/typescript/providers/toast/insets-container.d.ts.map +1 -1
- package/lib/typescript/providers/toast/lifecycle.context.d.ts +2 -2
- package/lib/typescript/providers/toast/lifecycle.context.d.ts.map +1 -1
- package/lib/typescript/providers/toast/provider.d.ts.map +1 -1
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts.map +1 -1
- package/lib/typescript/providers/toast/types.d.ts +22 -8
- package/lib/typescript/providers/toast/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/Menu/index.tsx +654 -0
- package/src/components/Menu/styles.ts +153 -0
- package/src/components/Select/index.tsx +58 -23
- package/src/components/Select/styles.ts +0 -59
- package/src/components/Slider/getSliderPopupPosition.ts +19 -7
- package/src/components/Slider/index.tsx +25 -9
- package/src/components/Toast/index.tsx +1 -1
- package/src/components/Toast/types.ts +2 -2
- package/src/components/index.ts +1 -0
- package/src/components/picker/surfaces.tsx +13 -9
- package/src/providers/forge-design/provider.tsx +35 -16
- package/src/providers/toast/insets-container.tsx +3 -2
- package/src/providers/toast/lifecycle.context.tsx +2 -2
- package/src/providers/toast/provider.tsx +150 -51
- package/src/providers/toast/toast-item-renderer.tsx +5 -1
- package/src/providers/toast/types.ts +22 -8
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
3
|
+
import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/constants';
|
|
4
|
+
|
|
5
|
+
export const menuRootVariants = cva(
|
|
6
|
+
[
|
|
7
|
+
'bg-surface-primary',
|
|
8
|
+
'border border-stroke-secondary',
|
|
9
|
+
'overflow-hidden',
|
|
10
|
+
'rounded-xl',
|
|
11
|
+
'p-1',
|
|
12
|
+
'shadow-lg',
|
|
13
|
+
'web:outline-none',
|
|
14
|
+
],
|
|
15
|
+
{
|
|
16
|
+
variants: {
|
|
17
|
+
scrollable: {
|
|
18
|
+
true: 'max-h-60 shrink',
|
|
19
|
+
false: '',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
scrollable: false,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const menuItemVariants = cva(
|
|
29
|
+
[
|
|
30
|
+
'flex-row items-center gap-2',
|
|
31
|
+
'min-h-9',
|
|
32
|
+
'rounded-lg',
|
|
33
|
+
TRANSITION_COLORS,
|
|
34
|
+
'data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none',
|
|
35
|
+
DISABLED_CURSOR,
|
|
36
|
+
'data-[state=checked]:bg-surface-action-tint data-[state=checked]:font-medium',
|
|
37
|
+
Platform.select({
|
|
38
|
+
default: 'data-[active=true]:bg-surface-action-tint-active',
|
|
39
|
+
web: 'data-[hover=true]:bg-surface-action-tint-hover data-[active=true]:data-[hover=true]:bg-surface-action-tint-active data-[highlighted=true]:bg-surface-action-tint-hover',
|
|
40
|
+
}),
|
|
41
|
+
],
|
|
42
|
+
{
|
|
43
|
+
variants: {
|
|
44
|
+
color: {
|
|
45
|
+
neutral: 'text-content-primary',
|
|
46
|
+
danger:
|
|
47
|
+
'text-content-danger data-[hover=true]:bg-surface-danger-tint-hover data-[highlighted=true]:bg-surface-danger-tint-hover',
|
|
48
|
+
},
|
|
49
|
+
inset: {
|
|
50
|
+
true: '',
|
|
51
|
+
false: '',
|
|
52
|
+
},
|
|
53
|
+
size: {
|
|
54
|
+
default: 'px-3 py-2',
|
|
55
|
+
small: 'px-2.5 py-1.5',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
compoundVariants: [
|
|
59
|
+
{
|
|
60
|
+
inset: true,
|
|
61
|
+
size: 'default',
|
|
62
|
+
class: 'ps-8 pe-3 py-2',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
inset: true,
|
|
66
|
+
size: 'small',
|
|
67
|
+
class: 'ps-8 pe-2.5 py-1.5',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
inset: false,
|
|
71
|
+
size: 'default',
|
|
72
|
+
class: 'px-3 py-2',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
inset: false,
|
|
76
|
+
size: 'small',
|
|
77
|
+
class: 'px-2.5 py-1.5',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
defaultVariants: {
|
|
81
|
+
color: 'neutral',
|
|
82
|
+
inset: false,
|
|
83
|
+
size: 'default',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
export const menuItemLabelVariants = cva(
|
|
89
|
+
[
|
|
90
|
+
'text-start',
|
|
91
|
+
Platform.select({
|
|
92
|
+
default: 'shrink-0',
|
|
93
|
+
web: 'min-w-0 flex-1',
|
|
94
|
+
}),
|
|
95
|
+
],
|
|
96
|
+
{
|
|
97
|
+
variants: {
|
|
98
|
+
size: {
|
|
99
|
+
default: 'text-[0.875rem]',
|
|
100
|
+
small: 'text-[0.75rem]',
|
|
101
|
+
},
|
|
102
|
+
color: {
|
|
103
|
+
neutral: 'text-content-primary',
|
|
104
|
+
danger: 'text-content-danger',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
defaultVariants: {
|
|
108
|
+
size: 'default',
|
|
109
|
+
color: 'neutral',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
export const menuItemIconVariants = cva(['shrink-0', 'size-5'], {
|
|
115
|
+
variants: {
|
|
116
|
+
color: {
|
|
117
|
+
neutral: 'text-content-secondary',
|
|
118
|
+
danger: 'text-content-danger',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
defaultVariants: {
|
|
122
|
+
color: 'neutral',
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const menuItemShortcutVariants = cva([
|
|
127
|
+
'shrink-0 text-content-tertiary',
|
|
128
|
+
'text-[0.75rem]',
|
|
129
|
+
'ms-auto',
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
export const menuItemIndicatorVariants = cva([
|
|
133
|
+
'shrink-0 data-[icon=inline-end]:ms-auto',
|
|
134
|
+
'text-content-action',
|
|
135
|
+
'size-5',
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
export const menuSectionLabelVariants = cva([
|
|
139
|
+
'px-3 py-1.5',
|
|
140
|
+
'text-[0.75rem] font-medium',
|
|
141
|
+
'text-content-tertiary',
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
export const menuSeparatorVariants = cva([
|
|
145
|
+
// Bleed past menu `p-1` inset so the line spans the full panel width (Figma: px-[-4px]).
|
|
146
|
+
// Omit `w-full`: percentage width ignores the negative margins and leaves a right-side gap.
|
|
147
|
+
'self-stretch py-1 -mx-1',
|
|
148
|
+
]);
|
|
149
|
+
|
|
150
|
+
export const menuSeparatorLineVariants = cva(['h-px w-full bg-stroke-secondary']);
|
|
151
|
+
|
|
152
|
+
export type MenuRootVariantProps = VariantProps<typeof menuRootVariants>;
|
|
153
|
+
export type MenuItemVariantProps = VariantProps<typeof menuItemVariants>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useMemo, type ReactNode } from 'react';
|
|
1
|
+
import { cloneElement, forwardRef, isValidElement, useMemo, type ReactNode } from 'react';
|
|
2
2
|
import { Text, type TextProps, View, type ViewProps } from 'react-native';
|
|
3
3
|
import { KeyboardArrowDown, KeyboardArrowUp } from '@cdx-ui/icons';
|
|
4
4
|
import {
|
|
@@ -20,13 +20,12 @@ import {
|
|
|
20
20
|
} from '@cdx-ui/primitives';
|
|
21
21
|
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
22
22
|
import { Icon, IconProps } from '../Icon';
|
|
23
|
+
import { Menu } from '../Menu';
|
|
24
|
+
import { menuItemLabelVariants, menuItemVariants } from '../Menu/styles';
|
|
23
25
|
import { positionToDataIcon, type IconSlotPosition } from '../../utils/positionToDataIcon';
|
|
24
26
|
import {
|
|
25
27
|
type SelectVariantProps,
|
|
26
|
-
selectContentVariants,
|
|
27
28
|
selectIconVariants,
|
|
28
|
-
selectItemLabelVariants,
|
|
29
|
-
selectItemVariants,
|
|
30
29
|
selectTriggerVariants,
|
|
31
30
|
selectValueVariants,
|
|
32
31
|
} from './styles';
|
|
@@ -35,6 +34,9 @@ const SCOPE = 'SELECT';
|
|
|
35
34
|
|
|
36
35
|
const useSelectStyleContext = () => useStyleContext(SCOPE) as SelectVariantProps;
|
|
37
36
|
|
|
37
|
+
const toMenuItemSize = (size: SelectVariantProps['size'] | undefined) =>
|
|
38
|
+
size === 'small' ? 'small' : 'default';
|
|
39
|
+
|
|
38
40
|
// =============================================================================
|
|
39
41
|
// STYLED ROOT
|
|
40
42
|
// =============================================================================
|
|
@@ -213,7 +215,7 @@ const SelectIcon = ({ asChild, className, style, as, position, ...props }: Selec
|
|
|
213
215
|
SelectIcon.displayName = 'Select.Icon';
|
|
214
216
|
|
|
215
217
|
// =============================================================================
|
|
216
|
-
// STYLED CONTENT
|
|
218
|
+
// STYLED CONTENT — composes Menu surface (listbox semantics stay on primitive)
|
|
217
219
|
// =============================================================================
|
|
218
220
|
|
|
219
221
|
export interface SelectContentProps extends ViewProps, ISelectContentProps {
|
|
@@ -222,18 +224,33 @@ export interface SelectContentProps extends ViewProps, ISelectContentProps {
|
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
const SelectContent = forwardRef<View, SelectContentProps>(
|
|
225
|
-
({ asChild, className, style, ...props }, ref) => {
|
|
226
|
-
|
|
227
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
228
|
+
if (asChild) {
|
|
229
|
+
return (
|
|
230
|
+
<SelectContentPrimitive
|
|
231
|
+
ref={ref}
|
|
232
|
+
asChild
|
|
233
|
+
className={className}
|
|
234
|
+
style={style}
|
|
235
|
+
{...props}
|
|
236
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'select-content' }))}
|
|
237
|
+
>
|
|
238
|
+
{children}
|
|
239
|
+
</SelectContentPrimitive>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
227
242
|
|
|
228
243
|
return (
|
|
229
244
|
<SelectContentPrimitive
|
|
230
245
|
ref={ref}
|
|
231
|
-
asChild={asChild}
|
|
232
|
-
className={computedClassName}
|
|
233
246
|
style={style}
|
|
234
247
|
{...props}
|
|
235
248
|
{...mergeDataAttributes(props, dataAttributes({ slot: 'select-content' }))}
|
|
236
|
-
|
|
249
|
+
>
|
|
250
|
+
<Menu.Content asSurface scrollable className={className}>
|
|
251
|
+
{children}
|
|
252
|
+
</Menu.Content>
|
|
253
|
+
</SelectContentPrimitive>
|
|
237
254
|
);
|
|
238
255
|
},
|
|
239
256
|
);
|
|
@@ -241,7 +258,7 @@ const SelectContent = forwardRef<View, SelectContentProps>(
|
|
|
241
258
|
SelectContent.displayName = 'Select.Content';
|
|
242
259
|
|
|
243
260
|
// =============================================================================
|
|
244
|
-
// STYLED ITEM
|
|
261
|
+
// STYLED ITEM — composes Menu item visuals (option semantics stay on primitive)
|
|
245
262
|
// =============================================================================
|
|
246
263
|
|
|
247
264
|
export interface SelectItemProps extends ISelectItemProps {
|
|
@@ -251,21 +268,38 @@ export interface SelectItemProps extends ISelectItemProps {
|
|
|
251
268
|
}
|
|
252
269
|
|
|
253
270
|
const SelectItem = forwardRef<View, SelectItemProps>(
|
|
254
|
-
({ asChild, className, children, style, ...props }, ref) => {
|
|
271
|
+
({ asChild, className, children, style, value: itemValue, ...props }, ref) => {
|
|
255
272
|
const { size } = useSelectStyleContext();
|
|
256
|
-
|
|
257
|
-
const
|
|
273
|
+
const { value: selectedValue } = useSelectContext();
|
|
274
|
+
const menuSize = toMenuItemSize(size);
|
|
275
|
+
const checked = selectedValue === itemValue;
|
|
276
|
+
|
|
277
|
+
const computedClassName = cn(menuItemVariants({ size: menuSize }), className);
|
|
278
|
+
const selectedIcon = <Menu.ItemIndicator isChecked={checked} />;
|
|
279
|
+
const itemChildren = asChild ? (
|
|
280
|
+
selectedIcon && isValidElement<{ children?: ReactNode }>(children) ? (
|
|
281
|
+
cloneElement(children, undefined, children.props.children, selectedIcon)
|
|
282
|
+
) : (
|
|
283
|
+
children
|
|
284
|
+
)
|
|
285
|
+
) : (
|
|
286
|
+
<>
|
|
287
|
+
{children}
|
|
288
|
+
{selectedIcon}
|
|
289
|
+
</>
|
|
290
|
+
);
|
|
258
291
|
|
|
259
292
|
return (
|
|
260
293
|
<SelectItemPrimitive
|
|
261
294
|
ref={ref}
|
|
262
295
|
asChild={asChild}
|
|
296
|
+
value={itemValue}
|
|
263
297
|
className={computedClassName}
|
|
264
298
|
style={style}
|
|
265
299
|
{...props}
|
|
266
300
|
{...mergeDataAttributes(props, dataAttributes({ slot: 'select-item' }))}
|
|
267
301
|
>
|
|
268
|
-
{
|
|
302
|
+
{itemChildren}
|
|
269
303
|
</SelectItemPrimitive>
|
|
270
304
|
);
|
|
271
305
|
},
|
|
@@ -274,7 +308,7 @@ const SelectItem = forwardRef<View, SelectItemProps>(
|
|
|
274
308
|
SelectItem.displayName = 'Select.Item';
|
|
275
309
|
|
|
276
310
|
// =============================================================================
|
|
277
|
-
// STYLED ITEM LABEL
|
|
311
|
+
// STYLED ITEM LABEL — composes Menu.ItemLabel
|
|
278
312
|
// =============================================================================
|
|
279
313
|
|
|
280
314
|
export interface SelectItemLabelProps extends TextProps, ISelectItemLabelProps {
|
|
@@ -286,26 +320,27 @@ const SelectItemLabel = forwardRef<Text, SelectItemLabelProps>(
|
|
|
286
320
|
({ asChild, className, style, children, ...props }, ref) => {
|
|
287
321
|
const { size } = useSelectStyleContext();
|
|
288
322
|
const { checked } = useSelectItemContext();
|
|
289
|
-
|
|
290
|
-
const computedClassName = cn(selectItemLabelVariants({ size }), className);
|
|
291
|
-
const Comp = asChild ? Slot : Text;
|
|
323
|
+
const menuSize = toMenuItemSize(size);
|
|
292
324
|
|
|
293
325
|
return (
|
|
294
|
-
<
|
|
326
|
+
<Menu.ItemLabel
|
|
295
327
|
ref={ref}
|
|
296
|
-
|
|
328
|
+
asChild={asChild}
|
|
329
|
+
isChecked={checked}
|
|
330
|
+
size={menuSize}
|
|
331
|
+
className={cn(menuItemLabelVariants({ size: menuSize }), className)}
|
|
297
332
|
style={style}
|
|
298
333
|
{...props}
|
|
299
334
|
{...mergeDataAttributes(
|
|
300
|
-
props,
|
|
301
335
|
dataAttributes({
|
|
302
336
|
slot: 'select-item-label',
|
|
303
337
|
state: checked ? 'checked' : 'unchecked',
|
|
304
338
|
}),
|
|
339
|
+
props,
|
|
305
340
|
)}
|
|
306
341
|
>
|
|
307
342
|
{children}
|
|
308
|
-
</
|
|
343
|
+
</Menu.ItemLabel>
|
|
309
344
|
);
|
|
310
345
|
},
|
|
311
346
|
);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Platform } from 'react-native';
|
|
2
1
|
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
3
2
|
import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/constants';
|
|
4
3
|
|
|
@@ -112,62 +111,4 @@ export const selectIconVariants = cva(
|
|
|
112
111
|
},
|
|
113
112
|
);
|
|
114
113
|
|
|
115
|
-
// ── Content ─────────────────────────────────────────────────
|
|
116
|
-
|
|
117
|
-
export const selectContentVariants = cva([
|
|
118
|
-
'bg-surface-primary',
|
|
119
|
-
'border border-stroke-secondary',
|
|
120
|
-
'overflow-hidden',
|
|
121
|
-
'rounded-xl',
|
|
122
|
-
Platform.select({
|
|
123
|
-
web: 'shadow-sm',
|
|
124
|
-
default: '',
|
|
125
|
-
}),
|
|
126
|
-
'max-h-60',
|
|
127
|
-
'py-1',
|
|
128
|
-
]);
|
|
129
|
-
|
|
130
|
-
// ── Item ────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
export const selectItemVariants = cva(
|
|
133
|
-
[
|
|
134
|
-
'flex-row items-center',
|
|
135
|
-
'transition-colors duration-100',
|
|
136
|
-
'data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none',
|
|
137
|
-
'data-[state=checked]:bg-surface-action-tint data-[state=checked]:font-medium',
|
|
138
|
-
Platform.select({
|
|
139
|
-
default: 'data-[active=true]:bg-surface-action-tint-active',
|
|
140
|
-
web: 'data-[hover=true]:bg-surface-action-tint-hover data-[active=true]:data-[hover=true]:bg-surface-action-tint-active data-[highlighted=true]:bg-surface-action-tint-hover',
|
|
141
|
-
}),
|
|
142
|
-
],
|
|
143
|
-
{
|
|
144
|
-
variants: {
|
|
145
|
-
size: {
|
|
146
|
-
default: 'px-3 py-2',
|
|
147
|
-
small: 'px-2.5 py-1.5',
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
defaultVariants: {
|
|
151
|
-
size: 'default',
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// ── ItemLabel ───────────────────────────────────────────────
|
|
157
|
-
|
|
158
|
-
export const selectItemLabelVariants = cva(
|
|
159
|
-
['text-content-primary', 'data-[state=checked]:font-medium'],
|
|
160
|
-
{
|
|
161
|
-
variants: {
|
|
162
|
-
size: {
|
|
163
|
-
default: 'text-[0.875rem]',
|
|
164
|
-
small: 'text-[0.75rem]',
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
defaultVariants: {
|
|
168
|
-
size: 'default',
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
);
|
|
172
|
-
|
|
173
114
|
export type SelectVariantProps = VariantProps<typeof selectTriggerVariants>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Platform, type ViewStyle } from 'react-native';
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
getAnchoredOverlayPosition,
|
|
4
|
+
type AnchorLayout,
|
|
5
|
+
type SliderOrientation,
|
|
6
|
+
} from '@cdx-ui/primitives';
|
|
3
7
|
|
|
4
8
|
export const SLIDER_POPUP_OFFSET = 8;
|
|
5
9
|
export const SLIDER_POPUP_Z_INDEX = 9999;
|
|
@@ -13,24 +17,32 @@ export function getSliderPopupAnchorStyle(
|
|
|
13
17
|
orientation: SliderOrientation,
|
|
14
18
|
offset = SLIDER_POPUP_OFFSET,
|
|
15
19
|
): ViewStyle {
|
|
20
|
+
const result = getAnchoredOverlayPosition(
|
|
21
|
+
anchor,
|
|
22
|
+
{ width: 0, height: 0 },
|
|
23
|
+
{ width: Number.MAX_SAFE_INTEGER, height: Number.MAX_SAFE_INTEGER },
|
|
24
|
+
{
|
|
25
|
+
placement: orientation === 'vertical' ? 'right' : 'top',
|
|
26
|
+
offset,
|
|
27
|
+
collisionBehavior: 'none',
|
|
28
|
+
},
|
|
29
|
+
);
|
|
16
30
|
const position = (Platform.OS === 'web' ? 'fixed' : 'absolute') as ViewStyle['position'];
|
|
17
31
|
|
|
18
32
|
if (orientation === 'vertical') {
|
|
19
|
-
const centerY = anchor.y + anchor.height / 2;
|
|
20
33
|
return {
|
|
21
34
|
position,
|
|
22
|
-
left:
|
|
23
|
-
top:
|
|
35
|
+
left: result.style.left,
|
|
36
|
+
top: result.style.top,
|
|
24
37
|
zIndex: SLIDER_POPUP_Z_INDEX,
|
|
25
38
|
transform: [{ translateY: '-50%' }] as ViewStyle['transform'],
|
|
26
39
|
};
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
const centerX = anchor.x + anchor.width / 2;
|
|
30
42
|
return {
|
|
31
43
|
position,
|
|
32
|
-
left:
|
|
33
|
-
top:
|
|
44
|
+
left: result.style.left,
|
|
45
|
+
top: result.style.top,
|
|
34
46
|
zIndex: SLIDER_POPUP_Z_INDEX,
|
|
35
47
|
transform: [{ translateX: '-50%' }, { translateY: '-100%' }] as ViewStyle['transform'],
|
|
36
48
|
};
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
Slot,
|
|
17
17
|
Portal,
|
|
18
18
|
createPortalFn,
|
|
19
|
-
|
|
19
|
+
useAnchoredOverlay,
|
|
20
20
|
dataAttributes,
|
|
21
21
|
getMarkerPositionStyle,
|
|
22
22
|
getMarkerStepValues,
|
|
@@ -29,7 +29,14 @@ import {
|
|
|
29
29
|
type ISliderThumbProps,
|
|
30
30
|
type SliderOrientation,
|
|
31
31
|
} from '@cdx-ui/primitives';
|
|
32
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
cn,
|
|
34
|
+
composeEventHandlers,
|
|
35
|
+
mergeRefs,
|
|
36
|
+
ParentContext,
|
|
37
|
+
useParentContext,
|
|
38
|
+
useStyleContext,
|
|
39
|
+
} from '@cdx-ui/utils';
|
|
33
40
|
import {
|
|
34
41
|
sliderMarkerVariants,
|
|
35
42
|
sliderPopupBaseVariants,
|
|
@@ -42,7 +49,7 @@ import {
|
|
|
42
49
|
type SliderColor,
|
|
43
50
|
type SliderVariantProps,
|
|
44
51
|
} from './styles';
|
|
45
|
-
import {
|
|
52
|
+
import { SLIDER_POPUP_OFFSET, SLIDER_POPUP_Z_INDEX } from './getSliderPopupPosition';
|
|
46
53
|
|
|
47
54
|
const SCOPE = 'SLIDER';
|
|
48
55
|
|
|
@@ -256,33 +263,42 @@ export interface SliderPopupProps extends ViewProps {
|
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
const SliderPopup = forwardRef<View, SliderPopupProps>(
|
|
259
|
-
({ asChild, className, style, children, ...props }, ref) => {
|
|
266
|
+
({ asChild, className, style, children, onLayout, ...props }, ref) => {
|
|
260
267
|
const { orientation } = useSliderStyleContext();
|
|
261
268
|
const { isDragging, isHovered, isFocused, getValueLabel, thumbRef, percent } =
|
|
262
269
|
useSliderContext();
|
|
263
270
|
const portalName = useId();
|
|
264
271
|
|
|
265
272
|
const visible = isDragging || isHovered || isFocused;
|
|
266
|
-
const
|
|
273
|
+
const {
|
|
274
|
+
floatingRef,
|
|
275
|
+
onFloatingLayout,
|
|
276
|
+
style: popupPositionStyle,
|
|
277
|
+
} = useAnchoredOverlay(thumbRef, visible, {
|
|
278
|
+
placement: orientation === 'vertical' ? 'right' : 'top',
|
|
279
|
+
offset: SLIDER_POPUP_OFFSET,
|
|
280
|
+
collisionBehavior: 'none',
|
|
281
|
+
width: 'content',
|
|
267
282
|
remeasureKey: percent,
|
|
268
283
|
trackWhileOpen: true,
|
|
269
284
|
});
|
|
270
285
|
|
|
271
|
-
if (!visible
|
|
286
|
+
if (!visible) {
|
|
272
287
|
return null;
|
|
273
288
|
}
|
|
274
289
|
|
|
275
290
|
const label = renderPopupLabel(children, getValueLabel);
|
|
276
291
|
const computedClassName = cn(sliderPopupBaseVariants(), className);
|
|
277
292
|
const Comp = asChild ? Slot : View;
|
|
278
|
-
const anchorStyle = getSliderPopupAnchorStyle(anchorLayout, orientation);
|
|
279
293
|
|
|
280
294
|
const popup = (
|
|
281
|
-
<View pointerEvents="none" style={
|
|
295
|
+
<View pointerEvents="none" style={[popupPositionStyle, { zIndex: SLIDER_POPUP_Z_INDEX }]}>
|
|
282
296
|
<Comp
|
|
283
|
-
ref={ref}
|
|
297
|
+
ref={mergeRefs(ref, floatingRef)}
|
|
284
298
|
className={computedClassName}
|
|
285
299
|
style={style}
|
|
300
|
+
onLayout={composeEventHandlers(onLayout, onFloatingLayout)}
|
|
301
|
+
{...props}
|
|
286
302
|
accessibilityElementsHidden
|
|
287
303
|
importantForAccessibility="no-hide-descendants"
|
|
288
304
|
{...mergeDataAttributes(
|
|
@@ -155,7 +155,7 @@ const ToastRoot = forwardRef<View, ToastProps>((props, ref) => {
|
|
|
155
155
|
|
|
156
156
|
const lifecycle = useToastLifecycle();
|
|
157
157
|
const isPendingRemoval = lifecycle?.pendingRemovalIds.has(id) ?? false;
|
|
158
|
-
const isFrontmost = lifecycle?.
|
|
158
|
+
const isFrontmost = lifecycle?.frontmostIds.has(id) ?? false;
|
|
159
159
|
|
|
160
160
|
const [localState, setLocalState] = useState<Exclude<ToastDataState, 'closed'>>('entering');
|
|
161
161
|
|
|
@@ -123,7 +123,7 @@ export type ToastRootAnimation = AnimationRoot<{
|
|
|
123
123
|
/**
|
|
124
124
|
* Props for the Toast.Root component
|
|
125
125
|
*/
|
|
126
|
-
export interface ToastProps extends ToastRootProps, Omit<ToastComponentProps, 'id'> {
|
|
126
|
+
export interface ToastProps extends ToastRootProps, Omit<ToastComponentProps, 'id' | 'placement'> {
|
|
127
127
|
/**
|
|
128
128
|
* Color of the toast
|
|
129
129
|
* @default 'neutral'
|
|
@@ -291,7 +291,7 @@ export type UseToastRootAnimationOptions = Pick<
|
|
|
291
291
|
* Props for the DefaultToast component
|
|
292
292
|
* Used internally when showing toasts with string or config object (without component)
|
|
293
293
|
*/
|
|
294
|
-
export interface DefaultToastProps extends ToastComponentProps {
|
|
294
|
+
export interface DefaultToastProps extends Omit<ToastComponentProps, 'placement'> {
|
|
295
295
|
/**
|
|
296
296
|
* Color of the toast
|
|
297
297
|
* @default 'neutral'
|
package/src/components/index.ts
CHANGED
|
@@ -3,12 +3,11 @@ import { ScrollView, View } from 'react-native';
|
|
|
3
3
|
import { FadeIn, FadeOut } from 'react-native-reanimated';
|
|
4
4
|
import {
|
|
5
5
|
OverlayContainer,
|
|
6
|
-
|
|
6
|
+
useAnchoredOverlay,
|
|
7
7
|
useDismissOverlay,
|
|
8
8
|
useEscapeKey,
|
|
9
|
-
useOverlayPosition,
|
|
10
9
|
} from '@cdx-ui/primitives';
|
|
11
|
-
import { cn } from '@cdx-ui/utils';
|
|
10
|
+
import { cn, mergeRefs } from '@cdx-ui/utils';
|
|
12
11
|
import { Dialog } from '../Dialog';
|
|
13
12
|
import { BottomSheet, useBottomSheet, type BottomSheetModalProps } from '../BottomSheet';
|
|
14
13
|
import { PICKER_POPOVER_Z_INDEX, pickerPopoverContentVariants } from './styles';
|
|
@@ -141,14 +140,18 @@ export function PickerPopoverSurface({
|
|
|
141
140
|
|
|
142
141
|
const dismiss = useCallback(() => setOpen(false), [setOpen]);
|
|
143
142
|
|
|
144
|
-
const
|
|
145
|
-
|
|
143
|
+
const { floatingRef, onFloatingLayout, style } = useAnchoredOverlay(anchorRef, open, {
|
|
144
|
+
placement: 'bottom-start',
|
|
145
|
+
offset: 4,
|
|
146
|
+
collisionBehavior: 'flip-shift',
|
|
147
|
+
width: 'anchor',
|
|
148
|
+
});
|
|
146
149
|
|
|
147
150
|
const excludeRefs = triggerRef ? [anchorRef, triggerRef] : [anchorRef];
|
|
148
151
|
useDismissOverlay(dismissEnabled, contentRef, excludeRefs, dismiss);
|
|
149
152
|
useEscapeKey(open, dismiss);
|
|
150
153
|
|
|
151
|
-
if (!open
|
|
154
|
+
if (!open) {
|
|
152
155
|
return null;
|
|
153
156
|
}
|
|
154
157
|
|
|
@@ -157,12 +160,13 @@ export function PickerPopoverSurface({
|
|
|
157
160
|
onDismiss={dismiss}
|
|
158
161
|
entering={FadeIn.duration(150)}
|
|
159
162
|
exiting={FadeOut.duration(100)}
|
|
160
|
-
style={
|
|
163
|
+
style={{ zIndex: PICKER_POPOVER_Z_INDEX }}
|
|
161
164
|
>
|
|
162
165
|
<View
|
|
163
|
-
ref={contentRef}
|
|
166
|
+
ref={mergeRefs(contentRef, floatingRef)}
|
|
167
|
+
onLayout={onFloatingLayout}
|
|
164
168
|
className={cn(pickerPopoverContentVariants(), className)}
|
|
165
|
-
style={
|
|
169
|
+
style={style}
|
|
166
170
|
accessibilityViewIsModal
|
|
167
171
|
>
|
|
168
172
|
<ScrollView scrollEventThrottle={16} showsVerticalScrollIndicator={false}>
|