@seed-design/lynx-react 0.2.0-alpha.2 → 0.2.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 +26 -32
- package/lib/components/ActionButton/ActionButton.d.ts.map +1 -1
- package/lib/components/ActionButton/ActionButton.jsx +139 -120
- package/lib/components/ActionButton/index.d.ts +1 -1
- package/lib/components/AppBar/AppBar.d.ts +35 -0
- package/lib/components/AppBar/AppBar.d.ts.map +1 -0
- package/lib/components/AppBar/AppBar.jsx +132 -0
- package/lib/components/AppBar/AppBar.namespace.d.ts +2 -0
- package/lib/components/AppBar/AppBar.namespace.d.ts.map +1 -0
- package/lib/components/AppBar/AppBar.namespace.js +15 -0
- package/lib/components/AppBar/context.d.ts +13 -0
- package/lib/components/AppBar/context.d.ts.map +1 -0
- package/lib/components/AppBar/context.js +12 -0
- package/lib/components/AppBar/index.d.ts +3 -0
- package/lib/components/AppBar/index.d.ts.map +1 -0
- package/lib/components/AppBar/useAppBar.d.ts +15 -0
- package/lib/components/AppBar/useAppBar.d.ts.map +1 -0
- package/lib/components/AppBar/useAppBar.js +72 -0
- package/lib/components/Badge/Badge.d.ts +14 -0
- package/lib/components/Badge/Badge.d.ts.map +1 -0
- package/lib/components/Badge/Badge.jsx +15 -0
- package/lib/components/Badge/index.d.ts +2 -0
- package/lib/components/Badge/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts +22 -27
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/lib/components/BottomSheet/BottomSheet.jsx +127 -142
- package/lib/components/BottomSheet/BottomSheet.namespace.d.ts +1 -1
- package/lib/components/BottomSheet/BottomSheet.namespace.js +18 -1
- package/lib/components/BottomSheet/index.d.ts +2 -2
- 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 +14 -30
- package/lib/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/lib/components/Checkbox/Checkbox.jsx +107 -98
- package/lib/components/Checkbox/Checkbox.namespace.d.ts +1 -1
- package/lib/components/Checkbox/Checkbox.namespace.js +12 -1
- package/lib/components/Checkbox/index.d.ts +2 -2
- 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 +4 -8
- package/lib/components/ProgressCircle/ProgressCircle.d.ts.map +1 -1
- package/lib/components/ProgressCircle/ProgressCircle.jsx +255 -260
- package/lib/components/ProgressCircle/ProgressCircle.namespace.d.ts +1 -1
- package/lib/components/ProgressCircle/ProgressCircle.namespace.js +9 -1
- package/lib/components/ProgressCircle/index.d.ts +2 -2
- package/lib/components/RadioGroup/RadioGroup.d.ts +12 -28
- package/lib/components/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/lib/components/RadioGroup/RadioGroup.jsx +134 -118
- package/lib/components/RadioGroup/RadioGroup.namespace.d.ts +1 -1
- package/lib/components/RadioGroup/RadioGroup.namespace.js +12 -1
- package/lib/components/RadioGroup/index.d.ts +2 -2
- 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 +8 -14
- package/lib/components/Switch/Switch.d.ts.map +1 -1
- package/lib/components/Switch/Switch.jsx +82 -56
- package/lib/components/Switch/Switch.namespace.d.ts +1 -1
- package/lib/components/Switch/Switch.namespace.js +11 -1
- package/lib/components/Switch/index.d.ts +2 -2
- package/lib/components/TagGroup/TagGroup.d.ts +8 -14
- package/lib/components/TagGroup/TagGroup.d.ts.map +1 -1
- package/lib/components/TagGroup/TagGroup.jsx +42 -39
- package/lib/components/TagGroup/TagGroup.namespace.d.ts +1 -1
- package/lib/components/TagGroup/TagGroup.namespace.js +10 -1
- package/lib/components/TagGroup/index.d.ts +2 -2
- 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 +13 -7
- package/lib/components/index.d.ts.map +1 -1
- package/lib/hooks/index.d.ts +4 -3
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/{use-controllable-state.d.ts → useControllableState.d.ts} +1 -1
- 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/{use-press-tap.d.ts → usePressTap.d.ts} +12 -9
- 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 +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +29 -3
- package/lib/types.d.ts +51 -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 +13 -12
- package/lib/utils/create-slot-recipe-context.d.ts.map +1 -1
- package/lib/utils/create-slot-recipe-context.jsx +88 -70
- package/lib/utils/get-seed-class-name.d.ts +6 -7
- package/lib/utils/get-seed-class-name.d.ts.map +1 -1
- package/lib/utils/get-seed-class-name.js +26 -37
- package/lib/utils/index.d.ts +4 -4
- package/lib/utils/resolve-recipe-token.js +45 -43
- package/lib/utils/split-multiple-variants-props.js +32 -32
- 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 +9 -9
- package/src/components/ActionButton/ActionButton.test.tsx +167 -0
- package/src/components/ActionButton/ActionButton.tsx +210 -168
- package/src/components/AppBar/AppBar.namespace.ts +18 -0
- package/src/components/AppBar/AppBar.test.tsx +270 -0
- package/src/components/AppBar/AppBar.tsx +288 -0
- package/src/components/AppBar/context.ts +27 -0
- package/src/components/AppBar/index.ts +21 -0
- package/src/components/AppBar/useAppBar.ts +100 -0
- package/src/components/Badge/Badge.test.tsx +54 -0
- package/src/components/Badge/Badge.tsx +32 -0
- package/src/components/Badge/index.ts +1 -0
- package/src/components/BottomSheet/BottomSheet.test.tsx +219 -0
- package/src/components/BottomSheet/BottomSheet.tsx +120 -83
- 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.tsx +108 -117
- package/src/components/Icon/Icon.tsx +265 -0
- package/src/components/Icon/index.ts +8 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +39 -25
- package/src/components/RadioGroup/RadioGroup.tsx +100 -118
- package/src/components/Stack/Stack.tsx +97 -0
- package/src/components/Stack/index.ts +1 -0
- package/src/components/Switch/Switch.tsx +61 -52
- package/src/components/TagGroup/TagGroup.tsx +27 -25
- package/src/components/Text/Text.tsx +64 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/index.ts +6 -0
- package/src/hooks/index.ts +4 -3
- package/src/hooks/{__tests__/use-controllable-state.test.ts → useControllableState.test.ts} +1 -1
- package/src/hooks/useIconColor.test.ts +13 -0
- package/src/hooks/useIconColor.ts +67 -0
- package/src/hooks/{__tests__/use-press-tap.test.ts → usePressTap.test.ts} +1 -1
- package/src/hooks/{use-press-tap.ts → usePressTap.ts} +14 -10
- package/src/hooks/useSafeArea.test.ts +83 -0
- package/src/hooks/useSafeArea.ts +56 -0
- package/src/index.ts +1 -0
- package/src/types.ts +76 -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 +55 -15
- package/src/utils/get-seed-class-name.ts +7 -12
- package/src/utils/{__tests__/split-multiple-variants-props.test.ts → split-multiple-variants-props.test.ts} +1 -1
- package/src/utils/styled.ts +442 -0
- package/lib/components/ActionButton/index.js +0 -1
- package/lib/components/BottomSheet/index.js +0 -2
- package/lib/components/Checkbox/index.js +0 -2
- package/lib/components/ProgressCircle/index.js +0 -2
- package/lib/components/RadioGroup/index.js +0 -2
- package/lib/components/Switch/index.js +0 -2
- package/lib/components/TagGroup/index.js +0 -2
- package/lib/components/index.js +0 -7
- package/lib/hooks/index.js +0 -3
- package/lib/hooks/use-controllable-state.d.ts.map +0 -1
- package/lib/hooks/use-controllable-state.js +0 -27
- package/lib/hooks/use-icon-color.d.ts +0 -15
- package/lib/hooks/use-icon-color.d.ts.map +0 -1
- package/lib/hooks/use-icon-color.js +0 -37
- package/lib/hooks/use-press-tap.d.ts.map +0 -1
- package/lib/hooks/use-press-tap.js +0 -35
- package/lib/utils/index.js +0 -4
- package/src/components/ActionButton/__tests__/ActionButton.test.tsx +0 -35
- package/src/components/BottomSheet/__tests__/BottomSheet.test.tsx +0 -119
- package/src/components/__tests__/ProgressCircle.test.ts +0 -33
- package/src/components/__tests__/exports.test.ts +0 -38
- package/src/components/__tests__/switch.test.ts +0 -34
- package/src/hooks/use-icon-color.ts +0 -51
- package/src/utils/__tests__/create-slot-recipe-context.test.tsx +0 -228
- /package/src/hooks/{use-controllable-state.ts → useControllableState.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as React from "react";
|
|
1
|
+
import * as React from "@lynx-js/react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
|
|
4
4
|
import { switchStyle } from "@seed-design/lynx-css/recipes/switch";
|
|
@@ -7,8 +7,9 @@ import { switchmark } from "@seed-design/lynx-css/recipes/switchmark";
|
|
|
7
7
|
import type { SwitchmarkVariantProps } from "@seed-design/lynx-css/recipes/switchmark";
|
|
8
8
|
|
|
9
9
|
import { splitMultipleVariantsProps } from "../../utils/split-multiple-variants-props";
|
|
10
|
-
import { useControllableState } from "../../hooks/
|
|
11
|
-
import { usePressTap } from "../../hooks/
|
|
10
|
+
import { useControllableState } from "../../hooks/useControllableState";
|
|
11
|
+
import { usePressTap } from "../../hooks/usePressTap";
|
|
12
|
+
import type { LynxStyledElementProps, LynxTextRef, LynxViewRef } from "../../types";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @platform Lynx
|
|
@@ -23,14 +24,12 @@ import { usePressTap } from "../../hooks/use-press-tap";
|
|
|
23
24
|
* switchmark recipe 와 Switch 컴포넌트에 boolean variant 로 노출.
|
|
24
25
|
*/
|
|
25
26
|
|
|
26
|
-
type SwitchSize = NonNullable<SwitchVariantProps["size"]>;
|
|
27
|
-
type SwitchTone = NonNullable<SwitchmarkVariantProps["tone"]>;
|
|
28
|
-
|
|
29
27
|
interface SwitchContextValue {
|
|
30
28
|
checked: boolean;
|
|
31
29
|
disabled: boolean;
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
switchVariantProps: SwitchVariantProps;
|
|
31
|
+
switchmarkVariantProps: SwitchmarkVariantProps;
|
|
32
|
+
toggle: () => void;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
const SwitchContext = React.createContext<SwitchContextValue | null>(null);
|
|
@@ -43,10 +42,15 @@ function useSwitchContext(consumer: string): SwitchContextValue {
|
|
|
43
42
|
return ctx;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
interface SwitchmarkControlContextValue {
|
|
46
|
+
thumbClassName: string;
|
|
47
|
+
switchmarkVariantProps: SwitchmarkVariantProps;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const SwitchmarkControlContext = React.createContext<SwitchmarkControlContextValue | null>(null);
|
|
47
51
|
|
|
48
|
-
function
|
|
49
|
-
const ctx = React.useContext(
|
|
52
|
+
function useSwitchmarkControlContext(consumer: string): SwitchmarkControlContextValue {
|
|
53
|
+
const ctx = React.useContext(SwitchmarkControlContext);
|
|
50
54
|
if (!ctx) {
|
|
51
55
|
throw new Error(`<${consumer}/> must be rendered inside <SwitchControl/>.`);
|
|
52
56
|
}
|
|
@@ -55,9 +59,10 @@ function useSwitchmarkThumbClass(consumer: string): string {
|
|
|
55
59
|
|
|
56
60
|
////////////////////////////////////////////////////////////////////////////////////
|
|
57
61
|
|
|
58
|
-
export interface SwitchRootProps
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
export interface SwitchRootProps
|
|
63
|
+
extends SwitchVariantProps,
|
|
64
|
+
Omit<SwitchmarkVariantProps, "size">,
|
|
65
|
+
LynxStyledElementProps {
|
|
61
66
|
checked?: boolean;
|
|
62
67
|
defaultChecked?: boolean;
|
|
63
68
|
disabled?: boolean;
|
|
@@ -76,8 +81,6 @@ export const SwitchRoot = React.forwardRef<unknown, SwitchRootProps>((props, ref
|
|
|
76
81
|
} = props;
|
|
77
82
|
const [{ switch: switchVariantProps, switchmark: switchmarkVariantProps }, nativeProps] =
|
|
78
83
|
splitMultipleVariantsProps(restProps, { switch: switchStyle, switchmark });
|
|
79
|
-
const size: SwitchSize = switchVariantProps.size ?? "32";
|
|
80
|
-
const tone: SwitchTone = switchmarkVariantProps.tone ?? "brand";
|
|
81
84
|
|
|
82
85
|
const [checked, setChecked] = useControllableState({
|
|
83
86
|
value: checkedProp,
|
|
@@ -85,22 +88,30 @@ export const SwitchRoot = React.forwardRef<unknown, SwitchRootProps>((props, ref
|
|
|
85
88
|
onChange: onCheckedChange,
|
|
86
89
|
});
|
|
87
90
|
|
|
91
|
+
const toggle = React.useCallback(() => setChecked(!checked), [checked, setChecked]);
|
|
92
|
+
|
|
88
93
|
const { pressed: _pressed, ...pressHandlers } = usePressTap({
|
|
89
94
|
disabled,
|
|
90
|
-
onTap:
|
|
95
|
+
onTap: toggle,
|
|
91
96
|
});
|
|
92
97
|
|
|
93
|
-
const rootClassName = switchStyle({
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
() => ({
|
|
97
|
-
|
|
98
|
+
const rootClassName = switchStyle({ ...switchVariantProps, disabled }).root;
|
|
99
|
+
|
|
100
|
+
const contextValue = React.useMemo<SwitchContextValue>(
|
|
101
|
+
() => ({
|
|
102
|
+
checked,
|
|
103
|
+
disabled,
|
|
104
|
+
switchVariantProps,
|
|
105
|
+
switchmarkVariantProps,
|
|
106
|
+
toggle,
|
|
107
|
+
}),
|
|
108
|
+
[checked, disabled, switchVariantProps, switchmarkVariantProps, toggle],
|
|
98
109
|
);
|
|
99
110
|
|
|
100
111
|
return (
|
|
101
|
-
<SwitchContext.Provider value={
|
|
112
|
+
<SwitchContext.Provider value={contextValue}>
|
|
102
113
|
<view
|
|
103
|
-
{...(ref ? { ref: ref as
|
|
114
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
104
115
|
className={clsx(rootClassName, className)}
|
|
105
116
|
{...pressHandlers}
|
|
106
117
|
{...nativeProps}
|
|
@@ -114,51 +125,49 @@ SwitchRoot.displayName = "SwitchRoot";
|
|
|
114
125
|
|
|
115
126
|
////////////////////////////////////////////////////////////////////////////////////
|
|
116
127
|
|
|
117
|
-
export interface SwitchControlProps
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
128
|
+
export interface SwitchControlProps
|
|
129
|
+
extends Pick<SwitchmarkVariantProps, "tone" | "size">,
|
|
130
|
+
LynxStyledElementProps {}
|
|
121
131
|
|
|
122
132
|
export const SwitchControl = React.forwardRef<unknown, SwitchControlProps>((props, ref) => {
|
|
123
133
|
const [variantProps, restProps] = switchmark.splitVariantProps(props);
|
|
124
134
|
const { children, className, ...nativeProps } = restProps;
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
);
|
|
135
|
+
const context = useSwitchContext("SwitchControl");
|
|
136
|
+
const switchmarkVariantProps: SwitchmarkVariantProps = {
|
|
137
|
+
...context.switchmarkVariantProps,
|
|
138
|
+
...variantProps,
|
|
139
|
+
checked: context.checked,
|
|
140
|
+
disabled: context.disabled,
|
|
141
|
+
};
|
|
142
|
+
const classes = switchmark(switchmarkVariantProps);
|
|
134
143
|
|
|
135
144
|
return (
|
|
136
|
-
<
|
|
145
|
+
<SwitchmarkControlContext.Provider
|
|
146
|
+
value={{ thumbClassName: classes.thumb, switchmarkVariantProps }}
|
|
147
|
+
>
|
|
137
148
|
<view
|
|
138
|
-
{...(ref ? { ref: ref as
|
|
149
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
139
150
|
className={clsx(classes.root, className)}
|
|
140
151
|
{...nativeProps}
|
|
141
152
|
>
|
|
142
153
|
{children}
|
|
143
154
|
</view>
|
|
144
|
-
</
|
|
155
|
+
</SwitchmarkControlContext.Provider>
|
|
145
156
|
);
|
|
146
157
|
});
|
|
147
158
|
SwitchControl.displayName = "SwitchControl";
|
|
148
159
|
|
|
149
160
|
////////////////////////////////////////////////////////////////////////////////////
|
|
150
161
|
|
|
151
|
-
export interface SwitchThumbProps {
|
|
152
|
-
className?: string;
|
|
153
|
-
}
|
|
162
|
+
export interface SwitchThumbProps extends Pick<LynxStyledElementProps, "className" | "style"> {}
|
|
154
163
|
|
|
155
164
|
export const SwitchThumb = React.forwardRef<unknown, SwitchThumbProps>((props, ref) => {
|
|
156
165
|
const { className, ...nativeProps } = props;
|
|
157
|
-
const thumbClassName =
|
|
166
|
+
const { thumbClassName } = useSwitchmarkControlContext("SwitchThumb");
|
|
158
167
|
|
|
159
168
|
return (
|
|
160
169
|
<view
|
|
161
|
-
{...(ref ? { ref: ref as
|
|
170
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
162
171
|
className={clsx(thumbClassName, className)}
|
|
163
172
|
{...nativeProps}
|
|
164
173
|
/>
|
|
@@ -168,19 +177,19 @@ SwitchThumb.displayName = "SwitchThumb";
|
|
|
168
177
|
|
|
169
178
|
////////////////////////////////////////////////////////////////////////////////////
|
|
170
179
|
|
|
171
|
-
export interface SwitchLabelProps {
|
|
172
|
-
children?: React.ReactNode;
|
|
173
|
-
className?: string;
|
|
174
|
-
}
|
|
180
|
+
export interface SwitchLabelProps extends LynxStyledElementProps {}
|
|
175
181
|
|
|
176
182
|
export const SwitchLabel = React.forwardRef<unknown, SwitchLabelProps>((props, ref) => {
|
|
177
183
|
const { children, className, ...nativeProps } = props;
|
|
178
|
-
const
|
|
179
|
-
const labelClassName = switchStyle({
|
|
184
|
+
const context = useSwitchContext("SwitchLabel");
|
|
185
|
+
const labelClassName = switchStyle({
|
|
186
|
+
...context.switchVariantProps,
|
|
187
|
+
disabled: context.disabled,
|
|
188
|
+
}).label;
|
|
180
189
|
|
|
181
190
|
return (
|
|
182
191
|
<text
|
|
183
|
-
{...(ref ? { ref: ref as
|
|
192
|
+
{...(ref ? { ref: ref as LynxTextRef } : {})}
|
|
184
193
|
className={clsx(labelClassName, className)}
|
|
185
194
|
{...nativeProps}
|
|
186
195
|
>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as React from "react";
|
|
1
|
+
import * as React from "@lynx-js/react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { tagGroup, type TagGroupVariantProps } from "@seed-design/lynx-css/recipes/tag-group";
|
|
4
4
|
import {
|
|
@@ -6,12 +6,17 @@ import {
|
|
|
6
6
|
type TagGroupItemVariantProps,
|
|
7
7
|
} from "@seed-design/lynx-css/recipes/tag-group-item";
|
|
8
8
|
|
|
9
|
+
import type { LynxStyledElementProps, LynxTextRef, LynxViewRef } from "../../types";
|
|
10
|
+
import { toArray } from "../../utils/children";
|
|
9
11
|
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
|
|
10
12
|
import { splitMultipleVariantsProps } from "../../utils/split-multiple-variants-props";
|
|
13
|
+
import { useStyleProps, type StyleProps } from "../../utils/styled";
|
|
11
14
|
|
|
12
15
|
const { PropsProvider, useProps, ClassNamesProvider, useClassNames } =
|
|
13
16
|
createSlotRecipeContext(tagGroupItem);
|
|
14
17
|
|
|
18
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
21
|
* @platform Lynx
|
|
17
22
|
*
|
|
@@ -19,12 +24,12 @@ const { PropsProvider, useProps, ClassNamesProvider, useClassNames } =
|
|
|
19
24
|
* - `truncate` prop: Lynx flex 모델에서는 item 단위 wrap만 가능해 웹 수준의
|
|
20
25
|
* "한 줄 유지 + label ellipsis" 조합을 재현할 수 없음
|
|
21
26
|
* - `asChild` prop: Lynx Slot 미지원
|
|
22
|
-
* - `flexShrink` prop: CSS variable 동적 주입 제한
|
|
23
27
|
* - 아이콘 slot: Lynx 3.7 SVG 지원 후 검토 (Tier B)
|
|
24
28
|
*/
|
|
25
|
-
export interface TagGroupRootProps
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
export interface TagGroupRootProps
|
|
30
|
+
extends TagGroupVariantProps,
|
|
31
|
+
TagGroupItemVariantProps,
|
|
32
|
+
LynxStyledElementProps {
|
|
28
33
|
/**
|
|
29
34
|
* children 사이에 삽입되는 구분자. 기본값 `" · "`.
|
|
30
35
|
*/
|
|
@@ -37,12 +42,12 @@ export const TagGroupRoot = React.forwardRef<unknown, TagGroupRootProps>((props,
|
|
|
37
42
|
const { children, className, separator = " · ", ...nativeProps } = otherProps;
|
|
38
43
|
const classes = tagGroup(tagGroupVariantProps);
|
|
39
44
|
|
|
40
|
-
const visibleChildren =
|
|
45
|
+
const visibleChildren = toArray(children);
|
|
41
46
|
|
|
42
47
|
return (
|
|
43
48
|
<PropsProvider value={tagGroupItemVariantProps}>
|
|
44
49
|
<view
|
|
45
|
-
{...(ref ? { ref: ref as
|
|
50
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
46
51
|
className={clsx(classes.root, className)}
|
|
47
52
|
{...nativeProps}
|
|
48
53
|
>
|
|
@@ -54,12 +59,7 @@ export const TagGroupRoot = React.forwardRef<unknown, TagGroupRootProps>((props,
|
|
|
54
59
|
return (
|
|
55
60
|
<view
|
|
56
61
|
key={(child as React.ReactElement).key ?? index}
|
|
57
|
-
|
|
58
|
-
display: "flex",
|
|
59
|
-
flexDirection: "row",
|
|
60
|
-
alignItems: "center",
|
|
61
|
-
flexShrink: 0,
|
|
62
|
-
}}
|
|
62
|
+
className={classes.separatorWrapper}
|
|
63
63
|
>
|
|
64
64
|
<text className={classes.separator}>{separator}</text>
|
|
65
65
|
{child}
|
|
@@ -72,29 +72,32 @@ export const TagGroupRoot = React.forwardRef<unknown, TagGroupRootProps>((props,
|
|
|
72
72
|
});
|
|
73
73
|
TagGroupRoot.displayName = "TagGroupRoot";
|
|
74
74
|
|
|
75
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
76
|
+
|
|
75
77
|
/**
|
|
76
78
|
* @platform Lynx
|
|
77
79
|
*
|
|
78
80
|
* 웹 대비 미지원 기능:
|
|
79
81
|
* - `asChild` prop: Lynx Slot 미지원
|
|
80
|
-
* - `flexShrink` prop: CSS variable 동적 주입 제한
|
|
81
82
|
*/
|
|
82
|
-
export interface TagGroupItemProps
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
83
|
+
export interface TagGroupItemProps
|
|
84
|
+
extends TagGroupItemVariantProps,
|
|
85
|
+
Pick<StyleProps, "flexShrink">,
|
|
86
|
+
LynxStyledElementProps {}
|
|
86
87
|
|
|
87
88
|
export const TagGroupItem = React.forwardRef<unknown, TagGroupItemProps>((props, ref) => {
|
|
88
89
|
const parentVariantProps = useProps();
|
|
89
90
|
const [localVariantProps, otherProps] = tagGroupItem.splitVariantProps(props);
|
|
90
91
|
const classes = tagGroupItem({ ...parentVariantProps, ...localVariantProps });
|
|
91
|
-
const {
|
|
92
|
+
const { style, restProps } = useStyleProps(otherProps);
|
|
93
|
+
const { children, className, ...nativeProps } = restProps;
|
|
92
94
|
|
|
93
95
|
return (
|
|
94
96
|
<ClassNamesProvider value={classes}>
|
|
95
97
|
<view
|
|
96
|
-
{...(ref ? { ref: ref as
|
|
98
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
97
99
|
className={clsx(classes.root, className)}
|
|
100
|
+
style={style}
|
|
98
101
|
{...nativeProps}
|
|
99
102
|
>
|
|
100
103
|
{children}
|
|
@@ -104,17 +107,16 @@ export const TagGroupItem = React.forwardRef<unknown, TagGroupItemProps>((props,
|
|
|
104
107
|
});
|
|
105
108
|
TagGroupItem.displayName = "TagGroupItem";
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
110
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
111
|
+
|
|
112
|
+
export interface TagGroupItemLabelProps extends LynxStyledElementProps {}
|
|
111
113
|
|
|
112
114
|
export const TagGroupItemLabel = React.forwardRef<unknown, TagGroupItemLabelProps>((props, ref) => {
|
|
113
115
|
const classes = useClassNames();
|
|
114
116
|
const { children, className, ...nativeProps } = props;
|
|
115
117
|
return (
|
|
116
118
|
<text
|
|
117
|
-
{...(ref ? { ref: ref as
|
|
119
|
+
{...(ref ? { ref: ref as LynxTextRef } : {})}
|
|
118
120
|
className={clsx(classes.label, className)}
|
|
119
121
|
{...nativeProps}
|
|
120
122
|
>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { typography } from "@seed-design/lynx-css/vars/component";
|
|
2
|
+
import type { CSSProperties } from "@lynx-js/types";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import * as React from "@lynx-js/react";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
handleColor,
|
|
8
|
+
handleFontSize,
|
|
9
|
+
handleFontWeight,
|
|
10
|
+
handleLineHeight,
|
|
11
|
+
type TextStyle,
|
|
12
|
+
type TextStyleProps,
|
|
13
|
+
} from "../../utils/styled";
|
|
14
|
+
import type { LynxStyledElementProps, LynxTextRef } from "../../types";
|
|
15
|
+
|
|
16
|
+
function capitalize<T extends string>(value: T): Capitalize<T> {
|
|
17
|
+
return (value.charAt(0).toUpperCase() + value.slice(1)) as Capitalize<T>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getTypographyStyle(textStyle: TextStyle | undefined) {
|
|
21
|
+
const key = `textStyle${capitalize(textStyle ?? "t5Regular")}`;
|
|
22
|
+
const value = typography[key as keyof typeof typography];
|
|
23
|
+
return value.enabled.root;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TextProps extends TextStyleProps, LynxStyledElementProps {}
|
|
27
|
+
|
|
28
|
+
export const Text = React.forwardRef<unknown, TextProps>((props, ref) => {
|
|
29
|
+
const {
|
|
30
|
+
color,
|
|
31
|
+
textStyle,
|
|
32
|
+
fontSize,
|
|
33
|
+
lineHeight,
|
|
34
|
+
fontWeight,
|
|
35
|
+
align,
|
|
36
|
+
children,
|
|
37
|
+
className,
|
|
38
|
+
style,
|
|
39
|
+
...nativeProps
|
|
40
|
+
} = props;
|
|
41
|
+
const typographyStyle = getTypographyStyle(textStyle);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<text
|
|
45
|
+
{...(ref ? { ref: ref as LynxTextRef } : {})}
|
|
46
|
+
{...nativeProps}
|
|
47
|
+
className={clsx(className)}
|
|
48
|
+
style={
|
|
49
|
+
{
|
|
50
|
+
color: handleColor(color),
|
|
51
|
+
fontSize: handleFontSize(fontSize) ?? typographyStyle.fontSize,
|
|
52
|
+
lineHeight: handleLineHeight(lineHeight ?? fontSize) ?? typographyStyle.lineHeight,
|
|
53
|
+
fontWeight: handleFontWeight(fontWeight) ?? typographyStyle.fontWeight,
|
|
54
|
+
textAlign: align,
|
|
55
|
+
...style,
|
|
56
|
+
} as CSSProperties
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
{children}
|
|
60
|
+
</text>
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
Text.displayName = "Text";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Text, type TextProps } from "./Text";
|
package/src/components/index.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
export * from "./ActionButton";
|
|
2
|
+
export * from "./AppBar";
|
|
3
|
+
export * from "./Badge";
|
|
4
|
+
export * from "./Box";
|
|
2
5
|
export * from "./BottomSheet";
|
|
3
6
|
export * from "./Checkbox";
|
|
7
|
+
export * from "./Icon";
|
|
4
8
|
export * from "./ProgressCircle";
|
|
5
9
|
export * from "./RadioGroup";
|
|
10
|
+
export * from "./Stack";
|
|
6
11
|
export * from "./Switch";
|
|
7
12
|
export * from "./TagGroup";
|
|
13
|
+
export * from "./Text";
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./useControllableState";
|
|
2
|
+
export * from "./useIconColor";
|
|
3
|
+
export * from "./usePressTap";
|
|
4
|
+
export * from "./useSafeArea";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { act, renderHook } from "@lynx-js/react/testing-library";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { useControllableState } from "
|
|
3
|
+
import { useControllableState } from "./useControllableState";
|
|
4
4
|
|
|
5
5
|
describe("useControllableState", () => {
|
|
6
6
|
describe("uncontrolled mode", () => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { renderHook } from "@lynx-js/react/testing-library";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { useIconColor } from "./useIconColor";
|
|
5
|
+
|
|
6
|
+
describe("useIconColor", () => {
|
|
7
|
+
it("returns icon tint sync props", () => {
|
|
8
|
+
const { result } = renderHook(() => useIconColor([]));
|
|
9
|
+
|
|
10
|
+
expect(result.current).toHaveProperty("ref");
|
|
11
|
+
expect(result.current["main-thread:binduiappear"]).toBeDefined();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { runOnMainThread, useEffect, useMainThreadRef } from "@lynx-js/react";
|
|
2
|
+
import type { MainThread } from "@lynx-js/types";
|
|
3
|
+
import type { DependencyList, RefObject } from "@lynx-js/react";
|
|
4
|
+
|
|
5
|
+
type IconElement = MainThread.Element & {
|
|
6
|
+
getComputedStyleProperty?: (name: string) => string;
|
|
7
|
+
getComputedCssProperty?: (name: string) => string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface UseIconColorOptions {
|
|
11
|
+
sourceRef?: RefObject<MainThread.Element>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Lynx `<image>` 의 `tint-color` attribute 에 CSS variable 문자열을 직접 넣는 경로는
|
|
15
|
+
// 안정적으로 동작하지 않는다. CSS `color` 는 computed style 로 resolved color 를 읽을 수
|
|
16
|
+
// 있으므로 main-thread 에서 한 번 읽어 `tint-color` 로 mirror 한다.
|
|
17
|
+
function syncTintColor(targetRef: RefObject<IconElement>, sourceRef?: RefObject<IconElement>) {
|
|
18
|
+
"main thread";
|
|
19
|
+
|
|
20
|
+
const target = targetRef.current;
|
|
21
|
+
if (!target) return;
|
|
22
|
+
|
|
23
|
+
const source = sourceRef?.current ?? target;
|
|
24
|
+
|
|
25
|
+
let color: string | undefined;
|
|
26
|
+
if (typeof source.getComputedStyleProperty === "function") {
|
|
27
|
+
color = source.getComputedStyleProperty("color");
|
|
28
|
+
} else if (typeof source.getComputedCssProperty === "function") {
|
|
29
|
+
color = source.getComputedCssProperty("color");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (color) {
|
|
33
|
+
target.setAttribute("tint-color", color);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Lynx `<image>` 의 tint color 를 recipe 의 CSS `color` 로부터 main-thread 에서 읽어
|
|
39
|
+
* `tint-color` attribute 로 mirror. `deps` 가 바뀌면 재동기화.
|
|
40
|
+
*
|
|
41
|
+
* ```tsx
|
|
42
|
+
* const iconColorProps = useIconColor([variant, disabled, loading]);
|
|
43
|
+
* return cloneElement(iconChild, iconColorProps);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function useIconColor(
|
|
47
|
+
deps: DependencyList,
|
|
48
|
+
options?: UseIconColorOptions,
|
|
49
|
+
): {
|
|
50
|
+
ref: RefObject<MainThread.Element>;
|
|
51
|
+
"main-thread:binduiappear": () => void;
|
|
52
|
+
} {
|
|
53
|
+
const ref = useMainThreadRef<IconElement>(null);
|
|
54
|
+
const sourceRef = options?.sourceRef as RefObject<IconElement> | undefined;
|
|
55
|
+
|
|
56
|
+
function syncOnUiAppear() {
|
|
57
|
+
"main thread";
|
|
58
|
+
syncTintColor(ref, sourceRef);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// deps 는 caller 가 책임.
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
runOnMainThread(syncTintColor)(ref, sourceRef);
|
|
64
|
+
}, deps);
|
|
65
|
+
|
|
66
|
+
return { ref, "main-thread:binduiappear": syncOnUiAppear };
|
|
67
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { act, renderHook } from "@lynx-js/react/testing-library";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { usePressTap } from "
|
|
3
|
+
import { usePressTap } from "./usePressTap";
|
|
4
4
|
|
|
5
5
|
const fakeEvent = {} as Parameters<ReturnType<typeof usePressTap>["bindtap"]>[0];
|
|
6
6
|
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { useState } from "@lynx-js/react";
|
|
2
|
-
import type { TouchEvent } from "@lynx-js/types";
|
|
3
2
|
import { useMemoizedFn } from "@lynx-js/lynx-ui-common";
|
|
3
|
+
import type { BaseTouchEvent, EventHandler, Target } from "@lynx-js/types";
|
|
4
|
+
|
|
5
|
+
import type { LynxTouchProps } from "../types";
|
|
6
|
+
|
|
7
|
+
type TouchHandler = EventHandler<BaseTouchEvent<Target>>;
|
|
4
8
|
|
|
5
9
|
export interface UsePressTapOptions {
|
|
6
10
|
disabled?: boolean;
|
|
7
|
-
onTap?:
|
|
8
|
-
mainThreadOnTap?:
|
|
11
|
+
onTap?: TouchHandler;
|
|
12
|
+
mainThreadOnTap?: LynxTouchProps["main-thread:bindtap"];
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
export interface UsePressTapReturn {
|
|
12
16
|
pressed: boolean;
|
|
13
|
-
bindtap:
|
|
14
|
-
bindtouchstart:
|
|
15
|
-
bindtouchend:
|
|
16
|
-
bindtouchcancel:
|
|
17
|
-
"main-thread:bindtap"?:
|
|
17
|
+
bindtap: TouchHandler;
|
|
18
|
+
bindtouchstart: TouchHandler;
|
|
19
|
+
bindtouchend: TouchHandler;
|
|
20
|
+
bindtouchcancel: TouchHandler;
|
|
21
|
+
"main-thread:bindtap"?: LynxTouchProps["main-thread:bindtap"];
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
/**
|
|
@@ -38,9 +42,9 @@ export function usePressTap(options: UsePressTapOptions = {}): UsePressTapReturn
|
|
|
38
42
|
setPressed(false);
|
|
39
43
|
});
|
|
40
44
|
|
|
41
|
-
const handleTap = useMemoizedFn(() => {
|
|
45
|
+
const handleTap = useMemoizedFn((...args: Parameters<TouchHandler>) => {
|
|
42
46
|
if (disabled) return;
|
|
43
|
-
onTap?.();
|
|
47
|
+
onTap?.(...args);
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
return {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { renderHook } from "@lynx-js/react/testing-library";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { useSafeArea } from "./useSafeArea";
|
|
5
|
+
|
|
6
|
+
interface TestLynxGlobal {
|
|
7
|
+
lynx?: {
|
|
8
|
+
__globalProps?: {
|
|
9
|
+
safeAreaInsetTop?: number;
|
|
10
|
+
safeAreaInsetBottom?: number;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
lynxTestingEnv?: {
|
|
14
|
+
backgroundThread: {
|
|
15
|
+
globalThis: TestLynxGlobal;
|
|
16
|
+
};
|
|
17
|
+
mainThread: {
|
|
18
|
+
globalThis: TestLynxGlobal;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function setGlobalProps(
|
|
24
|
+
globalProps: NonNullable<NonNullable<TestLynxGlobal["lynx"]>["__globalProps"]>,
|
|
25
|
+
) {
|
|
26
|
+
const lynxTestingEnv = (globalThis as TestLynxGlobal).lynxTestingEnv;
|
|
27
|
+
|
|
28
|
+
if (!lynxTestingEnv) {
|
|
29
|
+
throw new Error("Expected Lynx testing environment globals to be available.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const globals = [
|
|
33
|
+
globalThis as TestLynxGlobal,
|
|
34
|
+
lynxTestingEnv.backgroundThread.globalThis,
|
|
35
|
+
lynxTestingEnv.mainThread.globalThis,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
for (const global of globals) {
|
|
39
|
+
global.lynx = {
|
|
40
|
+
...global.lynx,
|
|
41
|
+
__globalProps: globalProps,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe("useSafeArea", () => {
|
|
47
|
+
it("falls back to Lynx env values when host flat global props are missing", () => {
|
|
48
|
+
const { result } = renderHook(() => useSafeArea());
|
|
49
|
+
|
|
50
|
+
expect(result.current).toEqual({
|
|
51
|
+
safeAreaInsetTop: "env(safe-area-inset-top)",
|
|
52
|
+
safeAreaInsetBottom: "env(safe-area-inset-bottom)",
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("uses flat globalProps values before env fallback", () => {
|
|
57
|
+
setGlobalProps({
|
|
58
|
+
safeAreaInsetTop: 48,
|
|
59
|
+
safeAreaInsetBottom: 35,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const { result } = renderHook(() => useSafeArea());
|
|
63
|
+
|
|
64
|
+
expect(result.current).toEqual({
|
|
65
|
+
safeAreaInsetTop: "48px",
|
|
66
|
+
safeAreaInsetBottom: "35px",
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("falls back to Lynx env values when host flat global props are zero", () => {
|
|
71
|
+
setGlobalProps({
|
|
72
|
+
safeAreaInsetTop: 0,
|
|
73
|
+
safeAreaInsetBottom: 0,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const { result } = renderHook(() => useSafeArea());
|
|
77
|
+
|
|
78
|
+
expect(result.current).toEqual({
|
|
79
|
+
safeAreaInsetTop: "env(safe-area-inset-top)",
|
|
80
|
+
safeAreaInsetBottom: "env(safe-area-inset-bottom)",
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|