@cdx-ui/components 0.1.5 → 0.1.7
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/Alert/index.js.map +1 -1
- package/lib/commonjs/components/Avatar/index.js +6 -4
- package/lib/commonjs/components/Avatar/index.js.map +1 -1
- package/lib/commonjs/components/Badge/index.js.map +1 -1
- package/lib/commonjs/components/Badge/styles.js +2 -2
- package/lib/commonjs/components/BottomSheet/index.js +106 -91
- package/lib/commonjs/components/BottomSheet/index.js.map +1 -1
- package/lib/commonjs/components/BottomSheet/styles.js +1 -12
- package/lib/commonjs/components/BottomSheet/styles.js.map +1 -1
- package/lib/commonjs/components/Button/index.js.map +1 -1
- package/lib/commonjs/components/Card/index.js.map +1 -1
- package/lib/commonjs/components/Dialog/index.js.map +1 -1
- package/lib/commonjs/components/Divider/index.js.map +1 -1
- package/lib/commonjs/components/Form/styles.js +1 -1
- package/lib/commonjs/components/Form/styles.js.map +1 -1
- package/lib/commonjs/components/FullScreenDialog/animation.js +46 -0
- package/lib/commonjs/components/FullScreenDialog/animation.js.map +1 -0
- package/lib/commonjs/components/FullScreenDialog/index.js +343 -0
- package/lib/commonjs/components/FullScreenDialog/index.js.map +1 -0
- package/lib/commonjs/components/FullScreenDialog/styles.js +14 -0
- package/lib/commonjs/components/FullScreenDialog/styles.js.map +1 -0
- package/lib/commonjs/components/IconButton/styles.js +7 -5
- package/lib/commonjs/components/IconButton/styles.js.map +1 -1
- package/lib/commonjs/components/InsuranceDisclosure/index.js.map +1 -1
- package/lib/commonjs/components/Link/index.js.map +1 -1
- package/lib/commonjs/components/ListItem/index.js +2 -0
- package/lib/commonjs/components/ListItem/index.js.map +1 -1
- package/lib/commonjs/components/ListItem/styles.js +6 -0
- package/lib/commonjs/components/ListItem/styles.js.map +1 -1
- package/lib/commonjs/components/ProgressSegmented/index.js.map +1 -1
- package/lib/commonjs/components/Radio/index.js.map +1 -1
- package/lib/commonjs/components/ScopedTheme/index.js +11 -3
- package/lib/commonjs/components/ScopedTheme/index.js.map +1 -1
- package/lib/commonjs/components/Skeleton/index.js.map +1 -1
- package/lib/commonjs/components/Stack/HStack.js.map +1 -1
- package/lib/commonjs/components/Stack/VStack.js.map +1 -1
- package/lib/commonjs/components/Textarea/index.js.map +1 -1
- package/lib/commonjs/components/Tile/index.js.map +1 -1
- package/lib/commonjs/components/Toast/index.js +40 -12
- package/lib/commonjs/components/Toast/index.js.map +1 -1
- package/lib/commonjs/components/Toast/styles.js +15 -4
- package/lib/commonjs/components/Toast/styles.js.map +1 -1
- package/lib/commonjs/components/ToggleButton/index.js +249 -0
- package/lib/commonjs/components/ToggleButton/index.js.map +1 -0
- package/lib/commonjs/components/ToggleButton/styles.js +155 -0
- package/lib/commonjs/components/ToggleButton/styles.js.map +1 -0
- package/lib/commonjs/components/index.js +24 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/components/picker/styles.js +6 -2
- package/lib/commonjs/components/picker/styles.js.map +1 -1
- package/lib/commonjs/components/sheet-header/index.js +97 -0
- package/lib/commonjs/components/sheet-header/index.js.map +1 -0
- package/lib/commonjs/components/sheet-header/styles.js +28 -0
- package/lib/commonjs/components/sheet-header/styles.js.map +1 -0
- package/lib/commonjs/figma/BottomSheet.figma.js +1 -1
- package/lib/commonjs/providers/toast/provider.js +44 -11
- package/lib/commonjs/providers/toast/provider.js.map +1 -1
- package/lib/module/components/Alert/index.js.map +1 -1
- package/lib/module/components/Avatar/index.js +6 -4
- package/lib/module/components/Avatar/index.js.map +1 -1
- package/lib/module/components/Badge/index.js.map +1 -1
- package/lib/module/components/Badge/styles.js +2 -2
- package/lib/module/components/BottomSheet/index.js +110 -95
- package/lib/module/components/BottomSheet/index.js.map +1 -1
- package/lib/module/components/BottomSheet/styles.js +0 -11
- package/lib/module/components/BottomSheet/styles.js.map +1 -1
- package/lib/module/components/Button/index.js.map +1 -1
- package/lib/module/components/Card/index.js.map +1 -1
- package/lib/module/components/Dialog/index.js.map +1 -1
- package/lib/module/components/Divider/index.js.map +1 -1
- package/lib/module/components/Form/styles.js +1 -1
- package/lib/module/components/Form/styles.js.map +1 -1
- package/lib/module/components/FullScreenDialog/animation.js +41 -0
- package/lib/module/components/FullScreenDialog/animation.js.map +1 -0
- package/lib/module/components/FullScreenDialog/index.js +338 -0
- package/lib/module/components/FullScreenDialog/index.js.map +1 -0
- package/lib/module/components/FullScreenDialog/styles.js +10 -0
- package/lib/module/components/FullScreenDialog/styles.js.map +1 -0
- package/lib/module/components/IconButton/styles.js +7 -4
- package/lib/module/components/IconButton/styles.js.map +1 -1
- package/lib/module/components/InsuranceDisclosure/index.js.map +1 -1
- package/lib/module/components/Link/index.js.map +1 -1
- package/lib/module/components/ListItem/index.js +2 -0
- package/lib/module/components/ListItem/index.js.map +1 -1
- package/lib/module/components/ListItem/styles.js +6 -0
- package/lib/module/components/ListItem/styles.js.map +1 -1
- package/lib/module/components/ProgressSegmented/index.js.map +1 -1
- package/lib/module/components/Radio/index.js.map +1 -1
- package/lib/module/components/ScopedTheme/index.js +11 -3
- package/lib/module/components/ScopedTheme/index.js.map +1 -1
- package/lib/module/components/Skeleton/index.js.map +1 -1
- package/lib/module/components/Stack/HStack.js.map +1 -1
- package/lib/module/components/Stack/VStack.js.map +1 -1
- package/lib/module/components/Textarea/index.js.map +1 -1
- package/lib/module/components/Tile/index.js.map +1 -1
- package/lib/module/components/Toast/index.js +43 -15
- package/lib/module/components/Toast/index.js.map +1 -1
- package/lib/module/components/Toast/styles.js +14 -3
- package/lib/module/components/Toast/styles.js.map +1 -1
- package/lib/module/components/ToggleButton/index.js +245 -0
- package/lib/module/components/ToggleButton/index.js.map +1 -0
- package/lib/module/components/ToggleButton/styles.js +152 -0
- package/lib/module/components/ToggleButton/styles.js.map +1 -0
- package/lib/module/components/index.js +2 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/picker/styles.js +6 -2
- package/lib/module/components/picker/styles.js.map +1 -1
- package/lib/module/components/sheet-header/index.js +94 -0
- package/lib/module/components/sheet-header/index.js.map +1 -0
- package/lib/module/components/sheet-header/styles.js +25 -0
- package/lib/module/components/sheet-header/styles.js.map +1 -0
- package/lib/module/figma/BottomSheet.figma.js +1 -1
- package/lib/module/providers/toast/provider.js +44 -11
- package/lib/module/providers/toast/provider.js.map +1 -1
- package/lib/typescript/components/Alert/index.d.ts +4 -1
- package/lib/typescript/components/Alert/index.d.ts.map +1 -1
- package/lib/typescript/components/Avatar/index.d.ts +10 -4
- package/lib/typescript/components/Avatar/index.d.ts.map +1 -1
- package/lib/typescript/components/Badge/index.d.ts +34 -0
- package/lib/typescript/components/Badge/index.d.ts.map +1 -1
- package/lib/typescript/components/BottomSheet/index.d.ts +12 -1
- package/lib/typescript/components/BottomSheet/index.d.ts.map +1 -1
- package/lib/typescript/components/BottomSheet/styles.d.ts +0 -5
- package/lib/typescript/components/BottomSheet/styles.d.ts.map +1 -1
- package/lib/typescript/components/Button/index.d.ts +9 -1
- package/lib/typescript/components/Button/index.d.ts.map +1 -1
- package/lib/typescript/components/Card/index.d.ts +14 -0
- package/lib/typescript/components/Card/index.d.ts.map +1 -1
- package/lib/typescript/components/Chip/index.d.ts +1 -1
- package/lib/typescript/components/CurrencyInput/index.d.ts +2 -2
- package/lib/typescript/components/CurrencyInput/index.d.ts.map +1 -1
- package/lib/typescript/components/Dialog/index.d.ts +10 -0
- package/lib/typescript/components/Dialog/index.d.ts.map +1 -1
- package/lib/typescript/components/Dialog/styles.d.ts +1 -0
- package/lib/typescript/components/Dialog/styles.d.ts.map +1 -1
- package/lib/typescript/components/Divider/index.d.ts +5 -0
- package/lib/typescript/components/Divider/index.d.ts.map +1 -1
- package/lib/typescript/components/Drawer/styles.d.ts +1 -1
- package/lib/typescript/components/Form/styles.d.ts.map +1 -1
- package/lib/typescript/components/FullScreenDialog/animation.d.ts +9 -0
- package/lib/typescript/components/FullScreenDialog/animation.d.ts.map +1 -0
- package/lib/typescript/components/FullScreenDialog/index.d.ts +85 -0
- package/lib/typescript/components/FullScreenDialog/index.d.ts.map +1 -0
- package/lib/typescript/components/FullScreenDialog/styles.d.ts +6 -0
- package/lib/typescript/components/FullScreenDialog/styles.d.ts.map +1 -0
- package/lib/typescript/components/IconButton/styles.d.ts +5 -0
- package/lib/typescript/components/IconButton/styles.d.ts.map +1 -1
- package/lib/typescript/components/Input/index.d.ts +1 -1
- package/lib/typescript/components/InsuranceDisclosure/index.d.ts +1 -0
- package/lib/typescript/components/InsuranceDisclosure/index.d.ts.map +1 -1
- package/lib/typescript/components/Link/index.d.ts +2 -0
- package/lib/typescript/components/Link/index.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/index.d.ts +43 -4
- package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/styles.d.ts +2 -0
- package/lib/typescript/components/ListItem/styles.d.ts.map +1 -1
- package/lib/typescript/components/ProgressSegmented/index.d.ts +10 -3
- package/lib/typescript/components/ProgressSegmented/index.d.ts.map +1 -1
- package/lib/typescript/components/Radio/index.d.ts +1 -0
- package/lib/typescript/components/Radio/index.d.ts.map +1 -1
- package/lib/typescript/components/ScopedTheme/index.d.ts +11 -3
- package/lib/typescript/components/ScopedTheme/index.d.ts.map +1 -1
- package/lib/typescript/components/Skeleton/index.d.ts +5 -1
- package/lib/typescript/components/Skeleton/index.d.ts.map +1 -1
- package/lib/typescript/components/Stack/HStack.d.ts +6 -0
- package/lib/typescript/components/Stack/HStack.d.ts.map +1 -1
- package/lib/typescript/components/Stack/VStack.d.ts +6 -0
- package/lib/typescript/components/Stack/VStack.d.ts.map +1 -1
- package/lib/typescript/components/Switch/index.d.ts +1 -1
- package/lib/typescript/components/Tabs/index.d.ts +2 -2
- package/lib/typescript/components/Textarea/index.d.ts +1 -0
- package/lib/typescript/components/Textarea/index.d.ts.map +1 -1
- package/lib/typescript/components/Tile/index.d.ts +49 -0
- package/lib/typescript/components/Tile/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/index.d.ts +15 -0
- package/lib/typescript/components/Toast/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/styles.d.ts +10 -0
- package/lib/typescript/components/Toast/styles.d.ts.map +1 -1
- package/lib/typescript/components/Toast/types.d.ts +9 -0
- package/lib/typescript/components/Toast/types.d.ts.map +1 -1
- package/lib/typescript/components/ToggleButton/index.d.ts +78 -0
- package/lib/typescript/components/ToggleButton/index.d.ts.map +1 -0
- package/lib/typescript/components/ToggleButton/styles.d.ts +30 -0
- package/lib/typescript/components/ToggleButton/styles.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +2 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/components/picker/styles.d.ts +5 -2
- package/lib/typescript/components/picker/styles.d.ts.map +1 -1
- package/lib/typescript/components/sheet-header/index.d.ts +24 -0
- package/lib/typescript/components/sheet-header/index.d.ts.map +1 -0
- package/lib/typescript/components/sheet-header/styles.d.ts +12 -0
- package/lib/typescript/components/sheet-header/styles.d.ts.map +1 -0
- package/lib/typescript/providers/toast/provider.d.ts +1 -1
- package/lib/typescript/providers/toast/provider.d.ts.map +1 -1
- package/lib/typescript/providers/toast/types.d.ts +16 -4
- package/lib/typescript/providers/toast/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/Alert/index.tsx +4 -1
- package/src/components/Avatar/index.tsx +10 -4
- package/src/components/Badge/index.tsx +34 -0
- package/src/components/Badge/styles.ts +2 -2
- package/src/components/BottomSheet/index.tsx +156 -125
- package/src/components/BottomSheet/styles.ts +1 -22
- package/src/components/Button/index.tsx +9 -1
- package/src/components/Card/index.tsx +14 -0
- package/src/components/Chip/index.tsx +1 -1
- package/src/components/CurrencyInput/index.tsx +2 -2
- package/src/components/Dialog/index.tsx +10 -0
- package/src/components/Dialog/styles.ts +1 -0
- package/src/components/Divider/index.tsx +5 -0
- package/src/components/Form/styles.ts +1 -1
- package/src/components/FullScreenDialog/animation.ts +22 -0
- package/src/components/FullScreenDialog/index.tsx +484 -0
- package/src/components/FullScreenDialog/styles.ts +23 -0
- package/src/components/IconButton/styles.ts +7 -4
- package/src/components/Input/index.tsx +1 -1
- package/src/components/InsuranceDisclosure/index.tsx +1 -0
- package/src/components/Link/index.tsx +2 -0
- package/src/components/ListItem/index.tsx +48 -4
- package/src/components/ListItem/styles.ts +7 -0
- package/src/components/ProgressSegmented/index.tsx +10 -3
- package/src/components/Radio/index.tsx +1 -0
- package/src/components/ScopedTheme/index.tsx +11 -3
- package/src/components/Skeleton/index.tsx +5 -1
- package/src/components/Stack/HStack.tsx +6 -0
- package/src/components/Stack/VStack.tsx +6 -0
- package/src/components/Switch/index.tsx +1 -1
- package/src/components/Tabs/index.tsx +2 -2
- package/src/components/Textarea/index.tsx +1 -0
- package/src/components/Tile/index.tsx +49 -0
- package/src/components/Toast/index.tsx +55 -9
- package/src/components/Toast/styles.ts +14 -3
- package/src/components/Toast/types.ts +9 -0
- package/src/components/ToggleButton/index.tsx +346 -0
- package/src/components/ToggleButton/styles.ts +191 -0
- package/src/components/index.ts +2 -0
- package/src/components/picker/styles.ts +6 -2
- package/src/components/sheet-header/index.tsx +148 -0
- package/src/components/sheet-header/styles.ts +28 -0
- package/src/providers/toast/provider.tsx +47 -13
- package/src/providers/toast/types.ts +16 -4
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo, type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
import { Text, View, type StyleProp, type TextProps, type ViewStyle } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
Slot,
|
|
5
|
+
ToggleButtonGroup as ToggleButtonGroupPrimitive,
|
|
6
|
+
ToggleButtonRoot as ToggleButtonRootPrimitive,
|
|
7
|
+
dataAttributes,
|
|
8
|
+
mergeDataAttributes,
|
|
9
|
+
useToggleButtonContext,
|
|
10
|
+
type IToggleButtonGroupMultipleProps,
|
|
11
|
+
type IToggleButtonGroupSingleProps,
|
|
12
|
+
type IToggleButtonProps,
|
|
13
|
+
} from '@cdx-ui/primitives';
|
|
14
|
+
import {
|
|
15
|
+
cn,
|
|
16
|
+
flattenChildren,
|
|
17
|
+
ParentContext,
|
|
18
|
+
useParentContext,
|
|
19
|
+
useStyleContext,
|
|
20
|
+
} from '@cdx-ui/utils';
|
|
21
|
+
import { Icon, type IconProps } from '../Icon';
|
|
22
|
+
import { positionToDataIcon, type IconSlotPosition } from '../../utils/positionToDataIcon';
|
|
23
|
+
import {
|
|
24
|
+
toggleButtonAttachedVariants,
|
|
25
|
+
toggleButtonGroupVariants,
|
|
26
|
+
toggleButtonIconVariants,
|
|
27
|
+
toggleButtonLabelVariants,
|
|
28
|
+
toggleButtonRootVariants,
|
|
29
|
+
type ToggleButtonAttachedPosition,
|
|
30
|
+
type ToggleButtonGroupVariantProps,
|
|
31
|
+
type ToggleButtonVariantProps,
|
|
32
|
+
} from './styles';
|
|
33
|
+
|
|
34
|
+
const SCOPE = 'TOGGLE_BUTTON';
|
|
35
|
+
|
|
36
|
+
const useToggleButtonStyleContext = () => useStyleContext(SCOPE) as ToggleButtonVariantProps;
|
|
37
|
+
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// STYLED ROOT COMPONENT
|
|
40
|
+
// =============================================================================
|
|
41
|
+
|
|
42
|
+
export type ToggleButtonVariant = 'default' | 'outline' | 'ghost';
|
|
43
|
+
export type ToggleButtonShape = NonNullable<ToggleButtonVariantProps['shape']>;
|
|
44
|
+
|
|
45
|
+
export interface ToggleButtonProps extends IToggleButtonProps {
|
|
46
|
+
/**
|
|
47
|
+
* Visual style. `default` is a muted filled surface; `outline` adds a border; `ghost` is transparent.
|
|
48
|
+
* @default 'default'
|
|
49
|
+
*/
|
|
50
|
+
variant?: ToggleButtonVariant;
|
|
51
|
+
/**
|
|
52
|
+
* Corner geometry — mirrors `Avatar.shape`.
|
|
53
|
+
* @default 'circle'
|
|
54
|
+
*/
|
|
55
|
+
shape?: ToggleButtonShape;
|
|
56
|
+
/**
|
|
57
|
+
* Height and padding scale.
|
|
58
|
+
* @default 'default'
|
|
59
|
+
*/
|
|
60
|
+
size?: 'small' | 'default' | 'large';
|
|
61
|
+
className?: string;
|
|
62
|
+
children?: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const ToggleButtonRoot = forwardRef<View, ToggleButtonProps>(
|
|
66
|
+
(
|
|
67
|
+
{
|
|
68
|
+
variant = 'default',
|
|
69
|
+
shape = 'circle',
|
|
70
|
+
size = 'default',
|
|
71
|
+
className,
|
|
72
|
+
children,
|
|
73
|
+
style,
|
|
74
|
+
isDisabled,
|
|
75
|
+
...props
|
|
76
|
+
},
|
|
77
|
+
ref,
|
|
78
|
+
) => {
|
|
79
|
+
const content = flattenChildren(children);
|
|
80
|
+
const iconOnly =
|
|
81
|
+
content.length === 1 &&
|
|
82
|
+
React.isValidElement(content[0]) &&
|
|
83
|
+
content[0].type === ToggleButtonIcon;
|
|
84
|
+
const computedClassName = cn(
|
|
85
|
+
toggleButtonRootVariants({ variant, shape, size, iconOnly }),
|
|
86
|
+
className,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const parent = useParentContext();
|
|
90
|
+
const ctx = useMemo(
|
|
91
|
+
() => ({ ...parent, [SCOPE]: { variant, shape, size } }),
|
|
92
|
+
[parent, variant, shape, size],
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<ParentContext.Provider value={ctx}>
|
|
97
|
+
<ToggleButtonRootPrimitive
|
|
98
|
+
ref={ref}
|
|
99
|
+
className={computedClassName}
|
|
100
|
+
style={style}
|
|
101
|
+
isDisabled={isDisabled}
|
|
102
|
+
{...props}
|
|
103
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'toggle-button' }))}
|
|
104
|
+
>
|
|
105
|
+
{children}
|
|
106
|
+
</ToggleButtonRootPrimitive>
|
|
107
|
+
</ParentContext.Provider>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
ToggleButtonRoot.displayName = 'ToggleButton';
|
|
113
|
+
|
|
114
|
+
// =============================================================================
|
|
115
|
+
// STYLED LABEL COMPONENT
|
|
116
|
+
// =============================================================================
|
|
117
|
+
|
|
118
|
+
export interface ToggleButtonLabelProps extends TextProps {
|
|
119
|
+
/** Render the consumer's child in place of the default `Text` host. */
|
|
120
|
+
asChild?: boolean;
|
|
121
|
+
className?: string;
|
|
122
|
+
children?: ReactNode;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const ToggleButtonLabel = forwardRef<Text, ToggleButtonLabelProps>(
|
|
126
|
+
({ asChild, className, children, style, ...props }, ref) => {
|
|
127
|
+
const { size } = useToggleButtonStyleContext();
|
|
128
|
+
const { isSelected, hover, active } = useToggleButtonContext();
|
|
129
|
+
const computedClassName = cn(toggleButtonLabelVariants({ size }), className);
|
|
130
|
+
const Comp = asChild ? Slot : Text;
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<Comp
|
|
134
|
+
ref={ref}
|
|
135
|
+
className={computedClassName}
|
|
136
|
+
style={style}
|
|
137
|
+
{...props}
|
|
138
|
+
{...mergeDataAttributes(
|
|
139
|
+
props,
|
|
140
|
+
dataAttributes({
|
|
141
|
+
slot: 'toggle-button-label',
|
|
142
|
+
selected: isSelected,
|
|
143
|
+
hover,
|
|
144
|
+
active,
|
|
145
|
+
}),
|
|
146
|
+
)}
|
|
147
|
+
>
|
|
148
|
+
{children}
|
|
149
|
+
</Comp>
|
|
150
|
+
);
|
|
151
|
+
},
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
ToggleButtonLabel.displayName = 'ToggleButton.Label';
|
|
155
|
+
|
|
156
|
+
// =============================================================================
|
|
157
|
+
// STYLED ICON COMPONENT
|
|
158
|
+
// =============================================================================
|
|
159
|
+
|
|
160
|
+
export interface ToggleButtonIconProps extends Omit<IconProps, 'children' | 'as'> {
|
|
161
|
+
/** Render a custom element instead of the default icon. */
|
|
162
|
+
asChild?: boolean;
|
|
163
|
+
/** Forge icon component to render. */
|
|
164
|
+
as?: IconProps['as'];
|
|
165
|
+
/** Leading or trailing placement relative to the label. */
|
|
166
|
+
position?: IconSlotPosition;
|
|
167
|
+
/**
|
|
168
|
+
* Render the filled icon variant. Defaults to the toggle's selected state.
|
|
169
|
+
* Icons without filled path data stay outlined.
|
|
170
|
+
*/
|
|
171
|
+
filled?: boolean;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const ToggleButtonIcon = ({
|
|
175
|
+
asChild,
|
|
176
|
+
className,
|
|
177
|
+
style,
|
|
178
|
+
as,
|
|
179
|
+
position,
|
|
180
|
+
filled,
|
|
181
|
+
...props
|
|
182
|
+
}: ToggleButtonIconProps) => {
|
|
183
|
+
const { size } = useToggleButtonStyleContext();
|
|
184
|
+
const { isSelected, hover, active } = useToggleButtonContext();
|
|
185
|
+
const computedClassName = cn(toggleButtonIconVariants({ size }), className);
|
|
186
|
+
const resolvedFilled = filled ?? isSelected;
|
|
187
|
+
const interactionAttributes = dataAttributes({
|
|
188
|
+
slot: 'toggle-button-icon',
|
|
189
|
+
selected: isSelected,
|
|
190
|
+
hover,
|
|
191
|
+
active,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (asChild) {
|
|
195
|
+
return (
|
|
196
|
+
<Slot
|
|
197
|
+
className={computedClassName}
|
|
198
|
+
style={style}
|
|
199
|
+
filled={resolvedFilled}
|
|
200
|
+
{...props}
|
|
201
|
+
{...mergeDataAttributes(props, interactionAttributes, positionToDataIcon(position))}
|
|
202
|
+
/>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!as) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<Icon
|
|
212
|
+
as={as}
|
|
213
|
+
className={computedClassName}
|
|
214
|
+
style={style}
|
|
215
|
+
filled={resolvedFilled}
|
|
216
|
+
{...props}
|
|
217
|
+
{...mergeDataAttributes(props, interactionAttributes, positionToDataIcon(position))}
|
|
218
|
+
/>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
ToggleButtonIcon.displayName = 'ToggleButton.Icon';
|
|
223
|
+
|
|
224
|
+
// =============================================================================
|
|
225
|
+
// STYLED GROUP COMPONENT
|
|
226
|
+
// =============================================================================
|
|
227
|
+
|
|
228
|
+
type ToggleButtonGroupSingleStyledProps = IToggleButtonGroupSingleProps &
|
|
229
|
+
ToggleButtonGroupVariantProps & {
|
|
230
|
+
className?: string;
|
|
231
|
+
children: ReactElement | ReactElement[];
|
|
232
|
+
/**
|
|
233
|
+
* Collapse gaps and adjoining corners into a single segmented control.
|
|
234
|
+
* @default true
|
|
235
|
+
*/
|
|
236
|
+
isAttached?: boolean;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
type ToggleButtonGroupMultipleStyledProps = IToggleButtonGroupMultipleProps &
|
|
240
|
+
ToggleButtonGroupVariantProps & {
|
|
241
|
+
className?: string;
|
|
242
|
+
children: ReactElement | ReactElement[];
|
|
243
|
+
/**
|
|
244
|
+
* Collapse gaps and adjoining corners into a single segmented control.
|
|
245
|
+
* @default true
|
|
246
|
+
*/
|
|
247
|
+
isAttached?: boolean;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
export type ToggleButtonGroupProps =
|
|
251
|
+
| ToggleButtonGroupSingleStyledProps
|
|
252
|
+
| ToggleButtonGroupMultipleStyledProps;
|
|
253
|
+
|
|
254
|
+
type AttachedOrientation = NonNullable<ToggleButtonGroupVariantProps['orientation']>;
|
|
255
|
+
|
|
256
|
+
const ATTACHED_RADIUS_STYLES: Record<
|
|
257
|
+
AttachedOrientation,
|
|
258
|
+
Record<ToggleButtonAttachedPosition, ViewStyle | undefined>
|
|
259
|
+
> = {
|
|
260
|
+
horizontal: {
|
|
261
|
+
only: undefined,
|
|
262
|
+
first: { borderTopRightRadius: 0, borderBottomRightRadius: 0 },
|
|
263
|
+
middle: { borderRadius: 0 },
|
|
264
|
+
last: { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 },
|
|
265
|
+
},
|
|
266
|
+
vertical: {
|
|
267
|
+
only: undefined,
|
|
268
|
+
first: { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 },
|
|
269
|
+
middle: { borderRadius: 0 },
|
|
270
|
+
last: { borderTopLeftRadius: 0, borderTopRightRadius: 0 },
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
function getAttachedPosition(index: number, count: number): ToggleButtonAttachedPosition {
|
|
275
|
+
if (count <= 1) {
|
|
276
|
+
return 'only';
|
|
277
|
+
}
|
|
278
|
+
if (index === 0) {
|
|
279
|
+
return 'first';
|
|
280
|
+
}
|
|
281
|
+
return index === count - 1 ? 'last' : 'middle';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const ToggleButtonGroup = forwardRef<View, ToggleButtonGroupProps>(
|
|
285
|
+
(
|
|
286
|
+
{
|
|
287
|
+
asChild,
|
|
288
|
+
className,
|
|
289
|
+
children,
|
|
290
|
+
style,
|
|
291
|
+
orientation = 'horizontal',
|
|
292
|
+
isAttached = true,
|
|
293
|
+
...props
|
|
294
|
+
},
|
|
295
|
+
ref,
|
|
296
|
+
) => {
|
|
297
|
+
const childrenArray = React.Children.toArray(flattenChildren(children));
|
|
298
|
+
|
|
299
|
+
const computedChildren = isAttached
|
|
300
|
+
? childrenArray.map((child, index) => {
|
|
301
|
+
if (!React.isValidElement<{ className?: string; style?: StyleProp<ViewStyle> }>(child)) {
|
|
302
|
+
return child;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const position = getAttachedPosition(index, childrenArray.length);
|
|
306
|
+
const radiusStyle = ATTACHED_RADIUS_STYLES[orientation][position];
|
|
307
|
+
|
|
308
|
+
return React.cloneElement(child, {
|
|
309
|
+
className: cn(
|
|
310
|
+
toggleButtonAttachedVariants({ orientation, position }),
|
|
311
|
+
child.props.className,
|
|
312
|
+
),
|
|
313
|
+
style: radiusStyle ? [radiusStyle, child.props.style] : child.props.style,
|
|
314
|
+
});
|
|
315
|
+
})
|
|
316
|
+
: childrenArray;
|
|
317
|
+
|
|
318
|
+
const groupClassName = cn(toggleButtonGroupVariants({ orientation, isAttached }), className);
|
|
319
|
+
|
|
320
|
+
return (
|
|
321
|
+
<ToggleButtonGroupPrimitive
|
|
322
|
+
ref={ref}
|
|
323
|
+
asChild={asChild}
|
|
324
|
+
className={groupClassName}
|
|
325
|
+
style={style}
|
|
326
|
+
orientation={orientation}
|
|
327
|
+
{...props}
|
|
328
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'toggle-button-group' }))}
|
|
329
|
+
>
|
|
330
|
+
{computedChildren}
|
|
331
|
+
</ToggleButtonGroupPrimitive>
|
|
332
|
+
);
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
ToggleButtonGroup.displayName = 'ToggleButtonGroup';
|
|
337
|
+
|
|
338
|
+
export const ToggleButton = Object.assign(ToggleButtonRoot, {
|
|
339
|
+
Label: ToggleButtonLabel,
|
|
340
|
+
Icon: ToggleButtonIcon,
|
|
341
|
+
}) as typeof ToggleButtonRoot & {
|
|
342
|
+
Label: typeof ToggleButtonLabel;
|
|
343
|
+
Icon: typeof ToggleButtonIcon;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export { ToggleButtonGroup };
|
|
@@ -0,0 +1,191 @@
|
|
|
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
|
+
// `data-toggle-state` is a single derived value (see the primitive's `getToggleState`), so these
|
|
6
|
+
// selectors never tie on specificity and match on native, where compound `data-[]` chains don't.
|
|
7
|
+
const selectedTint = [
|
|
8
|
+
'data-[toggle-state=selected]:bg-surface-action-tint',
|
|
9
|
+
'data-[toggle-state=selected-active]:bg-surface-action-tint-active',
|
|
10
|
+
Platform.select({
|
|
11
|
+
default: '',
|
|
12
|
+
web: 'data-[toggle-state=selected-hover]:bg-surface-action-tint-hover',
|
|
13
|
+
}),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const unselectedTint = [
|
|
17
|
+
'data-[toggle-state=active]:bg-surface-action-tint-active',
|
|
18
|
+
Platform.select({
|
|
19
|
+
default: '',
|
|
20
|
+
web: 'data-[toggle-state=hover]:bg-surface-action-tint-hover',
|
|
21
|
+
}),
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const toggleButtonRootVariants = cva(
|
|
25
|
+
[
|
|
26
|
+
'flex-row items-center justify-center self-start shrink-0 web:inline-flex',
|
|
27
|
+
'web:outline-none web:focus:outline-none web:focus-visible:outline-none',
|
|
28
|
+
TRANSITION_COLORS,
|
|
29
|
+
'data-[disabled=true]:opacity-[var(--opacity-disabled)]',
|
|
30
|
+
DISABLED_CURSOR,
|
|
31
|
+
'web:data-[focus-visible=true]:ring-2 web:data-[focus-visible=true]:ring-stroke-focus web:data-[focus-visible=true]:ring-offset-2',
|
|
32
|
+
],
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
variant: {
|
|
36
|
+
/** Muted filled surface. */
|
|
37
|
+
default: ['bg-surface-secondary', 'border-0'],
|
|
38
|
+
outline: [
|
|
39
|
+
'bg-transparent',
|
|
40
|
+
'border border-stroke-primary',
|
|
41
|
+
'web:border-default native:border-[length:var(--border-width-default)]',
|
|
42
|
+
],
|
|
43
|
+
ghost: ['bg-transparent', 'border-0'],
|
|
44
|
+
},
|
|
45
|
+
shape: {
|
|
46
|
+
circle: 'rounded-[var(--border-radius-round)]',
|
|
47
|
+
rounded: 'rounded-[var(--border-radius-default)]',
|
|
48
|
+
},
|
|
49
|
+
size: {
|
|
50
|
+
small: 'h-8 min-h-8 px-3 gap-1.5',
|
|
51
|
+
default: 'h-11 min-h-11 px-4 gap-2',
|
|
52
|
+
large: 'h-12 min-h-12 px-5 gap-2.5',
|
|
53
|
+
},
|
|
54
|
+
/** Square footprint when the only content is a single `ToggleButton.Icon`. */
|
|
55
|
+
iconOnly: {
|
|
56
|
+
true: 'px-0',
|
|
57
|
+
false: '',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
compoundVariants: [
|
|
61
|
+
{ iconOnly: true, size: 'small', className: 'w-8 min-w-8' },
|
|
62
|
+
{ iconOnly: true, size: 'default', className: 'w-11 min-w-11' },
|
|
63
|
+
{ iconOnly: true, size: 'large', className: 'w-12 min-w-12' },
|
|
64
|
+
{
|
|
65
|
+
variant: 'default',
|
|
66
|
+
className: [
|
|
67
|
+
...selectedTint,
|
|
68
|
+
'data-[toggle-state=active]:bg-surface-secondary-active',
|
|
69
|
+
Platform.select({
|
|
70
|
+
default: '',
|
|
71
|
+
web: 'data-[toggle-state=hover]:bg-surface-secondary-hover',
|
|
72
|
+
}),
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
variant: ['outline', 'ghost'],
|
|
77
|
+
className: [...selectedTint, ...unselectedTint],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
variant: 'outline',
|
|
81
|
+
className: 'data-[selected=true]:border-stroke-action',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
defaultVariants: {
|
|
85
|
+
variant: 'default',
|
|
86
|
+
shape: 'circle',
|
|
87
|
+
size: 'default',
|
|
88
|
+
iconOnly: false,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Classes for an item inside an attached group. Every item after the first overlaps its
|
|
95
|
+
* predecessor by one border width so adjoining borders collapse into a single line; the
|
|
96
|
+
* interacted or selected item is raised so its full border stays visible.
|
|
97
|
+
*/
|
|
98
|
+
export const toggleButtonAttachedVariants = cva(
|
|
99
|
+
['relative data-[hover=true]:z-[1] data-[active=true]:z-[1] data-[selected=true]:z-[1]'],
|
|
100
|
+
{
|
|
101
|
+
variants: {
|
|
102
|
+
orientation: {
|
|
103
|
+
horizontal: '',
|
|
104
|
+
vertical: 'self-stretch',
|
|
105
|
+
},
|
|
106
|
+
position: {
|
|
107
|
+
only: '',
|
|
108
|
+
first: '',
|
|
109
|
+
middle: '',
|
|
110
|
+
last: '',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
compoundVariants: [
|
|
114
|
+
{
|
|
115
|
+
orientation: 'horizontal',
|
|
116
|
+
position: ['middle', 'last'],
|
|
117
|
+
className: '-ms-[length:var(--border-width-default)]',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
orientation: 'vertical',
|
|
121
|
+
position: ['middle', 'last'],
|
|
122
|
+
className: '-mt-[length:var(--border-width-default)]',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
defaultVariants: {
|
|
126
|
+
orientation: 'horizontal',
|
|
127
|
+
position: 'only',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
export type ToggleButtonAttachedPosition = NonNullable<
|
|
133
|
+
VariantProps<typeof toggleButtonAttachedVariants>['position']
|
|
134
|
+
>;
|
|
135
|
+
|
|
136
|
+
export const toggleButtonGroupVariants = cva(['self-start'], {
|
|
137
|
+
variants: {
|
|
138
|
+
orientation: {
|
|
139
|
+
horizontal: 'flex-row',
|
|
140
|
+
vertical: 'flex-col items-stretch w-max max-w-full',
|
|
141
|
+
},
|
|
142
|
+
isAttached: {
|
|
143
|
+
true: 'gap-0',
|
|
144
|
+
false: 'gap-2',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
defaultVariants: {
|
|
148
|
+
orientation: 'horizontal',
|
|
149
|
+
isAttached: true,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Label and Icon emit their own `data-selected` / `data-active` / `data-hover` because
|
|
154
|
+
// native Uniwind cannot style a child from its parent's data attributes.
|
|
155
|
+
const contentColor = [
|
|
156
|
+
'text-content-primary',
|
|
157
|
+
'data-[selected=true]:text-content-action',
|
|
158
|
+
Platform.select({
|
|
159
|
+
default: 'data-[active=true]:text-content-action',
|
|
160
|
+
web: 'data-[hover=true]:text-content-action data-[active=true]:text-content-action',
|
|
161
|
+
}),
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
export const toggleButtonLabelVariants = cva(['shrink-0 font-medium', ...contentColor], {
|
|
165
|
+
variants: {
|
|
166
|
+
size: {
|
|
167
|
+
small: 'text-sm',
|
|
168
|
+
default: 'text-base',
|
|
169
|
+
large: 'text-lg',
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
defaultVariants: {
|
|
173
|
+
size: 'default',
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
export const toggleButtonIconVariants = cva(['shrink-0', ...contentColor], {
|
|
178
|
+
variants: {
|
|
179
|
+
size: {
|
|
180
|
+
small: 'size-4',
|
|
181
|
+
default: 'size-5',
|
|
182
|
+
large: 'size-6',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
defaultVariants: {
|
|
186
|
+
size: 'default',
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
export type ToggleButtonVariantProps = VariantProps<typeof toggleButtonRootVariants>;
|
|
191
|
+
export type ToggleButtonGroupVariantProps = VariantProps<typeof toggleButtonGroupVariants>;
|
package/src/components/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ export * from './Divider';
|
|
|
26
26
|
export * from './Drawer';
|
|
27
27
|
export * from './Field';
|
|
28
28
|
export * from './Form';
|
|
29
|
+
export * from './FullScreenDialog';
|
|
29
30
|
export * from './Image';
|
|
30
31
|
export * from './InsuranceDisclosure';
|
|
31
32
|
export * from './Input';
|
|
@@ -50,6 +51,7 @@ export * from './Tabs';
|
|
|
50
51
|
export * from './Table';
|
|
51
52
|
export * from './Textarea';
|
|
52
53
|
export * from './Tile';
|
|
54
|
+
export * from './ToggleButton';
|
|
53
55
|
export * from './Toast';
|
|
54
56
|
export * from './Tooltip';
|
|
55
57
|
export { HStack, VStack } from './Stack';
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
|
+
import { MODAL_OVERLAY_Z_INDEX } from '@cdx-ui/primitives';
|
|
2
3
|
import { cva } from '@cdx-ui/utils';
|
|
3
4
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Modal layer, so on web a popover opened from a `Dialog` or `FullScreenDialog` paints above it:
|
|
7
|
+
* equal z-index, and the popover mounts later in `document.body`.
|
|
8
|
+
*/
|
|
9
|
+
export const PICKER_POPOVER_Z_INDEX = MODAL_OVERLAY_Z_INDEX;
|
|
6
10
|
|
|
7
11
|
export const pickerPopoverContentVariants = cva([
|
|
8
12
|
'bg-surface-primary',
|