@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
|
@@ -24,16 +24,27 @@ import {
|
|
|
24
24
|
useContext,
|
|
25
25
|
useMemo,
|
|
26
26
|
useRef,
|
|
27
|
-
type
|
|
28
|
-
type
|
|
27
|
+
type ForwardRefExoticComponent,
|
|
28
|
+
type PropsWithoutRef,
|
|
29
|
+
type ReactElement,
|
|
29
30
|
type RefObject,
|
|
31
|
+
type RefAttributes,
|
|
30
32
|
} from "@lynx-js/react";
|
|
31
|
-
import type { CSSProperties } from "react";
|
|
32
33
|
import clsx from "clsx";
|
|
33
34
|
|
|
35
|
+
import { useSafeArea } from "../../hooks/useSafeArea";
|
|
36
|
+
import type {
|
|
37
|
+
LynxPressableProps,
|
|
38
|
+
LynxStyledElementProps,
|
|
39
|
+
LynxTextRef,
|
|
40
|
+
LynxViewRef,
|
|
41
|
+
} from "../../types";
|
|
34
42
|
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
|
|
35
43
|
|
|
36
44
|
type BottomSheetClassNames = ReturnType<typeof bottomSheet>;
|
|
45
|
+
type LynxForwardRefComponent<T, P> = ForwardRefExoticComponent<
|
|
46
|
+
PropsWithoutRef<P> & RefAttributes<T>
|
|
47
|
+
>;
|
|
37
48
|
|
|
38
49
|
const { ClassNamesProvider, useClassNames, withContext } = createSlotRecipeContext(bottomSheet);
|
|
39
50
|
|
|
@@ -132,8 +143,8 @@ export interface BottomSheetRootProps
|
|
|
132
143
|
* - `BottomSheetCloseButton`: Tier B (Lynx SVG 지원 후 추가 예정)
|
|
133
144
|
* - `BottomSheetTrigger`의 `asChild`: 미지원 (기본 `<view>`만)
|
|
134
145
|
*/
|
|
135
|
-
export const BottomSheetRoot
|
|
136
|
-
(props, forwardedRef) => {
|
|
146
|
+
export const BottomSheetRoot: LynxForwardRefComponent<SheetRootRef, BottomSheetRootProps> =
|
|
147
|
+
forwardRef<SheetRootRef, BottomSheetRootProps>((props, forwardedRef) => {
|
|
137
148
|
const [variantProps, restProps] = bottomSheet.splitVariantProps(props);
|
|
138
149
|
const { open, defaultOpen, onOpenChange, snapPoints, children, ...nativeProps } = restProps;
|
|
139
150
|
const { headerAlign, skipAnimation } = variantProps;
|
|
@@ -186,50 +197,47 @@ export const BottomSheetRoot = forwardRef<SheetRootRef, BottomSheetRootProps>(
|
|
|
186
197
|
</ClassNamesProvider>
|
|
187
198
|
</BottomSheetContext.Provider>
|
|
188
199
|
);
|
|
189
|
-
}
|
|
190
|
-
);
|
|
200
|
+
});
|
|
191
201
|
BottomSheetRoot.displayName = "BottomSheetRoot";
|
|
192
202
|
|
|
193
203
|
////////////////////////////////////////////////////////////////////////////////////
|
|
194
204
|
// Trigger
|
|
195
205
|
////////////////////////////////////////////////////////////////////////////////////
|
|
196
206
|
|
|
197
|
-
export interface BottomSheetTriggerProps
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
207
|
+
export interface BottomSheetTriggerProps
|
|
208
|
+
extends LynxStyledElementProps,
|
|
209
|
+
Pick<LynxPressableProps, "bindtap"> {}
|
|
210
|
+
|
|
211
|
+
export const BottomSheetTrigger: LynxForwardRefComponent<unknown, BottomSheetTriggerProps> =
|
|
212
|
+
forwardRef<unknown, BottomSheetTriggerProps>((props, ref) => {
|
|
213
|
+
const { children, className, style, bindtap: userBindtap } = props;
|
|
214
|
+
const { rootRef, options } = useBottomSheetContext();
|
|
215
|
+
|
|
216
|
+
// `bindtap`을 직접 prop으로 쓰면 React DOM `<view>` 타입(SVG)이 적용되어 TS가 거부한다.
|
|
217
|
+
// Lynx JSX 런타임은 이 prop을 올바르게 처리하므로 spread로 우회한다 (ActionButton과 동일 패턴).
|
|
218
|
+
const handlers: Pick<LynxPressableProps, "bindtap"> = {
|
|
219
|
+
bindtap: (event, instance) => {
|
|
220
|
+
if (options.skipAnimation) {
|
|
221
|
+
rootRef.current?.open({ animate: false });
|
|
222
|
+
} else {
|
|
223
|
+
rootRef.current?.open();
|
|
224
|
+
}
|
|
203
225
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// `bindtap`을 직접 prop으로 쓰면 React DOM `<view>` 타입(SVG)이 적용되어 TS가 거부한다.
|
|
209
|
-
// Lynx JSX 런타임은 이 prop을 올바르게 처리하므로 spread로 우회한다 (ActionButton과 동일 패턴).
|
|
210
|
-
const handlers = {
|
|
211
|
-
bindtap: () => {
|
|
212
|
-
if (options.skipAnimation) {
|
|
213
|
-
rootRef.current?.open({ animate: false });
|
|
214
|
-
} else {
|
|
215
|
-
rootRef.current?.open();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
userBindtap?.();
|
|
219
|
-
},
|
|
220
|
-
};
|
|
226
|
+
userBindtap?.(event, instance);
|
|
227
|
+
},
|
|
228
|
+
};
|
|
221
229
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
});
|
|
230
|
+
return (
|
|
231
|
+
<view
|
|
232
|
+
{...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
|
|
233
|
+
{...handlers}
|
|
234
|
+
className={className}
|
|
235
|
+
style={style as never}
|
|
236
|
+
>
|
|
237
|
+
{children}
|
|
238
|
+
</view>
|
|
239
|
+
);
|
|
240
|
+
});
|
|
233
241
|
BottomSheetTrigger.displayName = "BottomSheetTrigger";
|
|
234
242
|
|
|
235
243
|
////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -248,10 +256,8 @@ export interface BottomSheetPositionerProps extends SheetViewProps {}
|
|
|
248
256
|
* recipe의 `positioner` slot className을 자동 적용해 `position: fixed` + 전체
|
|
249
257
|
* 뷰포트 커버 레이아웃을 보장한다.
|
|
250
258
|
*/
|
|
251
|
-
export const BottomSheetPositioner
|
|
252
|
-
SheetView,
|
|
253
|
-
"positioner",
|
|
254
|
-
);
|
|
259
|
+
export const BottomSheetPositioner: LynxForwardRefComponent<unknown, BottomSheetPositionerProps> =
|
|
260
|
+
withContext<unknown, BottomSheetPositionerProps>(SheetView, "positioner");
|
|
255
261
|
BottomSheetPositioner.displayName = "BottomSheetPositioner";
|
|
256
262
|
|
|
257
263
|
////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -265,32 +271,40 @@ BottomSheetPositioner.displayName = "BottomSheetPositioner";
|
|
|
265
271
|
|
|
266
272
|
export interface BottomSheetBackdropProps extends SheetBackdropProps {}
|
|
267
273
|
|
|
268
|
-
export const BottomSheetBackdrop
|
|
269
|
-
SheetBackdrop,
|
|
270
|
-
"backdrop",
|
|
271
|
-
);
|
|
274
|
+
export const BottomSheetBackdrop: LynxForwardRefComponent<unknown, BottomSheetBackdropProps> =
|
|
275
|
+
withContext<unknown, BottomSheetBackdropProps>(SheetBackdrop, "backdrop");
|
|
272
276
|
BottomSheetBackdrop.displayName = "BottomSheetBackdrop";
|
|
273
277
|
|
|
274
278
|
export interface BottomSheetContentProps extends SheetContentProps {}
|
|
275
279
|
|
|
276
|
-
export const BottomSheetContent
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
+
export const BottomSheetContent: LynxForwardRefComponent<unknown, BottomSheetContentProps> =
|
|
281
|
+
forwardRef<unknown, BottomSheetContentProps>((props, ref) => {
|
|
282
|
+
const { className, innerStyle, snapAnimation, enterAnimation, exitAnimation, ...restProps } =
|
|
283
|
+
props;
|
|
284
|
+
const classNames = useClassNames();
|
|
285
|
+
const { options } = useBottomSheetContext();
|
|
286
|
+
const { safeAreaInsetBottom } = useSafeArea();
|
|
280
287
|
|
|
281
|
-
|
|
288
|
+
const defaultAnimation = options.skipAnimation ? SKIP_ANIMATION_TRANSITION : undefined;
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
290
|
+
return (
|
|
291
|
+
<SheetContent
|
|
292
|
+
{...(ref ? { ref } : {})}
|
|
293
|
+
{...restProps}
|
|
294
|
+
className={clsx(classNames.content, className)}
|
|
295
|
+
innerStyle={{
|
|
296
|
+
display: "flex",
|
|
297
|
+
flexDirection: "column",
|
|
298
|
+
minHeight: "0",
|
|
299
|
+
paddingBottom: safeAreaInsetBottom,
|
|
300
|
+
...innerStyle,
|
|
301
|
+
}}
|
|
302
|
+
snapAnimation={snapAnimation ?? defaultAnimation ?? SEED_SNAP_ANIMATION}
|
|
303
|
+
enterAnimation={enterAnimation ?? defaultAnimation ?? SEED_ENTER_ANIMATION}
|
|
304
|
+
exitAnimation={exitAnimation ?? defaultAnimation ?? SEED_EXIT_ANIMATION}
|
|
305
|
+
/>
|
|
306
|
+
);
|
|
307
|
+
});
|
|
294
308
|
BottomSheetContent.displayName = "BottomSheetContent";
|
|
295
309
|
|
|
296
310
|
////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -301,15 +315,21 @@ export interface BottomSheetHandleProps extends SheetHandleProps {}
|
|
|
301
315
|
|
|
302
316
|
/**
|
|
303
317
|
* @remarks
|
|
304
|
-
* `SheetHandle`은 forwardRef가 아니므로 ref 시그니처는 제공하지 않는다.
|
|
305
|
-
*
|
|
306
|
-
*
|
|
318
|
+
* `SheetHandle`은 forwardRef가 아니므로 ref 시그니처는 제공하지 않는다.
|
|
319
|
+
* Lynx drag handler는 `SheetHandle`의 outer view에 붙으므로, 44x44 target
|
|
320
|
+
* area는 `SheetHandle`에 적용하고 보이는 handle은 그 중심에 배치한다.
|
|
307
321
|
*/
|
|
308
|
-
export function BottomSheetHandle(props: BottomSheetHandleProps) {
|
|
309
|
-
const { className, style, ...rest } = props;
|
|
322
|
+
export function BottomSheetHandle(props: BottomSheetHandleProps): ReactElement {
|
|
323
|
+
const { children, className, style, ...rest } = props;
|
|
310
324
|
const classNames = bottomSheetHandle();
|
|
311
325
|
|
|
312
|
-
return
|
|
326
|
+
return (
|
|
327
|
+
<SheetHandle className={classNames.touchArea} {...rest}>
|
|
328
|
+
<view className={clsx(classNames.root, className)} style={style as never}>
|
|
329
|
+
{children}
|
|
330
|
+
</view>
|
|
331
|
+
</SheetHandle>
|
|
332
|
+
);
|
|
313
333
|
}
|
|
314
334
|
BottomSheetHandle.displayName = "BottomSheetHandle";
|
|
315
335
|
|
|
@@ -323,22 +343,20 @@ BottomSheetHandle.displayName = "BottomSheetHandle";
|
|
|
323
343
|
// (lynx-ui-sheet 같은 외부 컴포넌트 감싸기엔 withContext를 그대로 사용해도 안전.)
|
|
324
344
|
////////////////////////////////////////////////////////////////////////////////////
|
|
325
345
|
|
|
326
|
-
export interface BottomSheetSlotProps {
|
|
327
|
-
children?: ReactNode;
|
|
328
|
-
className?: string;
|
|
329
|
-
style?: CSSProperties;
|
|
330
|
-
}
|
|
346
|
+
export interface BottomSheetSlotProps extends LynxStyledElementProps {}
|
|
331
347
|
|
|
332
|
-
function createViewSlot(
|
|
348
|
+
function createViewSlot(
|
|
349
|
+
slotName: keyof BottomSheetClassNames,
|
|
350
|
+
): LynxForwardRefComponent<unknown, BottomSheetSlotProps> {
|
|
333
351
|
const Slot = forwardRef<unknown, BottomSheetSlotProps>((props, ref) => {
|
|
334
352
|
const { children, className, style } = props;
|
|
335
353
|
const classNames = useClassNames();
|
|
336
354
|
|
|
337
355
|
return (
|
|
338
356
|
<view
|
|
339
|
-
{...(ref ? { ref: ref as
|
|
357
|
+
{...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
|
|
340
358
|
className={clsx(classNames[slotName], className)}
|
|
341
|
-
style={style}
|
|
359
|
+
style={style as never}
|
|
342
360
|
>
|
|
343
361
|
{children}
|
|
344
362
|
</view>
|
|
@@ -347,16 +365,18 @@ function createViewSlot(slotName: keyof BottomSheetClassNames) {
|
|
|
347
365
|
return Slot;
|
|
348
366
|
}
|
|
349
367
|
|
|
350
|
-
function createTextSlot(
|
|
368
|
+
function createTextSlot(
|
|
369
|
+
slotName: keyof BottomSheetClassNames,
|
|
370
|
+
): LynxForwardRefComponent<unknown, BottomSheetSlotProps> {
|
|
351
371
|
const Slot = forwardRef<unknown, BottomSheetSlotProps>((props, ref) => {
|
|
352
372
|
const { children, className, style } = props;
|
|
353
373
|
const classNames = useClassNames();
|
|
354
374
|
|
|
355
375
|
return (
|
|
356
376
|
<text
|
|
357
|
-
{...(ref ? { ref: ref as
|
|
377
|
+
{...(ref ? ({ ref: ref as LynxTextRef } as Record<string, unknown>) : {})}
|
|
358
378
|
className={clsx(classNames[slotName], className)}
|
|
359
|
-
style={style}
|
|
379
|
+
style={style as never}
|
|
360
380
|
>
|
|
361
381
|
{children}
|
|
362
382
|
</text>
|
|
@@ -370,7 +390,24 @@ export const BottomSheetHeader = createViewSlot("header");
|
|
|
370
390
|
BottomSheetHeader.displayName = "BottomSheetHeader";
|
|
371
391
|
|
|
372
392
|
export interface BottomSheetBodyProps extends BottomSheetSlotProps {}
|
|
373
|
-
export const BottomSheetBody =
|
|
393
|
+
export const BottomSheetBody: LynxForwardRefComponent<unknown, BottomSheetBodyProps> = forwardRef<
|
|
394
|
+
unknown,
|
|
395
|
+
BottomSheetBodyProps
|
|
396
|
+
>((props, ref) => {
|
|
397
|
+
const { children, className, style } = props;
|
|
398
|
+
const classNames = useClassNames();
|
|
399
|
+
|
|
400
|
+
return (
|
|
401
|
+
<scroll-view
|
|
402
|
+
{...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
|
|
403
|
+
scroll-y
|
|
404
|
+
className={clsx(classNames.body, className)}
|
|
405
|
+
style={style as never}
|
|
406
|
+
>
|
|
407
|
+
{children}
|
|
408
|
+
</scroll-view>
|
|
409
|
+
);
|
|
410
|
+
});
|
|
374
411
|
BottomSheetBody.displayName = "BottomSheetBody";
|
|
375
412
|
|
|
376
413
|
export interface BottomSheetFooterProps extends BottomSheetSlotProps {}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { render } from "@lynx-js/react/testing-library";
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { Text } from "../Text";
|
|
6
|
+
import { Box } from "./Box";
|
|
7
|
+
|
|
8
|
+
interface TestLynxGlobal {
|
|
9
|
+
lynx?: {
|
|
10
|
+
__globalProps?: {
|
|
11
|
+
safeAreaInsetTop?: number;
|
|
12
|
+
safeAreaInsetBottom?: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
lynxTestingEnv?: {
|
|
16
|
+
backgroundThread: {
|
|
17
|
+
globalThis: TestLynxGlobal;
|
|
18
|
+
};
|
|
19
|
+
mainThread: {
|
|
20
|
+
globalThis: TestLynxGlobal;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getRenderedRoot() {
|
|
26
|
+
const root = elementTree.root;
|
|
27
|
+
|
|
28
|
+
if (!root) {
|
|
29
|
+
throw new Error("Expected Lynx render root to exist.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return root;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function expectStyle(style: CSSStyleDeclaration, expected: Record<string, string>) {
|
|
36
|
+
for (const [key, value] of Object.entries(expected)) {
|
|
37
|
+
expect(style.getPropertyValue(key)).toBe(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function setGlobalProps(
|
|
42
|
+
globalProps: NonNullable<NonNullable<TestLynxGlobal["lynx"]>["__globalProps"]>,
|
|
43
|
+
) {
|
|
44
|
+
const lynxTestingEnv = (globalThis as TestLynxGlobal).lynxTestingEnv;
|
|
45
|
+
const globals = [
|
|
46
|
+
globalThis as TestLynxGlobal,
|
|
47
|
+
lynxTestingEnv?.backgroundThread.globalThis,
|
|
48
|
+
lynxTestingEnv?.mainThread.globalThis,
|
|
49
|
+
].filter((global): global is TestLynxGlobal => Boolean(global));
|
|
50
|
+
|
|
51
|
+
for (const global of globals) {
|
|
52
|
+
global.lynx = {
|
|
53
|
+
...global.lynx,
|
|
54
|
+
__globalProps: globalProps,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe("Box", () => {
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
setGlobalProps({});
|
|
62
|
+
vi.unstubAllGlobals();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("resolves top and bottom safe area padding from global props", () => {
|
|
66
|
+
setGlobalProps({
|
|
67
|
+
safeAreaInsetTop: 47,
|
|
68
|
+
safeAreaInsetBottom: 34,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
render(
|
|
72
|
+
<Box className="box-test" pt="safeArea" pb="safeArea">
|
|
73
|
+
<Text>Box content</Text>
|
|
74
|
+
</Box>,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
78
|
+
|
|
79
|
+
expect(box).toBeInTheDocument();
|
|
80
|
+
expectStyle((box as HTMLElement).style, {
|
|
81
|
+
"padding-top": "47px",
|
|
82
|
+
"padding-bottom": "34px",
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import * as React from "@lynx-js/react";
|
|
3
|
+
|
|
4
|
+
import type { LynxPressableProps, LynxStyledElementProps, LynxViewRef } from "../../types";
|
|
5
|
+
import { useStyleProps, type StyleProps } from "../../utils/styled";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @platform Lynx
|
|
9
|
+
*
|
|
10
|
+
* `Box`는 SEED style prop을 native `<view>`의 object style로 변환하는 편의
|
|
11
|
+
* primitive입니다. 많은 항목을 반복 렌더링하는 화면에서는 primitive 컴포넌트
|
|
12
|
+
* 렌더링과 style prop 해석 비용이 누적될 수 있습니다. 앱 코드에서는 native
|
|
13
|
+
* `<view>`/`<text>`와 Tailwind utility className을 우선 고려하세요. 패키지
|
|
14
|
+
* 컴포넌트 내부에서는 native tag와 recipe className을 사용하고, inline style은
|
|
15
|
+
* 런타임 값이 필요한 경우에만 제한적으로 사용합니다.
|
|
16
|
+
*/
|
|
17
|
+
export interface BoxProps extends StyleProps, LynxStyledElementProps, LynxPressableProps {
|
|
18
|
+
bindtouchstart?: () => void;
|
|
19
|
+
bindtouchend?: () => void;
|
|
20
|
+
bindtouchcancel?: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const Box = React.forwardRef<unknown, BoxProps>((props, ref) => {
|
|
24
|
+
const { style, restProps } = useStyleProps(props);
|
|
25
|
+
const { children, className, ...nativeProps } = restProps;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<view
|
|
29
|
+
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
30
|
+
{...nativeProps}
|
|
31
|
+
className={clsx(className)}
|
|
32
|
+
style={style}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
</view>
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
Box.displayName = "Box";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Box, type BoxProps } from "./Box";
|