@cdx-ui/components 0.0.1-beta.142 → 0.0.1-beta.144
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/lib/commonjs/components/Checkbox/index.js +10 -4
- package/lib/commonjs/components/Checkbox/index.js.map +1 -1
- package/lib/commonjs/components/Checkbox/styles.js +8 -4
- package/lib/commonjs/components/Checkbox/styles.js.map +1 -1
- package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js +91 -0
- package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js.map +1 -0
- package/lib/commonjs/components/ProgressCircle/index.js +84 -0
- package/lib/commonjs/components/ProgressCircle/index.js.map +1 -0
- package/lib/commonjs/components/ProgressCircle/styles.js +50 -0
- package/lib/commonjs/components/ProgressCircle/styles.js.map +1 -0
- package/lib/commonjs/components/ProgressCircle/useProgressCircleColors.js +35 -0
- package/lib/commonjs/components/ProgressCircle/useProgressCircleColors.js.map +1 -0
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/module/components/Checkbox/index.js +10 -4
- package/lib/module/components/Checkbox/index.js.map +1 -1
- package/lib/module/components/Checkbox/styles.js +8 -4
- package/lib/module/components/Checkbox/styles.js.map +1 -1
- package/lib/module/components/ProgressCircle/ProgressCircleRing.js +86 -0
- package/lib/module/components/ProgressCircle/ProgressCircleRing.js.map +1 -0
- package/lib/module/components/ProgressCircle/index.js +80 -0
- package/lib/module/components/ProgressCircle/index.js.map +1 -0
- package/lib/module/components/ProgressCircle/styles.js +46 -0
- package/lib/module/components/ProgressCircle/styles.js.map +1 -0
- package/lib/module/components/ProgressCircle/useProgressCircleColors.js +32 -0
- package/lib/module/components/ProgressCircle/useProgressCircleColors.js.map +1 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/typescript/components/Checkbox/index.d.ts.map +1 -1
- package/lib/typescript/components/Checkbox/styles.d.ts.map +1 -1
- package/lib/typescript/components/ProgressCircle/ProgressCircleRing.d.ts +7 -0
- package/lib/typescript/components/ProgressCircle/ProgressCircleRing.d.ts.map +1 -0
- package/lib/typescript/components/ProgressCircle/index.d.ts +15 -0
- package/lib/typescript/components/ProgressCircle/index.d.ts.map +1 -0
- package/lib/typescript/components/ProgressCircle/styles.d.ts +23 -0
- package/lib/typescript/components/ProgressCircle/styles.d.ts.map +1 -0
- package/lib/typescript/components/ProgressCircle/useProgressCircleColors.d.ts +6 -0
- package/lib/typescript/components/ProgressCircle/useProgressCircleColors.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/package.json +10 -5
- package/src/components/Checkbox/index.tsx +15 -6
- package/src/components/Checkbox/styles.ts +25 -2
- package/src/components/ProgressCircle/ProgressCircleRing.tsx +105 -0
- package/src/components/ProgressCircle/index.tsx +94 -0
- package/src/components/ProgressCircle/styles.ts +47 -0
- package/src/components/ProgressCircle/useProgressCircleColors.ts +33 -0
- package/src/components/index.ts +1 -0
|
@@ -8,6 +8,7 @@ export const checkboxRootVariants = cva([
|
|
|
8
8
|
'flex-row items-center gap-2.5',
|
|
9
9
|
DISABLED_OPACITY,
|
|
10
10
|
DISABLED_CURSOR,
|
|
11
|
+
'data-[readonly=true]:cursor-default',
|
|
11
12
|
// Suppress stray outline on the Pressable/label wrapper; focus ring is drawn on Checkbox.Indicator (Radio pattern).
|
|
12
13
|
'web:outline-none web:focus:outline-none web:focus-visible:outline-none',
|
|
13
14
|
]);
|
|
@@ -33,6 +34,12 @@ export const checkboxIndicatorVariants = cva([
|
|
|
33
34
|
'data-[invalid=true]:border-stroke-danger',
|
|
34
35
|
Platform.select({
|
|
35
36
|
web: [
|
|
37
|
+
// Read-only — compound selectors evaluate correctly on web.
|
|
38
|
+
'data-[readonly=true]:bg-surface-secondary',
|
|
39
|
+
'data-[readonly=true]:data-[checked=true]:border-stroke-action',
|
|
40
|
+
'data-[readonly=true]:data-[indeterminate=true]:border-stroke-action',
|
|
41
|
+
'data-[readonly=true]:data-[checked=true]:bg-surface-secondary',
|
|
42
|
+
'data-[readonly=true]:data-[indeterminate=true]:bg-surface-secondary',
|
|
36
43
|
// Invalid bg — compound selectors evaluate correctly on web.
|
|
37
44
|
'data-[invalid=true]:data-[checked=true]:bg-surface-danger-strong',
|
|
38
45
|
'data-[invalid=true]:data-[indeterminate=true]:bg-surface-danger-strong',
|
|
@@ -63,13 +70,24 @@ export const checkboxIndicatorVariants = cva([
|
|
|
63
70
|
'web:active:data-[hover=true]:data-[checked=true]:data-[invalid=true]:border-surface-danger-strong-active',
|
|
64
71
|
'web:active:data-[hover=true]:data-[indeterminate=true]:data-[invalid=true]:bg-surface-danger-strong-active',
|
|
65
72
|
'web:active:data-[hover=true]:data-[indeterminate=true]:data-[invalid=true]:border-surface-danger-strong-active',
|
|
66
|
-
// Focus ring
|
|
73
|
+
// Focus ring — applies to read-only as well (focusable + aria-readonly).
|
|
67
74
|
'web:data-[focus-visible=true]:outline-none',
|
|
68
75
|
'web:data-[focus-visible=true]:ring-2 web:data-[focus-visible=true]:ring-stroke-focus web:data-[focus-visible=true]:ring-offset-2',
|
|
69
76
|
].join(' '),
|
|
70
77
|
default: [
|
|
71
78
|
// Native: Uniwind only evaluates the last data-[] condition in a compound chain.
|
|
72
79
|
// Use single-condition data-[field-state=...] selectors (emitted by CheckboxIndicator).
|
|
80
|
+
// Read-only — derived field-state encodes check × readonly (no active/hover on readonly).
|
|
81
|
+
'data-[field-state=readonly-unchecked]:bg-surface-secondary',
|
|
82
|
+
'data-[field-state=readonly-checked]:bg-surface-secondary',
|
|
83
|
+
'data-[field-state=readonly-checked]:border-stroke-action',
|
|
84
|
+
'data-[field-state=readonly-indeterminate]:bg-surface-secondary',
|
|
85
|
+
'data-[field-state=readonly-indeterminate]:border-stroke-action',
|
|
86
|
+
'data-[field-state=readonly-unchecked-invalid]:bg-surface-secondary',
|
|
87
|
+
'data-[field-state=readonly-checked-invalid]:bg-surface-secondary',
|
|
88
|
+
'data-[field-state=readonly-checked-invalid]:border-stroke-action',
|
|
89
|
+
'data-[field-state=readonly-indeterminate-invalid]:bg-surface-secondary',
|
|
90
|
+
'data-[field-state=readonly-indeterminate-invalid]:border-stroke-action',
|
|
73
91
|
// checked/indeterminate + invalid → danger bg
|
|
74
92
|
'data-[field-state=checked-invalid]:bg-surface-danger-strong',
|
|
75
93
|
'data-[field-state=indeterminate-invalid]:bg-surface-danger-strong',
|
|
@@ -90,11 +108,16 @@ export const checkboxIndicatorVariants = cva([
|
|
|
90
108
|
}),
|
|
91
109
|
]);
|
|
92
110
|
|
|
93
|
-
export const checkboxIconVariants = cva([
|
|
111
|
+
export const checkboxIconVariants = cva([
|
|
112
|
+
'text-white',
|
|
113
|
+
'data-[readonly=true]:text-content-action',
|
|
114
|
+
'h-5 w-5',
|
|
115
|
+
]);
|
|
94
116
|
|
|
95
117
|
export const checkboxLabelVariants = cva([
|
|
96
118
|
'text-content-primary text-base',
|
|
97
119
|
'data-[disabled=true]:text-content-tertiary',
|
|
120
|
+
'data-[readonly=true]:cursor-default',
|
|
98
121
|
]);
|
|
99
122
|
|
|
100
123
|
export const checkboxGroupVariants = cva([], {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
Easing,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
useSharedValue,
|
|
7
|
+
withRepeat,
|
|
8
|
+
withTiming,
|
|
9
|
+
} from 'react-native-reanimated';
|
|
10
|
+
import { Circle, Svg } from 'react-native-svg';
|
|
11
|
+
import { useProgressContext } from '@cdx-ui/primitives';
|
|
12
|
+
import { PROGRESS_CIRCLE_DIMENSIONS, type ProgressCircleSize } from './styles';
|
|
13
|
+
import { useProgressCircleColors } from './useProgressCircleColors';
|
|
14
|
+
|
|
15
|
+
const INDETERMINATE_ARC_RATIO = 0.25;
|
|
16
|
+
const ROTATION_DURATION_MS = 1000;
|
|
17
|
+
|
|
18
|
+
export interface ProgressCircleRingProps {
|
|
19
|
+
readonly size?: ProgressCircleSize;
|
|
20
|
+
readonly color?: 'default' | 'inherit';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function ProgressCircleRing({ size = 'large', color = 'default' }: ProgressCircleRingProps) {
|
|
24
|
+
const { percent, state } = useProgressContext();
|
|
25
|
+
const ringColors = useProgressCircleColors(color);
|
|
26
|
+
const rotation = useSharedValue(0);
|
|
27
|
+
const { size: dimension, strokeWidth } = PROGRESS_CIRCLE_DIMENSIONS[size];
|
|
28
|
+
const radius = (dimension - strokeWidth) / 2;
|
|
29
|
+
const center = dimension / 2;
|
|
30
|
+
const circumference = 2 * Math.PI * radius;
|
|
31
|
+
const isIndeterminate = state === 'indeterminate';
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!isIndeterminate) {
|
|
35
|
+
rotation.set(0);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
rotation.set(
|
|
40
|
+
withRepeat(
|
|
41
|
+
withTiming(360, {
|
|
42
|
+
duration: ROTATION_DURATION_MS,
|
|
43
|
+
easing: Easing.linear,
|
|
44
|
+
}),
|
|
45
|
+
-1,
|
|
46
|
+
false,
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
}, [isIndeterminate, rotation]);
|
|
50
|
+
|
|
51
|
+
const animatedStyle = useAnimatedStyle(
|
|
52
|
+
() => ({
|
|
53
|
+
transform: [{ rotate: `${String(rotation.get())}deg` }],
|
|
54
|
+
}),
|
|
55
|
+
[rotation],
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const progressLength = isIndeterminate
|
|
59
|
+
? circumference * INDETERMINATE_ARC_RATIO
|
|
60
|
+
: (circumference * percent) / 100;
|
|
61
|
+
const gapLength = circumference - progressLength;
|
|
62
|
+
|
|
63
|
+
const ring = (
|
|
64
|
+
<Svg
|
|
65
|
+
width={dimension}
|
|
66
|
+
height={dimension}
|
|
67
|
+
viewBox={`0 0 ${String(dimension)} ${String(dimension)}`}
|
|
68
|
+
>
|
|
69
|
+
<Circle
|
|
70
|
+
cx={center}
|
|
71
|
+
cy={center}
|
|
72
|
+
r={radius}
|
|
73
|
+
stroke={ringColors.track}
|
|
74
|
+
strokeWidth={strokeWidth}
|
|
75
|
+
fill="none"
|
|
76
|
+
opacity={ringColors.trackOpacity}
|
|
77
|
+
/>
|
|
78
|
+
{progressLength > 0 ? (
|
|
79
|
+
<Circle
|
|
80
|
+
cx={center}
|
|
81
|
+
cy={center}
|
|
82
|
+
r={radius}
|
|
83
|
+
stroke={ringColors.indicator}
|
|
84
|
+
strokeWidth={strokeWidth}
|
|
85
|
+
fill="none"
|
|
86
|
+
strokeDasharray={`${String(progressLength)} ${String(gapLength)}`}
|
|
87
|
+
strokeLinecap="round"
|
|
88
|
+
rotation={-90}
|
|
89
|
+
origin={`${String(center)}, ${String(center)}`}
|
|
90
|
+
/>
|
|
91
|
+
) : null}
|
|
92
|
+
</Svg>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (isIndeterminate) {
|
|
96
|
+
const inheritClass = color === 'inherit' ? 'text-inherit' : undefined;
|
|
97
|
+
return (
|
|
98
|
+
<Animated.View style={animatedStyle} className={inheritClass}>
|
|
99
|
+
<View className={inheritClass}>{ring}</View>
|
|
100
|
+
</Animated.View>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return ring;
|
|
105
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createContext, forwardRef, useContext, useMemo } from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
ProgressBarRoot,
|
|
5
|
+
dataAttributes,
|
|
6
|
+
mergeDataAttributes,
|
|
7
|
+
type IProgressProps,
|
|
8
|
+
} from '@cdx-ui/primitives';
|
|
9
|
+
import { cn } from '@cdx-ui/utils';
|
|
10
|
+
import { ProgressCircleRing } from './ProgressCircleRing';
|
|
11
|
+
import {
|
|
12
|
+
progressCircleIndicatorVariants,
|
|
13
|
+
progressCircleRootVariants,
|
|
14
|
+
type ProgressCircleIndicatorVariantProps,
|
|
15
|
+
type ProgressCircleRootVariantProps,
|
|
16
|
+
type ProgressCircleSize,
|
|
17
|
+
} from './styles';
|
|
18
|
+
|
|
19
|
+
type ProgressCircleColor = NonNullable<ProgressCircleRootVariantProps['color']>;
|
|
20
|
+
|
|
21
|
+
interface ProgressCircleStyleContextValue {
|
|
22
|
+
readonly size: ProgressCircleSize;
|
|
23
|
+
readonly color: ProgressCircleColor;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const ProgressCircleStyleContext = createContext<ProgressCircleStyleContextValue>({
|
|
27
|
+
size: 'large',
|
|
28
|
+
color: 'default',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export interface ProgressCircleProps extends IProgressProps, ProgressCircleRootVariantProps {}
|
|
32
|
+
|
|
33
|
+
export interface ProgressCircleIndicatorProps
|
|
34
|
+
extends ViewProps, ProgressCircleIndicatorVariantProps {}
|
|
35
|
+
|
|
36
|
+
const ProgressCircleRootComponent = forwardRef<View, ProgressCircleProps>(
|
|
37
|
+
({ className, style, size = 'large', color = 'default', children, ...props }, ref) => {
|
|
38
|
+
const rootClass = cn(progressCircleRootVariants({ size, color }), className);
|
|
39
|
+
const styleContext = useMemo(
|
|
40
|
+
() => ({
|
|
41
|
+
size: size ?? 'large',
|
|
42
|
+
color: color ?? 'default',
|
|
43
|
+
}),
|
|
44
|
+
[size, color],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<ProgressCircleStyleContext.Provider value={styleContext}>
|
|
49
|
+
<ProgressBarRoot
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={rootClass}
|
|
52
|
+
style={style}
|
|
53
|
+
{...props}
|
|
54
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'progress-circle' }))}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</ProgressBarRoot>
|
|
58
|
+
</ProgressCircleStyleContext.Provider>
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
ProgressCircleRootComponent.displayName = 'ProgressCircle';
|
|
64
|
+
|
|
65
|
+
const ProgressCircleIndicatorComponent = forwardRef<View, ProgressCircleIndicatorProps>(
|
|
66
|
+
({ className, style, size: sizeProp, color: colorProp, ...props }, ref) => {
|
|
67
|
+
const { size: contextSize, color: contextColor } = useContext(ProgressCircleStyleContext);
|
|
68
|
+
const size = sizeProp ?? contextSize;
|
|
69
|
+
const color = colorProp ?? contextColor;
|
|
70
|
+
const indicatorClass = cn(progressCircleIndicatorVariants({ size, color }), className);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<View
|
|
74
|
+
ref={ref}
|
|
75
|
+
className={indicatorClass}
|
|
76
|
+
style={style}
|
|
77
|
+
{...props}
|
|
78
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'progress-circle-indicator' }))}
|
|
79
|
+
>
|
|
80
|
+
<ProgressCircleRing size={size} color={color} />
|
|
81
|
+
</View>
|
|
82
|
+
);
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
ProgressCircleIndicatorComponent.displayName = 'ProgressCircle.Indicator';
|
|
87
|
+
|
|
88
|
+
type ProgressCircleCompoundComponent = typeof ProgressCircleRootComponent & {
|
|
89
|
+
Indicator: typeof ProgressCircleIndicatorComponent;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const ProgressCircle = Object.assign(ProgressCircleRootComponent, {
|
|
93
|
+
Indicator: ProgressCircleIndicatorComponent,
|
|
94
|
+
}) as ProgressCircleCompoundComponent;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cva, type VariantProps } from '@cdx-ui/utils';
|
|
2
|
+
|
|
3
|
+
export const progressCircleRootVariants = cva(['items-center justify-center'], {
|
|
4
|
+
variants: {
|
|
5
|
+
size: {
|
|
6
|
+
large: 'size-[32px]',
|
|
7
|
+
small: 'size-[24px]',
|
|
8
|
+
},
|
|
9
|
+
color: {
|
|
10
|
+
default: '',
|
|
11
|
+
inherit: 'text-inherit',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
size: 'large',
|
|
16
|
+
color: 'default',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const progressCircleIndicatorVariants = cva(['size-full items-center justify-center'], {
|
|
21
|
+
variants: {
|
|
22
|
+
size: {
|
|
23
|
+
large: '',
|
|
24
|
+
small: '',
|
|
25
|
+
},
|
|
26
|
+
color: {
|
|
27
|
+
default: '',
|
|
28
|
+
inherit: 'text-inherit',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
size: 'large',
|
|
33
|
+
color: 'default',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export type ProgressCircleRootVariantProps = VariantProps<typeof progressCircleRootVariants>;
|
|
38
|
+
export type ProgressCircleIndicatorVariantProps = VariantProps<
|
|
39
|
+
typeof progressCircleIndicatorVariants
|
|
40
|
+
>;
|
|
41
|
+
|
|
42
|
+
export const PROGRESS_CIRCLE_DIMENSIONS = {
|
|
43
|
+
large: { size: 32, strokeWidth: 3 },
|
|
44
|
+
small: { size: 24, strokeWidth: 2 },
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
export type ProgressCircleSize = keyof typeof PROGRESS_CIRCLE_DIMENSIONS;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useCSSVariable } from 'uniwind';
|
|
2
|
+
|
|
3
|
+
/** Light-theme fallbacks when Uniwind CSS context is unavailable (e.g. Jest). */
|
|
4
|
+
const FALLBACKS = {
|
|
5
|
+
track: '#e8eefc',
|
|
6
|
+
indicator: '#346099',
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
function toColor(value: string | number | undefined, fallback: string): string {
|
|
10
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
return fallback;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useProgressCircleColors(color: 'default' | 'inherit') {
|
|
17
|
+
const trackToken = useCSSVariable('--color-surface-action-subtle');
|
|
18
|
+
const indicatorToken = useCSSVariable('--color-surface-action-strong');
|
|
19
|
+
|
|
20
|
+
if (color === 'inherit') {
|
|
21
|
+
return {
|
|
22
|
+
track: 'currentColor',
|
|
23
|
+
indicator: 'currentColor',
|
|
24
|
+
trackOpacity: 0.24,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
track: toColor(trackToken, FALLBACKS.track),
|
|
30
|
+
indicator: toColor(indicatorToken, FALLBACKS.indicator),
|
|
31
|
+
trackOpacity: 1,
|
|
32
|
+
};
|
|
33
|
+
}
|
package/src/components/index.ts
CHANGED