@seed-design/lynx-react 0.1.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/lib/_virtual/_rolldown/runtime.js +13 -0
- package/lib/components/ActionButton/ActionButton.d.ts +44 -0
- package/lib/components/ActionButton/ActionButton.d.ts.map +1 -0
- package/lib/components/ActionButton/ActionButton.jsx +158 -0
- package/lib/components/ActionButton/index.d.ts +2 -0
- package/lib/components/ActionButton/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts +87 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.jsx +150 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.d.ts +2 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.js +18 -0
- package/lib/components/BottomSheet/index.d.ts +3 -0
- package/lib/components/BottomSheet/index.d.ts.map +1 -0
- package/lib/components/Box/Box.d.ts +20 -0
- package/lib/components/Box/Box.d.ts.map +1 -0
- package/lib/components/Box/Box.jsx +14 -0
- package/lib/components/Box/index.d.ts +2 -0
- package/lib/components/Box/index.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.d.ts +35 -0
- package/lib/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.jsx +130 -0
- package/lib/components/Checkbox/Checkbox.namespace.d.ts +2 -0
- package/lib/components/Checkbox/Checkbox.namespace.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.namespace.js +12 -0
- package/lib/components/Checkbox/index.d.ts +3 -0
- package/lib/components/Checkbox/index.d.ts.map +1 -0
- package/lib/components/Icon/Icon.d.ts +37 -0
- package/lib/components/Icon/Icon.d.ts.map +1 -0
- package/lib/components/Icon/Icon.jsx +143 -0
- package/lib/components/Icon/index.d.ts +2 -0
- package/lib/components/Icon/index.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts +25 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.jsx +281 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.d.ts +2 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.js +9 -0
- package/lib/components/ProgressCircle/index.d.ts +3 -0
- package/lib/components/ProgressCircle/index.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.d.ts +34 -0
- package/lib/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.jsx +160 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.d.ts +2 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.js +12 -0
- package/lib/components/RadioGroup/index.d.ts +3 -0
- package/lib/components/RadioGroup/index.d.ts.map +1 -0
- package/lib/components/Stack/Stack.d.ts +33 -0
- package/lib/components/Stack/Stack.d.ts.map +1 -0
- package/lib/components/Stack/Stack.jsx +39 -0
- package/lib/components/Stack/index.d.ts +2 -0
- package/lib/components/Stack/index.d.ts.map +1 -0
- package/lib/components/Switch/Switch.d.ts +21 -0
- package/lib/components/Switch/Switch.d.ts.map +1 -0
- package/lib/components/Switch/Switch.jsx +101 -0
- package/lib/components/Switch/Switch.namespace.d.ts +2 -0
- package/lib/components/Switch/Switch.namespace.d.ts.map +1 -0
- package/lib/components/Switch/Switch.namespace.js +11 -0
- package/lib/components/Switch/index.d.ts +3 -0
- package/lib/components/Switch/index.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.d.ts +34 -0
- package/lib/components/TagGroup/TagGroup.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.jsx +57 -0
- package/lib/components/TagGroup/TagGroup.namespace.d.ts +2 -0
- package/lib/components/TagGroup/TagGroup.namespace.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.namespace.js +10 -0
- package/lib/components/TagGroup/index.d.ts +3 -0
- package/lib/components/TagGroup/index.d.ts.map +1 -0
- package/lib/components/Text/Text.d.ts +7 -0
- package/lib/components/Text/Text.d.ts.map +1 -0
- package/lib/components/Text/Text.jsx +28 -0
- package/lib/components/Text/index.d.ts +2 -0
- package/lib/components/Text/index.d.ts.map +1 -0
- package/lib/components/index.d.ts +12 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/hooks/index.d.ts +5 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/useControllableState.d.ts +15 -0
- package/lib/hooks/useControllableState.d.ts.map +1 -0
- package/lib/hooks/useControllableState.js +27 -0
- package/lib/hooks/useIconColor.d.ts +19 -0
- package/lib/hooks/useIconColor.d.ts.map +1 -0
- package/lib/hooks/useIconColor.js +38 -0
- package/lib/hooks/usePressTap.d.ts +27 -0
- package/lib/hooks/usePressTap.d.ts.map +1 -0
- package/lib/hooks/usePressTap.js +35 -0
- package/lib/hooks/useSafeArea.d.ts +19 -0
- package/lib/hooks/useSafeArea.d.ts.map +1 -0
- package/lib/hooks/useSafeArea.js +33 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +26 -0
- package/lib/types.d.ts +33 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils/children.d.ts +3 -0
- package/lib/utils/children.d.ts.map +1 -0
- package/lib/utils/children.js +8 -0
- package/lib/utils/create-slot-recipe-context.d.ts +27 -0
- package/lib/utils/create-slot-recipe-context.d.ts.map +1 -0
- package/lib/utils/create-slot-recipe-context.jsx +94 -0
- package/lib/utils/get-seed-class-name.d.ts +22 -0
- package/lib/utils/get-seed-class-name.d.ts.map +1 -0
- package/lib/utils/get-seed-class-name.js +28 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/resolve-recipe-token.d.ts +38 -0
- package/lib/utils/resolve-recipe-token.d.ts.map +1 -0
- package/lib/utils/resolve-recipe-token.js +49 -0
- package/lib/utils/split-multiple-variants-props.d.ts +29 -0
- package/lib/utils/split-multiple-variants-props.d.ts.map +1 -0
- package/lib/utils/split-multiple-variants-props.js +34 -0
- package/lib/utils/styled.d.ts +83 -0
- package/lib/utils/styled.d.ts.map +1 -0
- package/lib/utils/styled.js +144 -0
- package/package.json +54 -0
- package/src/components/ActionButton/ActionButton.test.tsx +137 -0
- package/src/components/ActionButton/ActionButton.tsx +340 -0
- package/src/components/ActionButton/index.ts +1 -0
- package/src/components/BottomSheet/BottomSheet.namespace.ts +24 -0
- package/src/components/BottomSheet/BottomSheet.test.tsx +153 -0
- package/src/components/BottomSheet/BottomSheet.tsx +397 -0
- package/src/components/BottomSheet/index.ts +27 -0
- package/src/components/Box/Box.test.tsx +85 -0
- package/src/components/Box/Box.tsx +39 -0
- package/src/components/Box/index.ts +1 -0
- package/src/components/Checkbox/Checkbox.namespace.ts +12 -0
- package/src/components/Checkbox/Checkbox.tsx +282 -0
- package/src/components/Checkbox/index.ts +14 -0
- package/src/components/Icon/Icon.tsx +265 -0
- package/src/components/Icon/index.ts +8 -0
- package/src/components/ProgressCircle/ProgressCircle.namespace.ts +5 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +424 -0
- package/src/components/ProgressCircle/index.ts +9 -0
- package/src/components/RadioGroup/RadioGroup.namespace.ts +12 -0
- package/src/components/RadioGroup/RadioGroup.tsx +320 -0
- package/src/components/RadioGroup/index.ts +14 -0
- package/src/components/Stack/Stack.tsx +97 -0
- package/src/components/Stack/index.ts +1 -0
- package/src/components/Switch/Switch.namespace.ts +10 -0
- package/src/components/Switch/Switch.tsx +200 -0
- package/src/components/Switch/index.ts +12 -0
- package/src/components/TagGroup/TagGroup.namespace.ts +8 -0
- package/src/components/TagGroup/TagGroup.tsx +127 -0
- package/src/components/TagGroup/index.ts +10 -0
- package/src/components/Text/Text.tsx +64 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/index.ts +11 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useControllableState.test.ts +120 -0
- package/src/hooks/useControllableState.ts +38 -0
- package/src/hooks/useIconColor.test.ts +13 -0
- package/src/hooks/useIconColor.ts +67 -0
- package/src/hooks/usePressTap.test.ts +129 -0
- package/src/hooks/usePressTap.ts +58 -0
- package/src/hooks/useSafeArea.test.ts +83 -0
- package/src/hooks/useSafeArea.ts +56 -0
- package/src/index.ts +4 -0
- package/src/types.ts +45 -0
- package/src/utils/children.ts +13 -0
- package/src/utils/create-slot-recipe-context.test.tsx +96 -0
- package/src/utils/create-slot-recipe-context.tsx +187 -0
- package/src/utils/get-seed-class-name.ts +47 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/resolve-recipe-token.ts +47 -0
- package/src/utils/split-multiple-variants-props.test.ts +61 -0
- package/src/utils/split-multiple-variants-props.ts +59 -0
- package/src/utils/styled.ts +442 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { usePressTap } from "../../hooks/usePressTap.js";
|
|
2
|
+
import { InternalIcon } from "../Icon/Icon.jsx";
|
|
3
|
+
import { useControllableState } from "../../hooks/useControllableState.js";
|
|
4
|
+
import { splitMultipleVariantsProps } from "../../utils/split-multiple-variants-props.js";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import * as React from "@lynx-js/react";
|
|
7
|
+
import { isValidElement } from "@lynx-js/react";
|
|
8
|
+
import { checkbox } from "@seed-design/lynx-css/recipes/checkbox";
|
|
9
|
+
import { checkmark } from "@seed-design/lynx-css/recipes/checkmark";
|
|
10
|
+
import { checkboxGroup } from "@seed-design/lynx-css/recipes/checkbox-group";
|
|
11
|
+
//#region src/components/Checkbox/Checkbox.tsx
|
|
12
|
+
var CheckboxContext = React.createContext(null);
|
|
13
|
+
function useCheckboxContext(consumer) {
|
|
14
|
+
const ctx = React.useContext(CheckboxContext);
|
|
15
|
+
if (!ctx) throw new Error(`<${consumer}/> must be rendered inside <CheckboxRoot/>.`);
|
|
16
|
+
return ctx;
|
|
17
|
+
}
|
|
18
|
+
var CheckmarkControlContext = React.createContext(null);
|
|
19
|
+
function useCheckmarkControlContext(consumer) {
|
|
20
|
+
const ctx = React.useContext(CheckmarkControlContext);
|
|
21
|
+
if (!ctx) throw new Error(`<${consumer}/> must be rendered inside <CheckboxControl/>.`);
|
|
22
|
+
return ctx;
|
|
23
|
+
}
|
|
24
|
+
var CheckboxRoot = React.forwardRef((props, ref) => {
|
|
25
|
+
const { children, className, checked: checkedProp, defaultChecked = false, indeterminate = false, disabled = false, onCheckedChange, ...restProps } = props;
|
|
26
|
+
const [{ checkbox: checkboxVariantProps, checkmark: checkmarkVariantProps }, nativeProps] = splitMultipleVariantsProps(restProps, {
|
|
27
|
+
checkbox,
|
|
28
|
+
checkmark
|
|
29
|
+
});
|
|
30
|
+
const [checked, setChecked] = useControllableState({
|
|
31
|
+
value: checkedProp,
|
|
32
|
+
defaultValue: defaultChecked,
|
|
33
|
+
onChange: onCheckedChange
|
|
34
|
+
});
|
|
35
|
+
const toggle = React.useCallback(() => setChecked(!checked), [checked, setChecked]);
|
|
36
|
+
const { pressed, ...pressHandlers } = usePressTap({
|
|
37
|
+
disabled,
|
|
38
|
+
onTap: toggle
|
|
39
|
+
});
|
|
40
|
+
const rootClassName = checkbox({
|
|
41
|
+
...checkboxVariantProps,
|
|
42
|
+
disabled
|
|
43
|
+
}).root;
|
|
44
|
+
const contextValue = React.useMemo(() => ({
|
|
45
|
+
checked,
|
|
46
|
+
indeterminate,
|
|
47
|
+
disabled,
|
|
48
|
+
pressed,
|
|
49
|
+
checkboxVariantProps,
|
|
50
|
+
checkmarkVariantProps,
|
|
51
|
+
toggle
|
|
52
|
+
}), [
|
|
53
|
+
checked,
|
|
54
|
+
indeterminate,
|
|
55
|
+
disabled,
|
|
56
|
+
pressed,
|
|
57
|
+
checkboxVariantProps,
|
|
58
|
+
checkmarkVariantProps,
|
|
59
|
+
toggle
|
|
60
|
+
]);
|
|
61
|
+
return <CheckboxContext.Provider value={contextValue}>
|
|
62
|
+
<view {...ref ? { ref } : {}} className={clsx(rootClassName, className)} {...pressHandlers} {...nativeProps}>
|
|
63
|
+
{children}
|
|
64
|
+
</view>
|
|
65
|
+
</CheckboxContext.Provider>;
|
|
66
|
+
});
|
|
67
|
+
CheckboxRoot.displayName = "CheckboxRoot";
|
|
68
|
+
var CheckboxControl = React.forwardRef((props, ref) => {
|
|
69
|
+
const [variantProps, restProps] = checkmark.splitVariantProps(props);
|
|
70
|
+
const { children, className, ...nativeProps } = restProps;
|
|
71
|
+
const context = useCheckboxContext("CheckboxControl");
|
|
72
|
+
const checkmarkVariantProps = {
|
|
73
|
+
...context.checkmarkVariantProps,
|
|
74
|
+
...variantProps,
|
|
75
|
+
checked: context.checked,
|
|
76
|
+
disabled: context.disabled,
|
|
77
|
+
indeterminate: context.indeterminate,
|
|
78
|
+
pressed: context.pressed
|
|
79
|
+
};
|
|
80
|
+
const classes = checkmark(checkmarkVariantProps);
|
|
81
|
+
return <CheckmarkControlContext.Provider value={{
|
|
82
|
+
iconClassName: classes.icon,
|
|
83
|
+
checkmarkVariantProps
|
|
84
|
+
}}>
|
|
85
|
+
<view {...ref ? { ref } : {}} className={clsx(classes.root, className)} {...nativeProps}>
|
|
86
|
+
{children}
|
|
87
|
+
</view>
|
|
88
|
+
</CheckmarkControlContext.Provider>;
|
|
89
|
+
});
|
|
90
|
+
CheckboxControl.displayName = "CheckboxControl";
|
|
91
|
+
function CheckboxIndicator(props) {
|
|
92
|
+
const { unchecked, checked: checkedIcon, indeterminate: indeterminateIcon, className, style } = props;
|
|
93
|
+
const context = useCheckboxContext("CheckboxIndicator");
|
|
94
|
+
const { iconClassName, checkmarkVariantProps } = useCheckmarkControlContext("CheckboxIndicator");
|
|
95
|
+
if (process.env.NODE_ENV !== "production" && context.indeterminate && !indeterminateIcon) console.warn("[seed-design] CheckboxIndicator: `indeterminate` prop must be provided when the checkbox is in an indeterminate state.");
|
|
96
|
+
const icon = context.indeterminate ? indeterminateIcon : context.checked ? checkedIcon : unchecked;
|
|
97
|
+
if (!icon || !isValidElement(icon)) return null;
|
|
98
|
+
return <InternalIcon icon={icon} className={clsx(iconClassName, className)} style={style} deps={[
|
|
99
|
+
context.checked,
|
|
100
|
+
context.indeterminate,
|
|
101
|
+
context.disabled,
|
|
102
|
+
context.pressed,
|
|
103
|
+
checkmarkVariantProps.tone,
|
|
104
|
+
checkmarkVariantProps.variant,
|
|
105
|
+
checkmarkVariantProps.size
|
|
106
|
+
]} />;
|
|
107
|
+
}
|
|
108
|
+
CheckboxIndicator.displayName = "CheckboxIndicator";
|
|
109
|
+
var CheckboxLabel = React.forwardRef((props, ref) => {
|
|
110
|
+
const { children, className, ...nativeProps } = props;
|
|
111
|
+
const context = useCheckboxContext("CheckboxLabel");
|
|
112
|
+
const labelClassName = checkbox({
|
|
113
|
+
...context.checkboxVariantProps,
|
|
114
|
+
disabled: context.disabled
|
|
115
|
+
}).label;
|
|
116
|
+
return <text {...ref ? { ref } : {}} className={clsx(labelClassName, className)} {...nativeProps}>
|
|
117
|
+
{children}
|
|
118
|
+
</text>;
|
|
119
|
+
});
|
|
120
|
+
CheckboxLabel.displayName = "CheckboxLabel";
|
|
121
|
+
var CheckboxGroup = React.forwardRef((props, ref) => {
|
|
122
|
+
const { children, className, ...nativeProps } = props;
|
|
123
|
+
const classes = checkboxGroup();
|
|
124
|
+
return <view {...ref ? { ref } : {}} className={clsx(classes.root, className)} {...nativeProps}>
|
|
125
|
+
{children}
|
|
126
|
+
</view>;
|
|
127
|
+
});
|
|
128
|
+
CheckboxGroup.displayName = "CheckboxGroup";
|
|
129
|
+
//#endregion
|
|
130
|
+
export { CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { CheckboxControl as Control, CheckboxGroup as Group, CheckboxIndicator as Indicator, CheckboxLabel as Label, CheckboxRoot as Root, type CheckboxControlProps as ControlProps, type CheckboxGroupProps as GroupProps, type CheckboxIndicatorProps as IndicatorProps, type CheckboxLabelProps as LabelProps, type CheckboxRootProps as RootProps, } from './Checkbox';
|
|
2
|
+
//# sourceMappingURL=Checkbox.namespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkbox.namespace.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox/Checkbox.namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,IAAI,OAAO,EAC1B,aAAa,IAAI,KAAK,EACtB,iBAAiB,IAAI,SAAS,EAC9B,aAAa,IAAI,KAAK,EACtB,YAAY,IAAI,IAAI,EACpB,KAAK,oBAAoB,IAAI,YAAY,EACzC,KAAK,kBAAkB,IAAI,UAAU,EACrC,KAAK,sBAAsB,IAAI,cAAc,EAC7C,KAAK,kBAAkB,IAAI,UAAU,EACrC,KAAK,iBAAiB,IAAI,SAAS,GACpC,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot } from "./Checkbox.jsx";
|
|
3
|
+
//#region src/components/Checkbox/Checkbox.namespace.ts
|
|
4
|
+
var Checkbox_namespace_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
Control: () => CheckboxControl,
|
|
6
|
+
Group: () => CheckboxGroup,
|
|
7
|
+
Indicator: () => CheckboxIndicator,
|
|
8
|
+
Label: () => CheckboxLabel,
|
|
9
|
+
Root: () => CheckboxRoot
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
export { Checkbox_namespace_exports };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { CheckboxRoot, CheckboxControl, CheckboxIndicator, CheckboxLabel, CheckboxGroup, type CheckboxRootProps, type CheckboxControlProps, type CheckboxIndicatorProps, type CheckboxLabelProps, type CheckboxGroupProps, } from './Checkbox';
|
|
2
|
+
export * as Checkbox from './Checkbox.namespace';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DependencyList, ReactElement } from '@lynx-js/react';
|
|
2
|
+
import { LynxIconElementProps, LynxStyledElementProps } from '../../types';
|
|
3
|
+
import { StyleProps } from '../../utils/styled';
|
|
4
|
+
import * as React from "@lynx-js/react";
|
|
5
|
+
export type IconSlotName = "icon" | "prefixIcon" | "suffixIcon";
|
|
6
|
+
interface IconSlotContextValue {
|
|
7
|
+
classNames?: Partial<Record<IconSlotName, string>>;
|
|
8
|
+
deps?: DependencyList;
|
|
9
|
+
}
|
|
10
|
+
export declare function IconRequired({ children, enabled, }: {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
export declare function IconSlotProvider({ value, children, }: {
|
|
15
|
+
value: IconSlotContextValue;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}): React.JSX.Element;
|
|
18
|
+
export declare function getIconSlotName(node: React.ReactNode): IconSlotName | null;
|
|
19
|
+
export interface IconProps extends LynxStyledElementProps {
|
|
20
|
+
icon: ReactElement<LynxIconElementProps>;
|
|
21
|
+
size?: StyleProps["height"] | number;
|
|
22
|
+
color?: StyleProps["color"];
|
|
23
|
+
}
|
|
24
|
+
export interface PrefixIconProps extends IconProps {
|
|
25
|
+
}
|
|
26
|
+
export interface SuffixIconProps extends IconProps {
|
|
27
|
+
}
|
|
28
|
+
export declare const Icon: React.ForwardRefExoticComponent<IconProps & React.RefAttributes<unknown>>;
|
|
29
|
+
export declare const PrefixIcon: React.ForwardRefExoticComponent<PrefixIconProps & React.RefAttributes<unknown>>;
|
|
30
|
+
export declare const SuffixIcon: React.ForwardRefExoticComponent<SuffixIconProps & React.RefAttributes<unknown>>;
|
|
31
|
+
export interface InternalIconProps extends LynxStyledElementProps {
|
|
32
|
+
icon: ReactElement<LynxIconElementProps>;
|
|
33
|
+
deps?: DependencyList;
|
|
34
|
+
}
|
|
35
|
+
export declare const InternalIcon: React.ForwardRefExoticComponent<InternalIconProps & React.RefAttributes<unknown>>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=Icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../src/components/Icon/Icon.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEnF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;AAIhE,UAAU,oBAAoB;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAWD,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB,qBAyCA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,oBAAoB,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,qBAEA;AAUD,wBAAgB,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,GAAG,YAAY,GAAG,IAAI,CAI1E;AAID,MAAM,WAAW,SAAU,SAAQ,sBAAsB;IACvD,IAAI,EAAE,YAAY,CAAC,oBAAoB,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;IACrC,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;CAAG;AAErD,MAAM,WAAW,eAAgB,SAAQ,SAAS;CAAG;AAqGrD,eAAO,MAAM,IAAI,2EAA8D,CAAC;AAChF,eAAO,MAAM,UAAU,iFAItB,CAAC;AACF,eAAO,MAAM,UAAU,iFAItB,CAAC;AAIF,MAAM,WAAW,iBAAkB,SAAQ,sBAAsB;IAC/D,IAAI,EAAE,YAAY,CAAC,oBAAoB,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,eAAO,MAAM,YAAY,mFA2BvB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { handleColor, handleDimension } from "../../utils/styled.js";
|
|
2
|
+
import { useIconColor } from "../../hooks/useIconColor.js";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import * as React from "@lynx-js/react";
|
|
5
|
+
import { cloneElement, isValidElement, useMainThreadRef } from "@lynx-js/react";
|
|
6
|
+
//#region src/components/Icon/Icon.tsx
|
|
7
|
+
var IconSlotContext = React.createContext(null);
|
|
8
|
+
var IconRequiredContext = React.createContext(null);
|
|
9
|
+
function IconRequired({ children, enabled }) {
|
|
10
|
+
const registeredCountRef = React.useRef(0);
|
|
11
|
+
const parentContext = React.useContext(IconRequiredContext);
|
|
12
|
+
const register = React.useCallback(() => {
|
|
13
|
+
registeredCountRef.current += 1;
|
|
14
|
+
if (process.env.NODE_ENV !== "production" && registeredCountRef.current > 1) throw new Error("Icon-only Component must render only one <Icon /> under children. Check if you are rendering multiple <Icon />.");
|
|
15
|
+
}, []);
|
|
16
|
+
const unregister = React.useCallback(() => {
|
|
17
|
+
registeredCountRef.current = Math.max(0, registeredCountRef.current - 1);
|
|
18
|
+
}, []);
|
|
19
|
+
React.useLayoutEffect(() => {
|
|
20
|
+
if (!enabled) return;
|
|
21
|
+
if (process.env.NODE_ENV !== "production") {
|
|
22
|
+
if (parentContext) throw new Error("Icon-only Component must not be nested within another Icon-Only. Check if you are using Icon-Only inside another Icon-Only.");
|
|
23
|
+
if (registeredCountRef.current === 0) throw new Error("Icon-only Component must render <Icon /> as a child. Check if you are using raw icon element instead of <Icon icon={} />.");
|
|
24
|
+
}
|
|
25
|
+
}, [enabled, parentContext]);
|
|
26
|
+
const value = React.useMemo(() => {
|
|
27
|
+
if (!enabled) return parentContext ?? null;
|
|
28
|
+
return {
|
|
29
|
+
register,
|
|
30
|
+
unregister
|
|
31
|
+
};
|
|
32
|
+
}, [
|
|
33
|
+
enabled,
|
|
34
|
+
parentContext,
|
|
35
|
+
register,
|
|
36
|
+
unregister
|
|
37
|
+
]);
|
|
38
|
+
return <IconRequiredContext.Provider value={value}>{children}</IconRequiredContext.Provider>;
|
|
39
|
+
}
|
|
40
|
+
function IconSlotProvider({ value, children }) {
|
|
41
|
+
return <IconSlotContext.Provider value={value}>{children}</IconSlotContext.Provider>;
|
|
42
|
+
}
|
|
43
|
+
var iconSlotMarker = Symbol.for("@seed-design/lynx-react/icon-slot");
|
|
44
|
+
function getIconSlotName(node) {
|
|
45
|
+
if (!isValidElement(node)) return null;
|
|
46
|
+
return node.type[iconSlotMarker] ?? null;
|
|
47
|
+
}
|
|
48
|
+
function mergeWrapperStyle({ size, color, style }) {
|
|
49
|
+
const dimension = handleDimension(size);
|
|
50
|
+
const resolvedColor = handleColor(color);
|
|
51
|
+
if (dimension == null && resolvedColor == null) return style;
|
|
52
|
+
return {
|
|
53
|
+
...dimension != null ? {
|
|
54
|
+
width: dimension,
|
|
55
|
+
height: dimension
|
|
56
|
+
} : {},
|
|
57
|
+
...resolvedColor != null ? { color: resolvedColor } : {},
|
|
58
|
+
...style
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getStyleColor(style) {
|
|
62
|
+
return style?.color;
|
|
63
|
+
}
|
|
64
|
+
var IconSlotBase = React.forwardRef((props, ref) => {
|
|
65
|
+
const { icon, slot, baseClassName, className, style, size, color, children: _children, ...nativeProps } = props;
|
|
66
|
+
const context = React.useContext(IconSlotContext);
|
|
67
|
+
const iconRequiredContext = React.useContext(IconRequiredContext);
|
|
68
|
+
const sourceRef = useMainThreadRef(null);
|
|
69
|
+
const slotClassName = slot != null ? context?.classNames?.[slot] : void 0;
|
|
70
|
+
const iconColor = useIconColor([
|
|
71
|
+
baseClassName,
|
|
72
|
+
slotClassName,
|
|
73
|
+
className,
|
|
74
|
+
size,
|
|
75
|
+
color,
|
|
76
|
+
getStyleColor(style),
|
|
77
|
+
...context?.deps ?? []
|
|
78
|
+
], { sourceRef });
|
|
79
|
+
const hasValidIcon = isValidElement(icon);
|
|
80
|
+
React.useLayoutEffect(() => {
|
|
81
|
+
if (slot !== "icon" || !hasValidIcon) return;
|
|
82
|
+
iconRequiredContext?.register();
|
|
83
|
+
return () => {
|
|
84
|
+
iconRequiredContext?.unregister();
|
|
85
|
+
};
|
|
86
|
+
}, [
|
|
87
|
+
hasValidIcon,
|
|
88
|
+
iconRequiredContext,
|
|
89
|
+
slot
|
|
90
|
+
]);
|
|
91
|
+
if (!hasValidIcon) return null;
|
|
92
|
+
return <view {...ref ? { ref } : {}} {...nativeProps} main-thread:ref={sourceRef} className={clsx(baseClassName, slotClassName, className)} style={mergeWrapperStyle({
|
|
93
|
+
size,
|
|
94
|
+
color,
|
|
95
|
+
style
|
|
96
|
+
})}>
|
|
97
|
+
{cloneElement(icon, {
|
|
98
|
+
...iconColor,
|
|
99
|
+
className: icon.props.className,
|
|
100
|
+
style: {
|
|
101
|
+
...icon.props.style,
|
|
102
|
+
width: "100%",
|
|
103
|
+
height: "100%"
|
|
104
|
+
}
|
|
105
|
+
})}
|
|
106
|
+
</view>;
|
|
107
|
+
});
|
|
108
|
+
IconSlotBase.displayName = "IconSlotBase";
|
|
109
|
+
function createIconComponent(displayName, slot, baseClassName) {
|
|
110
|
+
const Component = React.forwardRef((props, ref) => {
|
|
111
|
+
return <IconSlotBase ref={ref} slot={slot} baseClassName={baseClassName} {...props} />;
|
|
112
|
+
});
|
|
113
|
+
Component.displayName = displayName;
|
|
114
|
+
Component[iconSlotMarker] = slot;
|
|
115
|
+
return Component;
|
|
116
|
+
}
|
|
117
|
+
var Icon = createIconComponent("Icon", "icon", "seed-icon");
|
|
118
|
+
var PrefixIcon = createIconComponent("PrefixIcon", "prefixIcon", "seed-prefix-icon");
|
|
119
|
+
var SuffixIcon = createIconComponent("SuffixIcon", "suffixIcon", "seed-suffix-icon");
|
|
120
|
+
var InternalIcon = React.forwardRef((props, ref) => {
|
|
121
|
+
const { icon, deps = [], className, style, children: _children, ...nativeProps } = props;
|
|
122
|
+
const sourceRef = useMainThreadRef(null);
|
|
123
|
+
const iconColor = useIconColor([
|
|
124
|
+
className,
|
|
125
|
+
getStyleColor(style),
|
|
126
|
+
...deps ?? []
|
|
127
|
+
], { sourceRef });
|
|
128
|
+
if (!isValidElement(icon)) return null;
|
|
129
|
+
return <view {...ref ? { ref } : {}} {...nativeProps} main-thread:ref={sourceRef} className={className} style={style}>
|
|
130
|
+
{cloneElement(icon, {
|
|
131
|
+
...iconColor,
|
|
132
|
+
className: icon.props.className,
|
|
133
|
+
style: {
|
|
134
|
+
...icon.props.style,
|
|
135
|
+
width: "100%",
|
|
136
|
+
height: "100%"
|
|
137
|
+
}
|
|
138
|
+
})}
|
|
139
|
+
</view>;
|
|
140
|
+
});
|
|
141
|
+
InternalIcon.displayName = "InternalIcon";
|
|
142
|
+
//#endregion
|
|
143
|
+
export { Icon, IconRequired, IconSlotProvider, InternalIcon, PrefixIcon, SuffixIcon, getIconSlotName };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Icon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,QAAQ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ProgressCircleVariantProps } from '@seed-design/lynx-css/recipes/progress-circle';
|
|
2
|
+
import { LynxStyledElementProps } from '../../types';
|
|
3
|
+
import type * as React from "@lynx-js/react";
|
|
4
|
+
export interface ProgressCircleRootProps extends ProgressCircleVariantProps, LynxStyledElementProps {
|
|
5
|
+
minValue?: number;
|
|
6
|
+
maxValue?: number;
|
|
7
|
+
value?: number;
|
|
8
|
+
}
|
|
9
|
+
export type RootProps = ProgressCircleRootProps;
|
|
10
|
+
/**
|
|
11
|
+
* Lynx에서 SVG를 사용할 수 없어 CSS clip-path 기반 pie sector로 구현.
|
|
12
|
+
*
|
|
13
|
+
* **Known Issues:**
|
|
14
|
+
* - clip-path가 Lynx에서 animatable이 아니라 JS RAF로 매 프레임 SVG path 생성
|
|
15
|
+
* - Lynx main thread에서 모듈 레벨 Map 미지원으로 인스턴스 간 RAF 공유 불가
|
|
16
|
+
* - 다수 인스턴스 동시 렌더링 시 성능 저하 가능
|
|
17
|
+
*
|
|
18
|
+
* Lynx SVG + stroke-dasharray 지원 시 CSS-only 애니메이션으로 전환 예정.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ProgressCircleRoot: React.ForwardRefExoticComponent<ProgressCircleRootProps & React.RefAttributes<unknown>>;
|
|
21
|
+
export declare const ProgressCircleRange: {
|
|
22
|
+
(): React.JSX.Element;
|
|
23
|
+
displayName: string;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=ProgressCircle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressCircle.d.ts","sourceRoot":"","sources":["../../../src/components/ProgressCircle/ProgressCircle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAa7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,KAAK,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AA2GvE,MAAM,WAAW,uBACf,SAAQ,0BAA0B,EAChC,sBAAsB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,SAAS,GAAG,uBAAuB,CAAC;AAIhD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,yFA8B7B,CAAC;AAIH,eAAO,MAAM,mBAAmB;;;CAQ/B,CAAC"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { progressCircle } from "@seed-design/lynx-css/recipes/progress-circle";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { createContext, forwardRef, runOnMainThread, useContext, useEffect, useMainThreadRef, useMemo } from "@lynx-js/react";
|
|
4
|
+
//#region src/components/ProgressCircle/ProgressCircle.tsx
|
|
5
|
+
var ProgressCircleContext = createContext(null);
|
|
6
|
+
function useProgressCircleContext() {
|
|
7
|
+
const ctx = useContext(ProgressCircleContext);
|
|
8
|
+
if (!ctx) throw new Error("ProgressCircle compound components must be used within ProgressCircle.Root");
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
11
|
+
function computeRingGeometry(numSize) {
|
|
12
|
+
const halfSize = numSize / 2;
|
|
13
|
+
const innerR = .53 * Math.SQRT2 * halfSize;
|
|
14
|
+
return {
|
|
15
|
+
halfSize,
|
|
16
|
+
innerR,
|
|
17
|
+
ringCenterR: (halfSize + innerR) / 2,
|
|
18
|
+
capSize: halfSize - innerR
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function bgPieClipPath(size, angleDeg) {
|
|
22
|
+
if (angleDeg >= 360) return void 0;
|
|
23
|
+
if (angleDeg <= 0) return "path(\"M 0 0 Z\")";
|
|
24
|
+
const c = size / 2;
|
|
25
|
+
const r = c + 1;
|
|
26
|
+
const rad = angleDeg * Math.PI / 180;
|
|
27
|
+
const endX = c + r * Math.sin(rad);
|
|
28
|
+
const endY = c - r * Math.cos(rad);
|
|
29
|
+
const largeArc = angleDeg > 180 ? 1 : 0;
|
|
30
|
+
return `path("M ${c} ${c} L ${c} ${c - r} A ${r} ${r} 0 ${largeArc} 1 ${endX} ${endY} Z")`;
|
|
31
|
+
}
|
|
32
|
+
function cubicBezier(rawT, x1, y1, x2, y2) {
|
|
33
|
+
"main thread";
|
|
34
|
+
const t = Math.max(0, Math.min(1, rawT));
|
|
35
|
+
const cx = 3 * x1;
|
|
36
|
+
const bx = 3 * (x2 - x1) - cx;
|
|
37
|
+
const ax = 1 - cx - bx;
|
|
38
|
+
let currentT = t;
|
|
39
|
+
for (let i = 0; i < 8; i++) {
|
|
40
|
+
const currentX = ((ax * currentT + bx) * currentT + cx) * currentT - t;
|
|
41
|
+
const currentDx = (3 * ax * currentT + 2 * bx) * currentT + cx;
|
|
42
|
+
if (Math.abs(currentDx) < 1e-6) break;
|
|
43
|
+
currentT = currentT - currentX / currentDx;
|
|
44
|
+
}
|
|
45
|
+
const cy = 3 * y1;
|
|
46
|
+
const by = 3 * (y2 - y1) - cy;
|
|
47
|
+
return (((1 - cy - by) * currentT + by) * currentT + cy) * currentT;
|
|
48
|
+
}
|
|
49
|
+
function pieClipPath(size, angleDeg) {
|
|
50
|
+
"main thread";
|
|
51
|
+
if (angleDeg >= 360) return void 0;
|
|
52
|
+
if (angleDeg <= 0) return "path(\"M 0 0 Z\")";
|
|
53
|
+
const c = size / 2;
|
|
54
|
+
const r = c + 1;
|
|
55
|
+
const rad = angleDeg * Math.PI / 180;
|
|
56
|
+
const endX = c + r * Math.sin(rad);
|
|
57
|
+
const endY = c - r * Math.cos(rad);
|
|
58
|
+
const largeArc = angleDeg > 180 ? 1 : 0;
|
|
59
|
+
return `path("M ${c} ${c} L ${c} ${c - r} A ${r} ${r} 0 ${largeArc} 1 ${endX} ${endY} Z")`;
|
|
60
|
+
}
|
|
61
|
+
function sampleIndeterminate(t) {
|
|
62
|
+
"main thread";
|
|
63
|
+
const containerEased = cubicBezier(t, .35, .25, .65, .75);
|
|
64
|
+
const headEased = cubicBezier(t, .35, 0, .65, 1);
|
|
65
|
+
const tailEased = cubicBezier(t, .35, 0, .65, .6);
|
|
66
|
+
const headLength = headEased <= .75 ? headEased / .75 * 360 : 360;
|
|
67
|
+
const tailOffset = tailEased <= 1 / 3 ? 0 : (tailEased - 1 / 3) / (2 / 3) * 360;
|
|
68
|
+
const arcLength = Math.max(0, headLength - tailOffset);
|
|
69
|
+
return {
|
|
70
|
+
containerDeg: containerEased * 360 + tailOffset,
|
|
71
|
+
arcLength
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
var INDETERMINATE_DURATION = 1200;
|
|
75
|
+
var TRANSITION_DURATION = 300;
|
|
76
|
+
/**
|
|
77
|
+
* Lynx에서 SVG를 사용할 수 없어 CSS clip-path 기반 pie sector로 구현.
|
|
78
|
+
*
|
|
79
|
+
* **Known Issues:**
|
|
80
|
+
* - clip-path가 Lynx에서 animatable이 아니라 JS RAF로 매 프레임 SVG path 생성
|
|
81
|
+
* - Lynx main thread에서 모듈 레벨 Map 미지원으로 인스턴스 간 RAF 공유 불가
|
|
82
|
+
* - 다수 인스턴스 동시 렌더링 시 성능 저하 가능
|
|
83
|
+
*
|
|
84
|
+
* Lynx SVG + stroke-dasharray 지원 시 CSS-only 애니메이션으로 전환 예정.
|
|
85
|
+
*/
|
|
86
|
+
var ProgressCircleRoot = forwardRef((props, ref) => {
|
|
87
|
+
const [variantProps, otherProps] = progressCircle.splitVariantProps(props);
|
|
88
|
+
const { children, className, style, minValue, maxValue, value } = otherProps;
|
|
89
|
+
const size = variantProps.size ?? "40";
|
|
90
|
+
const tone = variantProps.tone ?? "neutral";
|
|
91
|
+
const numSize = Number(size);
|
|
92
|
+
const isDeterminate = minValue !== void 0 && maxValue !== void 0 && value !== void 0;
|
|
93
|
+
const range = (maxValue ?? 1) - (minValue ?? 0);
|
|
94
|
+
const progress = isDeterminate ? range === 0 ? 0 : ((value ?? 0) - (minValue ?? 0)) / range : 0;
|
|
95
|
+
const classes = progressCircle({
|
|
96
|
+
tone,
|
|
97
|
+
size
|
|
98
|
+
});
|
|
99
|
+
const ctx = useMemo(() => ({
|
|
100
|
+
numSize,
|
|
101
|
+
isDeterminate,
|
|
102
|
+
progress,
|
|
103
|
+
classes
|
|
104
|
+
}), [
|
|
105
|
+
numSize,
|
|
106
|
+
isDeterminate,
|
|
107
|
+
progress,
|
|
108
|
+
classes
|
|
109
|
+
]);
|
|
110
|
+
return <ProgressCircleContext.Provider value={ctx}>
|
|
111
|
+
<view {...ref ? { ref } : {}} className={clsx(classes.root, className)} style={{
|
|
112
|
+
...style,
|
|
113
|
+
width: `${numSize}px`,
|
|
114
|
+
height: `${numSize}px`
|
|
115
|
+
}}>
|
|
116
|
+
{children}
|
|
117
|
+
</view>
|
|
118
|
+
</ProgressCircleContext.Provider>;
|
|
119
|
+
});
|
|
120
|
+
var ProgressCircleRange = () => {
|
|
121
|
+
const { numSize, isDeterminate, progress, classes } = useProgressCircleContext();
|
|
122
|
+
if (!isDeterminate) return <IndeterminateRange numSize={numSize} classes={classes} />;
|
|
123
|
+
return <DeterminateRange numSize={numSize} progress={progress} classes={classes} />;
|
|
124
|
+
};
|
|
125
|
+
function DeterminateRange({ numSize, progress, classes }) {
|
|
126
|
+
const rangeRef = useMainThreadRef(null);
|
|
127
|
+
const startCapRef = useMainThreadRef(null);
|
|
128
|
+
const endCapRef = useMainThreadRef(null);
|
|
129
|
+
const prevProgressRef = useMainThreadRef(progress);
|
|
130
|
+
const cancelRef = useMainThreadRef(0);
|
|
131
|
+
const { halfSize, ringCenterR, capSize } = computeRingGeometry(numSize);
|
|
132
|
+
const initialAngle = progress * 360;
|
|
133
|
+
const initialClipPath = bgPieClipPath(numSize, initialAngle);
|
|
134
|
+
const initialEndRad = initialAngle * Math.PI / 180;
|
|
135
|
+
function startAnimation(newProgress) {
|
|
136
|
+
"main thread";
|
|
137
|
+
if (cancelRef.current) {
|
|
138
|
+
cancelAnimationFrame(cancelRef.current);
|
|
139
|
+
cancelRef.current = 0;
|
|
140
|
+
}
|
|
141
|
+
const from = prevProgressRef.current ?? 0;
|
|
142
|
+
prevProgressRef.current = newProgress;
|
|
143
|
+
if (from === newProgress) return;
|
|
144
|
+
const rangeEl = rangeRef.current;
|
|
145
|
+
const endCapEl = endCapRef.current;
|
|
146
|
+
let startTs = 0;
|
|
147
|
+
function applyProgress(p) {
|
|
148
|
+
const angleDeg = p * 360;
|
|
149
|
+
const cp = pieClipPath(numSize, angleDeg);
|
|
150
|
+
if (cp) rangeEl?.setStyleProperty("clip-path", cp);
|
|
151
|
+
else rangeEl?.setStyleProperty("clip-path", "none");
|
|
152
|
+
const rad = angleDeg * Math.PI / 180;
|
|
153
|
+
endCapEl?.setStyleProperties({
|
|
154
|
+
left: `${halfSize + ringCenterR * Math.sin(rad) - capSize / 2}px`,
|
|
155
|
+
top: `${halfSize - ringCenterR * Math.cos(rad) - capSize / 2}px`
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function step(ts) {
|
|
159
|
+
if (!startTs) startTs = Number(ts);
|
|
160
|
+
const elapsed = ts - startTs;
|
|
161
|
+
if (elapsed >= TRANSITION_DURATION) {
|
|
162
|
+
applyProgress(newProgress);
|
|
163
|
+
cancelRef.current = 0;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const eased = cubicBezier(elapsed / TRANSITION_DURATION, 0, 0, .15, 1);
|
|
167
|
+
applyProgress(from + (newProgress - from) * eased);
|
|
168
|
+
cancelRef.current = requestAnimationFrame(step);
|
|
169
|
+
}
|
|
170
|
+
applyProgress(from);
|
|
171
|
+
cancelRef.current = requestAnimationFrame(step);
|
|
172
|
+
}
|
|
173
|
+
function cancelAnimation() {
|
|
174
|
+
"main thread";
|
|
175
|
+
if (cancelRef.current) {
|
|
176
|
+
cancelAnimationFrame(cancelRef.current);
|
|
177
|
+
cancelRef.current = 0;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
runOnMainThread(startAnimation)(progress);
|
|
182
|
+
return () => {
|
|
183
|
+
runOnMainThread(cancelAnimation)();
|
|
184
|
+
};
|
|
185
|
+
}, [progress, numSize]);
|
|
186
|
+
return <>
|
|
187
|
+
<view main-thread:ref={rangeRef} className={classes.range} style={{
|
|
188
|
+
position: "absolute",
|
|
189
|
+
width: `${numSize}px`,
|
|
190
|
+
height: `${numSize}px`,
|
|
191
|
+
borderRadius: "50%",
|
|
192
|
+
clipPath: initialClipPath
|
|
193
|
+
}} />
|
|
194
|
+
<view main-thread:ref={startCapRef} className={classes.cap} style={{
|
|
195
|
+
width: `${capSize}px`,
|
|
196
|
+
height: `${capSize}px`,
|
|
197
|
+
left: `${halfSize - capSize / 2}px`,
|
|
198
|
+
top: `${halfSize - ringCenterR - capSize / 2}px`
|
|
199
|
+
}} />
|
|
200
|
+
<view main-thread:ref={endCapRef} className={classes.cap} style={{
|
|
201
|
+
width: `${capSize}px`,
|
|
202
|
+
height: `${capSize}px`,
|
|
203
|
+
left: `${halfSize + ringCenterR * Math.sin(initialEndRad) - capSize / 2}px`,
|
|
204
|
+
top: `${halfSize - ringCenterR * Math.cos(initialEndRad) - capSize / 2}px`
|
|
205
|
+
}} />
|
|
206
|
+
</>;
|
|
207
|
+
}
|
|
208
|
+
function IndeterminateRange({ numSize, classes }) {
|
|
209
|
+
const containerRef = useMainThreadRef(null);
|
|
210
|
+
const rangeRef = useMainThreadRef(null);
|
|
211
|
+
const headCapRef = useMainThreadRef(null);
|
|
212
|
+
const tailCapRef = useMainThreadRef(null);
|
|
213
|
+
const rafIdRef = useMainThreadRef(0);
|
|
214
|
+
const { halfSize, ringCenterR, capSize } = computeRingGeometry(numSize);
|
|
215
|
+
function startLoop() {
|
|
216
|
+
"main thread";
|
|
217
|
+
const containerEl = containerRef.current;
|
|
218
|
+
const rangeEl = rangeRef.current;
|
|
219
|
+
const headCapEl = headCapRef.current;
|
|
220
|
+
let startTs = 0;
|
|
221
|
+
function tick(ts) {
|
|
222
|
+
if (!startTs) startTs = Number(ts);
|
|
223
|
+
const state = sampleIndeterminate((ts - startTs) % INDETERMINATE_DURATION / INDETERMINATE_DURATION);
|
|
224
|
+
containerEl?.setStyleProperty("transform", `rotate(${state.containerDeg}deg)`);
|
|
225
|
+
const clipPath = pieClipPath(numSize, state.arcLength);
|
|
226
|
+
if (clipPath) rangeEl?.setStyleProperty("clip-path", clipPath);
|
|
227
|
+
else rangeEl?.setStyleProperty("clip-path", "none");
|
|
228
|
+
const headRad = state.arcLength * Math.PI / 180;
|
|
229
|
+
headCapEl?.setStyleProperties({
|
|
230
|
+
left: `${halfSize + ringCenterR * Math.sin(headRad) - capSize / 2}px`,
|
|
231
|
+
top: `${halfSize - ringCenterR * Math.cos(headRad) - capSize / 2}px`
|
|
232
|
+
});
|
|
233
|
+
rafIdRef.current = requestAnimationFrame(tick);
|
|
234
|
+
}
|
|
235
|
+
rafIdRef.current = requestAnimationFrame(tick);
|
|
236
|
+
}
|
|
237
|
+
function stopLoop() {
|
|
238
|
+
"main thread";
|
|
239
|
+
if (rafIdRef.current) {
|
|
240
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
241
|
+
rafIdRef.current = 0;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
runOnMainThread(startLoop)();
|
|
246
|
+
return () => {
|
|
247
|
+
runOnMainThread(stopLoop)();
|
|
248
|
+
};
|
|
249
|
+
}, [numSize]);
|
|
250
|
+
const initialClipPath = "path(\"M 0 0 Z\")";
|
|
251
|
+
return <view main-thread:ref={containerRef} style={{
|
|
252
|
+
position: "absolute",
|
|
253
|
+
width: `${numSize}px`,
|
|
254
|
+
height: `${numSize}px`,
|
|
255
|
+
transform: "rotate(0deg)"
|
|
256
|
+
}}>
|
|
257
|
+
<view main-thread:ref={rangeRef} className={classes.range} style={{
|
|
258
|
+
position: "absolute",
|
|
259
|
+
width: `${numSize}px`,
|
|
260
|
+
height: `${numSize}px`,
|
|
261
|
+
borderRadius: "50%",
|
|
262
|
+
clipPath: initialClipPath
|
|
263
|
+
}} />
|
|
264
|
+
<view main-thread:ref={tailCapRef} className={classes.cap} style={{
|
|
265
|
+
width: `${capSize}px`,
|
|
266
|
+
height: `${capSize}px`,
|
|
267
|
+
left: `${halfSize - capSize / 2}px`,
|
|
268
|
+
top: `${halfSize - ringCenterR - capSize / 2}px`
|
|
269
|
+
}} />
|
|
270
|
+
<view main-thread:ref={headCapRef} className={classes.cap} style={{
|
|
271
|
+
width: `${capSize}px`,
|
|
272
|
+
height: `${capSize}px`,
|
|
273
|
+
left: `${halfSize - capSize / 2}px`,
|
|
274
|
+
top: `${halfSize - ringCenterR - capSize / 2}px`
|
|
275
|
+
}} />
|
|
276
|
+
</view>;
|
|
277
|
+
}
|
|
278
|
+
ProgressCircleRoot.displayName = "ProgressCircleRoot";
|
|
279
|
+
ProgressCircleRange.displayName = "ProgressCircleRange";
|
|
280
|
+
//#endregion
|
|
281
|
+
export { ProgressCircleRange, ProgressCircleRoot };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressCircle.namespace.d.ts","sourceRoot":"","sources":["../../../src/components/ProgressCircle/ProgressCircle.namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,IAAI,KAAK,EAC5B,kBAAkB,IAAI,IAAI,EAC1B,KAAK,uBAAuB,IAAI,SAAS,GAC1C,MAAM,kBAAkB,CAAC"}
|