@seed-design/lynx-react 0.1.1-alpha.0 → 0.2.0-alpha.2
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/components/ActionButton/ActionButton.d.ts +40 -9
- package/lib/components/ActionButton/ActionButton.d.ts.map +1 -1
- package/lib/components/ActionButton/ActionButton.jsx +132 -14
- package/lib/components/BottomSheet/BottomSheet.d.ts +92 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.jsx +178 -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 +1 -0
- package/lib/components/BottomSheet/index.d.ts +3 -0
- package/lib/components/BottomSheet/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/index.js +2 -0
- package/lib/components/Checkbox/Checkbox.d.ts +51 -0
- package/lib/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.jsx +121 -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 +1 -0
- package/lib/components/Checkbox/index.d.ts +3 -0
- package/lib/components/Checkbox/index.d.ts.map +1 -0
- package/lib/components/Checkbox/index.js +2 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts +10 -9
- package/lib/components/ProgressCircle/ProgressCircle.d.ts.map +1 -1
- package/lib/components/ProgressCircle/ProgressCircle.jsx +8 -14
- 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 +1 -0
- package/lib/components/ProgressCircle/index.d.ts +2 -1
- package/lib/components/ProgressCircle/index.d.ts.map +1 -1
- package/lib/components/ProgressCircle/index.js +2 -1
- package/lib/components/RadioGroup/RadioGroup.d.ts +50 -0
- package/lib/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.jsx +144 -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 +1 -0
- package/lib/components/RadioGroup/index.d.ts +3 -0
- package/lib/components/RadioGroup/index.d.ts.map +1 -0
- package/lib/components/RadioGroup/index.js +2 -0
- package/lib/components/Switch/Switch.d.ts +27 -0
- package/lib/components/Switch/Switch.d.ts.map +1 -0
- package/lib/components/Switch/Switch.jsx +75 -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 +1 -0
- package/lib/components/Switch/index.d.ts +3 -0
- package/lib/components/Switch/index.d.ts.map +1 -0
- package/lib/components/Switch/index.js +2 -0
- package/lib/components/TagGroup/TagGroup.d.ts +40 -0
- package/lib/components/TagGroup/TagGroup.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.jsx +54 -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 +1 -0
- package/lib/components/TagGroup/index.d.ts +3 -0
- package/lib/components/TagGroup/index.d.ts.map +1 -0
- package/lib/components/TagGroup/index.js +2 -0
- package/lib/components/index.d.ts +8 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +7 -0
- package/lib/hooks/index.d.ts +4 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/index.js +3 -0
- package/lib/hooks/use-controllable-state.d.ts +15 -0
- package/lib/hooks/use-controllable-state.d.ts.map +1 -0
- package/lib/hooks/use-controllable-state.js +27 -0
- package/lib/hooks/use-icon-color.d.ts +15 -0
- package/lib/hooks/use-icon-color.d.ts.map +1 -0
- package/lib/hooks/use-icon-color.js +37 -0
- package/lib/hooks/use-press-tap.d.ts +24 -0
- package/lib/hooks/use-press-tap.d.ts.map +1 -0
- package/lib/hooks/use-press-tap.js +35 -0
- package/lib/index.d.ts +3 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -4
- package/lib/utils/create-slot-recipe-context.d.ts +26 -0
- package/lib/utils/create-slot-recipe-context.d.ts.map +1 -0
- package/lib/utils/create-slot-recipe-context.jsx +76 -0
- package/lib/utils/get-seed-class-name.d.ts.map +1 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +4 -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 +47 -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/package.json +12 -9
- package/src/components/ActionButton/ActionButton.tsx +290 -31
- package/src/components/ActionButton/__tests__/ActionButton.test.tsx +35 -0
- package/src/components/BottomSheet/BottomSheet.namespace.ts +24 -0
- package/src/components/BottomSheet/BottomSheet.tsx +386 -0
- package/src/components/BottomSheet/__tests__/BottomSheet.test.tsx +119 -0
- package/src/components/BottomSheet/index.ts +27 -0
- package/src/components/Checkbox/Checkbox.namespace.ts +12 -0
- package/src/components/Checkbox/Checkbox.tsx +291 -0
- package/src/components/Checkbox/index.ts +14 -0
- package/src/components/ProgressCircle/ProgressCircle.namespace.ts +5 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +14 -13
- package/src/components/ProgressCircle/index.ts +9 -1
- package/src/components/RadioGroup/RadioGroup.namespace.ts +12 -0
- package/src/components/RadioGroup/RadioGroup.tsx +338 -0
- package/src/components/RadioGroup/index.ts +14 -0
- package/src/components/Switch/Switch.namespace.ts +10 -0
- package/src/components/Switch/Switch.tsx +191 -0
- package/src/components/Switch/index.ts +12 -0
- package/src/components/TagGroup/TagGroup.namespace.ts +8 -0
- package/src/components/TagGroup/TagGroup.tsx +125 -0
- package/src/components/TagGroup/index.ts +10 -0
- package/src/components/__tests__/ProgressCircle.test.ts +33 -0
- package/src/components/__tests__/exports.test.ts +38 -0
- package/src/components/__tests__/switch.test.ts +34 -0
- package/src/components/index.ts +7 -0
- package/src/hooks/__tests__/use-controllable-state.test.ts +120 -0
- package/src/hooks/__tests__/use-press-tap.test.ts +129 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/use-controllable-state.ts +38 -0
- package/src/hooks/use-icon-color.ts +51 -0
- package/src/hooks/use-press-tap.ts +54 -0
- package/src/index.ts +3 -4
- package/src/utils/__tests__/create-slot-recipe-context.test.tsx +228 -0
- package/src/utils/__tests__/split-multiple-variants-props.test.ts +61 -0
- package/src/utils/create-slot-recipe-context.tsx +147 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/resolve-recipe-token.ts +47 -0
- package/src/utils/split-multiple-variants-props.ts +59 -0
- package/lib/components/Box/Box.d.ts +0 -10
- package/lib/components/Box/Box.d.ts.map +0 -1
- package/lib/components/Box/Box.jsx +0 -19
- package/lib/components/Box/index.d.ts +0 -2
- package/lib/components/Box/index.d.ts.map +0 -1
- package/lib/components/Box/index.js +0 -1
- package/lib/components/Flex/Flex.d.ts +0 -33
- package/lib/components/Flex/Flex.d.ts.map +0 -1
- package/lib/components/Flex/Flex.jsx +0 -7
- package/lib/components/Flex/index.d.ts +0 -2
- package/lib/components/Flex/index.d.ts.map +0 -1
- package/lib/components/Flex/index.js +0 -1
- package/lib/components/List/List.d.ts +0 -9
- package/lib/components/List/List.d.ts.map +0 -1
- package/lib/components/List/List.jsx +0 -17
- package/lib/components/List/index.d.ts +0 -2
- package/lib/components/List/index.d.ts.map +0 -1
- package/lib/components/List/index.js +0 -1
- package/lib/components/ListItem/ListItem.d.ts +0 -8
- package/lib/components/ListItem/ListItem.d.ts.map +0 -1
- package/lib/components/ListItem/ListItem.jsx +0 -11
- package/lib/components/ListItem/index.d.ts +0 -2
- package/lib/components/ListItem/index.d.ts.map +0 -1
- package/lib/components/ListItem/index.js +0 -1
- package/lib/components/ScrollView/ScrollView.d.ts +0 -9
- package/lib/components/ScrollView/ScrollView.d.ts.map +0 -1
- package/lib/components/ScrollView/ScrollView.jsx +0 -17
- package/lib/components/ScrollView/index.d.ts +0 -2
- package/lib/components/ScrollView/index.d.ts.map +0 -1
- package/lib/components/ScrollView/index.js +0 -1
- package/lib/components/Stack/Stack.d.ts +0 -6
- package/lib/components/Stack/Stack.d.ts.map +0 -1
- package/lib/components/Stack/Stack.jsx +0 -10
- package/lib/components/Stack/index.d.ts +0 -2
- package/lib/components/Stack/index.d.ts.map +0 -1
- package/lib/components/Stack/index.js +0 -1
- package/lib/components/Text/Text.d.ts +0 -30
- package/lib/components/Text/Text.d.ts.map +0 -1
- package/lib/components/Text/Text.jsx +0 -49
- package/lib/components/Text/index.d.ts +0 -2
- package/lib/components/Text/index.d.ts.map +0 -1
- package/lib/components/Text/index.js +0 -1
- package/lib/get-seed-class-name.d.ts.map +0 -1
- package/lib/utils/dynamic-style.d.ts +0 -13
- package/lib/utils/dynamic-style.d.ts.map +0 -1
- package/lib/utils/dynamic-style.js +0 -26
- package/lib/utils/styled.d.ts +0 -120
- package/lib/utils/styled.d.ts.map +0 -1
- package/lib/utils/styled.jsx +0 -131
- package/src/utils/dynamic-style.ts +0 -26
- /package/lib/{get-seed-class-name.d.ts → utils/get-seed-class-name.d.ts} +0 -0
- /package/lib/{get-seed-class-name.js → utils/get-seed-class-name.js} +0 -0
- /package/src/{get-seed-class-name.ts → utils/get-seed-class-name.ts} +0 -0
|
@@ -1,24 +1,55 @@
|
|
|
1
1
|
import type { ActionButtonVariantProps } from "@seed-design/lynx-css/recipes/action-button";
|
|
2
|
+
import type { MainThread } from "@lynx-js/types";
|
|
2
3
|
import * as React from "react";
|
|
4
|
+
import { type ReactElement } from "react";
|
|
5
|
+
type IconElementProps = {
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
ref?: React.Ref<MainThread.Element>;
|
|
9
|
+
};
|
|
3
10
|
/**
|
|
4
11
|
* @platform Lynx
|
|
5
12
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
*
|
|
13
|
+
* 웹 대비 차이:
|
|
14
|
+
* - 아이콘 전달 방식: 웹의 `<ActionButton.PrefixIcon svg={...} />` 가 아니라 `prefixIcon` /
|
|
15
|
+
* `suffixIcon` / `icon` prop 으로 ReactElement 를 직접 넘긴다. Lynx `<text>` 가 flex
|
|
16
|
+
* 컨테이너가 아니라 children 전체를 text 로 감싸면 아이콘이 flex item 이 안 되기 때문.
|
|
17
|
+
* - 미지원 prop: `color`, `fontWeight`, `bleedX`, `bleedY` (CSS variable 동적 주입 제한)
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* import IconPlusFill from "@karrotmarket/lynx-monochrome-icon/IconPlusFill";
|
|
21
|
+
* import IconChevronDownFill from "@karrotmarket/lynx-monochrome-icon/IconChevronDownFill";
|
|
22
|
+
*
|
|
23
|
+
* // withText (기본)
|
|
24
|
+
* <ActionButton
|
|
25
|
+
* variant="brandSolid"
|
|
26
|
+
* prefixIcon={<IconPlusFill />}
|
|
27
|
+
* suffixIcon={<IconChevronDownFill />}
|
|
28
|
+
* >
|
|
29
|
+
* 라벨
|
|
30
|
+
* </ActionButton>
|
|
10
31
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
32
|
+
* // iconOnly — `icon` prop 과 `aria-label` 필수
|
|
33
|
+
* <ActionButton
|
|
34
|
+
* layout="iconOnly"
|
|
35
|
+
* variant="neutralSolid"
|
|
36
|
+
* icon={<IconPlusFill />}
|
|
37
|
+
* aria-label="추가"
|
|
38
|
+
* />
|
|
39
|
+
* ```
|
|
14
40
|
*/
|
|
15
|
-
export interface ActionButtonProps extends Omit<ActionButtonVariantProps, "
|
|
41
|
+
export interface ActionButtonProps extends Omit<ActionButtonVariantProps, "layout" | "pressed"> {
|
|
16
42
|
children?: React.ReactNode;
|
|
17
|
-
disabled?: boolean;
|
|
18
43
|
className?: string;
|
|
19
44
|
flexGrow?: number;
|
|
45
|
+
layout?: "withText" | "iconOnly";
|
|
46
|
+
icon?: ReactElement<IconElementProps>;
|
|
47
|
+
prefixIcon?: ReactElement<IconElementProps>;
|
|
48
|
+
suffixIcon?: ReactElement<IconElementProps>;
|
|
49
|
+
"aria-label"?: string;
|
|
20
50
|
bindtap?: () => void;
|
|
21
51
|
"main-thread:bindtap"?: () => void;
|
|
22
52
|
}
|
|
23
53
|
export declare const ActionButton: React.ForwardRefExoticComponent<ActionButtonProps & React.RefAttributes<unknown>>;
|
|
54
|
+
export {};
|
|
24
55
|
//# sourceMappingURL=ActionButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionButton.d.ts","sourceRoot":"","sources":["../../../src/components/ActionButton/ActionButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAE5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ActionButton.d.ts","sourceRoot":"","sources":["../../../src/components/ActionButton/ActionButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAE5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAsBjF,KAAK,gBAAgB,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;CACrC,CAAC;AAuLF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7F,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,YAAY,mFA4DvB,CAAC"}
|
|
@@ -1,21 +1,139 @@
|
|
|
1
1
|
import { actionButton } from "@seed-design/lynx-css/recipes/action-button";
|
|
2
|
+
import { actionButton as actionButtonVars } from "@seed-design/lynx-css/vars/component";
|
|
2
3
|
import clsx from "clsx";
|
|
3
4
|
import * as React from "react";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
import { cloneElement, isValidElement, useMemo } from "react";
|
|
6
|
+
import { useIconColor } from "../../hooks/use-icon-color";
|
|
7
|
+
import { usePressTap } from "../../hooks/use-press-tap";
|
|
8
|
+
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
|
|
9
|
+
import { capitalize, resolveRecipeToken } from "../../utils/resolve-recipe-token";
|
|
10
|
+
import { ProgressCircleRange, ProgressCircleRoot, } from "../ProgressCircle";
|
|
11
|
+
// Root/TextSlot 은 `withProvider("view", ...)` / `withContext("text", ...)` 를 쓰지 않는다.
|
|
12
|
+
// intrinsic string 인자는 `React.createElement("view", ...)` 로 컴파일되어 Lynx 컴파일러의
|
|
13
|
+
// 리터럴 JSX 정적 분석을 우회하고 `BackgroundSnapshot not found: view` 런타임 에러를 유발한다.
|
|
14
|
+
// (자세한 내용: `packages/lynx-react/AGENTS.md` 의 "Native tag literal JSX constraint" 섹션)
|
|
15
|
+
const { ClassNamesProvider, useClassNames, PropsProvider, useProps } = createSlotRecipeContext(actionButton);
|
|
16
|
+
const progressCircleSizeMap = {
|
|
17
|
+
xsmall: "14",
|
|
18
|
+
small: "14",
|
|
19
|
+
medium: "16",
|
|
20
|
+
large: "18",
|
|
21
|
+
};
|
|
22
|
+
const ActionButtonRoot = React.forwardRef((innerProps, ref) => {
|
|
23
|
+
const props = { layout: "withText", ...innerProps };
|
|
24
|
+
const [variantProps, otherProps] = actionButton.splitVariantProps(props);
|
|
25
|
+
const classNames = actionButton(variantProps);
|
|
26
|
+
const { className: userClassName, children, ...rest } = otherProps;
|
|
27
|
+
const propsForContext = useMemo(() => variantProps, [
|
|
28
|
+
variantProps.variant,
|
|
29
|
+
variantProps.size,
|
|
30
|
+
variantProps.layout,
|
|
31
|
+
variantProps.pressed,
|
|
32
|
+
variantProps.disabled,
|
|
33
|
+
variantProps.loading,
|
|
34
|
+
]);
|
|
35
|
+
return (<ClassNamesProvider value={classNames}>
|
|
36
|
+
<PropsProvider value={propsForContext}>
|
|
37
|
+
<view {...(ref ? { ref: ref } : {})} {...rest} className={clsx(classNames.root, userClassName)}>
|
|
38
|
+
{children}
|
|
39
|
+
</view>
|
|
40
|
+
</PropsProvider>
|
|
41
|
+
</ClassNamesProvider>);
|
|
42
|
+
});
|
|
43
|
+
ActionButtonRoot.displayName = "ActionButtonRoot";
|
|
44
|
+
const ActionButtonTextSlot = React.forwardRef((props, ref) => {
|
|
45
|
+
const { children, className: userClassName, ...rest } = props;
|
|
46
|
+
const classNames = useClassNames();
|
|
47
|
+
return (<text {...(ref ? { ref: ref } : {})} {...rest} className={clsx(classNames.text, userClassName)}>
|
|
48
|
+
{children}
|
|
49
|
+
</text>);
|
|
50
|
+
});
|
|
51
|
+
ActionButtonTextSlot.displayName = "ActionButtonTextSlot";
|
|
52
|
+
/**
|
|
53
|
+
* rootage vars 에서 현재 variant/size/layout 조합의 slot `size` 토큰
|
|
54
|
+
* (예: `"var(--seed-dimension-x4)"`) 을 꺼낸다. 아이콘 컴포넌트가 inline
|
|
55
|
+
* `style={{ width, height }}` 를 박기 때문에 style prop 으로 덮어 씌워야 recipe 사이즈가 적용된다.
|
|
56
|
+
*/
|
|
57
|
+
function resolveIconSize(variantProps, slot) {
|
|
58
|
+
const size = variantProps?.size ?? "medium";
|
|
59
|
+
// `icon` slot is only rendered under `layout="iconOnly"` and keyed at
|
|
60
|
+
// `sizeXxxLayoutIconOnly.enabled.icon.size`. prefixIcon/suffixIcon follow
|
|
61
|
+
// the current `layout` (`withText` by default) path.
|
|
62
|
+
const layout = slot === "icon" ? "iconOnly" : (variantProps?.layout ?? "withText");
|
|
63
|
+
return resolveRecipeToken(actionButtonVars, [
|
|
64
|
+
`size${capitalize(size)}Layout${capitalize(layout)}`,
|
|
65
|
+
"enabled",
|
|
66
|
+
slot,
|
|
67
|
+
"size",
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `prefixIcon` / `suffixIcon` prop 으로 전달된 아이콘 element 에 slot className +
|
|
72
|
+
* size(style) + main-thread tint-color ref 를 주입한다.
|
|
73
|
+
*/
|
|
74
|
+
function ActionButtonIconSlot({ icon, slot, }) {
|
|
75
|
+
const classNames = useClassNames();
|
|
76
|
+
const variantProps = useProps();
|
|
77
|
+
const { ref } = useIconColor([
|
|
78
|
+
variantProps?.variant ?? null,
|
|
79
|
+
variantProps?.disabled ?? false,
|
|
80
|
+
variantProps?.loading ?? false,
|
|
81
|
+
]);
|
|
82
|
+
const sizeVar = resolveIconSize(variantProps, slot);
|
|
83
|
+
const childProps = icon.props;
|
|
84
|
+
return cloneElement(icon, {
|
|
85
|
+
className: clsx(classNames[slot], childProps.className),
|
|
86
|
+
style: sizeVar != null ? { width: sizeVar, height: sizeVar, ...childProps.style } : childProps.style,
|
|
87
|
+
ref: ref,
|
|
12
88
|
});
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
}
|
|
18
|
-
|
|
89
|
+
}
|
|
90
|
+
function ActionButtonContent({ children, isIconOnly, icon, prefixIcon, suffixIcon, }) {
|
|
91
|
+
if (isIconOnly) {
|
|
92
|
+
return icon != null && isValidElement(icon) ? (<ActionButtonIconSlot icon={icon} slot="icon"/>) : null;
|
|
93
|
+
}
|
|
94
|
+
return (<>
|
|
95
|
+
{prefixIcon != null && isValidElement(prefixIcon) ? (<ActionButtonIconSlot icon={prefixIcon} slot="prefixIcon"/>) : null}
|
|
96
|
+
<ActionButtonTextSlot>{children}</ActionButtonTextSlot>
|
|
97
|
+
{suffixIcon != null && isValidElement(suffixIcon) ? (<ActionButtonIconSlot icon={suffixIcon} slot="suffixIcon"/>) : null}
|
|
98
|
+
</>);
|
|
99
|
+
}
|
|
100
|
+
function ActionButtonLoadingContent(props) {
|
|
101
|
+
const classNames = useClassNames();
|
|
102
|
+
return (<view className={classNames.content}>
|
|
103
|
+
<ActionButtonContent {...props}/>
|
|
19
104
|
</view>);
|
|
105
|
+
}
|
|
106
|
+
function ActionButtonLoadingIndicator({ size }) {
|
|
107
|
+
const classNames = useClassNames();
|
|
108
|
+
return (<view className={classNames.loadingIndicator}>
|
|
109
|
+
<ProgressCircleRoot size={progressCircleSizeMap[size]} tone="inherit">
|
|
110
|
+
<ProgressCircleRange />
|
|
111
|
+
</ProgressCircleRoot>
|
|
112
|
+
</view>);
|
|
113
|
+
}
|
|
114
|
+
export const ActionButton = React.forwardRef((props, ref) => {
|
|
115
|
+
const { children, flexGrow, layout, icon, prefixIcon, suffixIcon, bindtap, "main-thread:bindtap": mainThreadBindtap, ...variantAndRest } = props;
|
|
116
|
+
const { disabled = false, loading = false } = variantAndRest;
|
|
117
|
+
const isInteractive = !disabled && !loading;
|
|
118
|
+
const isIconOnly = layout === "iconOnly";
|
|
119
|
+
const size = variantAndRest.size ?? "medium";
|
|
120
|
+
if (process.env.NODE_ENV !== "production" && isIconOnly && !props["aria-label"]) {
|
|
121
|
+
console.warn('ActionButton: `layout="iconOnly"` requires `aria-label` for accessibility.');
|
|
122
|
+
}
|
|
123
|
+
const { pressed, ...pressTapHandlers } = usePressTap({
|
|
124
|
+
disabled: !isInteractive,
|
|
125
|
+
onTap: bindtap,
|
|
126
|
+
mainThreadOnTap: mainThreadBindtap,
|
|
127
|
+
});
|
|
128
|
+
return (<ActionButtonRoot {...variantAndRest} layout={layout} pressed={pressed} ref={ref} style={flexGrow != null ? { flexGrow } : undefined} {...pressTapHandlers}>
|
|
129
|
+
{loading ? (<>
|
|
130
|
+
<ActionButtonLoadingIndicator size={size}/>
|
|
131
|
+
<ActionButtonLoadingContent isIconOnly={isIconOnly} icon={icon} prefixIcon={prefixIcon} suffixIcon={suffixIcon}>
|
|
132
|
+
{children}
|
|
133
|
+
</ActionButtonLoadingContent>
|
|
134
|
+
</>) : (<ActionButtonContent isIconOnly={isIconOnly} icon={icon} prefixIcon={prefixIcon} suffixIcon={suffixIcon}>
|
|
135
|
+
{children}
|
|
136
|
+
</ActionButtonContent>)}
|
|
137
|
+
</ActionButtonRoot>);
|
|
20
138
|
});
|
|
21
139
|
ActionButton.displayName = "ActionButton";
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type BottomSheetVariantProps } from "@seed-design/lynx-css/recipes/bottom-sheet";
|
|
2
|
+
import { type SheetBackdropProps, type SheetContentProps, type SheetHandleProps, type SheetRootProps, type SheetRootRef, type SheetViewProps } from "@lynx-js/lynx-ui-sheet";
|
|
3
|
+
import { type ReactNode } from "@lynx-js/react";
|
|
4
|
+
import type { CSSProperties } from "react";
|
|
5
|
+
export type BottomSheetRootRef = SheetRootRef;
|
|
6
|
+
export interface BottomSheetRootProps extends BottomSheetVariantProps, Omit<SheetRootProps, "show" | "defaultShow" | "onShowChange"> {
|
|
7
|
+
/**
|
|
8
|
+
* Whether the sheet is open (controlled mode).
|
|
9
|
+
* Internally mapped to `show` of `@lynx-js/lynx-ui-sheet`.
|
|
10
|
+
*/
|
|
11
|
+
open?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the sheet is open by default (uncontrolled mode).
|
|
14
|
+
* Internally mapped to `defaultShow`.
|
|
15
|
+
* @defaultValue false
|
|
16
|
+
*/
|
|
17
|
+
defaultOpen?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Called when the sheet's open state is about to change.
|
|
20
|
+
* Internally mapped to `onShowChange`.
|
|
21
|
+
*/
|
|
22
|
+
onOpenChange?: (open: boolean) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @platform Lynx — wraps `@lynx-js/lynx-ui-sheet`
|
|
26
|
+
*
|
|
27
|
+
* 웹 대비 미지원 기능:
|
|
28
|
+
* - `lazyMount`, `unmountOnExit`: lynx-ui-sheet의 `forceMount`로 대체
|
|
29
|
+
* - `BottomSheetPositioner`: lynx-ui-sheet의 `SheetView`가 자동 처리하므로 별도 슬롯 없음
|
|
30
|
+
* - `BottomSheetCloseButton`: Tier B (Lynx SVG 지원 후 추가 예정)
|
|
31
|
+
* - `BottomSheetTrigger`의 `asChild`: 미지원 (기본 `<view>`만)
|
|
32
|
+
*/
|
|
33
|
+
export declare const BottomSheetRoot: import("react").ForwardRefExoticComponent<BottomSheetRootProps & import("react").RefAttributes<SheetRootRef>>;
|
|
34
|
+
export interface BottomSheetTriggerProps {
|
|
35
|
+
children?: ReactNode;
|
|
36
|
+
className?: string;
|
|
37
|
+
style?: CSSProperties;
|
|
38
|
+
bindtap?: () => void;
|
|
39
|
+
}
|
|
40
|
+
export declare const BottomSheetTrigger: import("react").ForwardRefExoticComponent<BottomSheetTriggerProps & import("react").RefAttributes<unknown>>;
|
|
41
|
+
export interface BottomSheetPositionerProps extends SheetViewProps {
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Backdrop/Content는 반드시 `BottomSheetPositioner` 안에 배치해야 한다.
|
|
45
|
+
*
|
|
46
|
+
* `SheetView`는 `mounted || forceMount` 조건으로 자식을 gating하므로 시트가 처음
|
|
47
|
+
* 열리기 전까지는 SheetBackdrop/SheetContent가 마운트되지 않아 motion value
|
|
48
|
+
* 초기화 레이스를 피할 수 있다. Trigger는 이 컴포넌트 밖에 두어야 탭 가능하다.
|
|
49
|
+
*
|
|
50
|
+
* recipe의 `positioner` slot className을 자동 적용해 `position: fixed` + 전체
|
|
51
|
+
* 뷰포트 커버 레이아웃을 보장한다.
|
|
52
|
+
*/
|
|
53
|
+
export declare const BottomSheetPositioner: import("react").ForwardRefExoticComponent<BottomSheetPositionerProps & import("react").RefAttributes<unknown>>;
|
|
54
|
+
export interface BottomSheetBackdropProps extends SheetBackdropProps {
|
|
55
|
+
}
|
|
56
|
+
export declare const BottomSheetBackdrop: import("react").ForwardRefExoticComponent<BottomSheetBackdropProps & import("react").RefAttributes<unknown>>;
|
|
57
|
+
export interface BottomSheetContentProps extends SheetContentProps {
|
|
58
|
+
}
|
|
59
|
+
export declare const BottomSheetContent: import("react").ForwardRefExoticComponent<BottomSheetContentProps & import("react").RefAttributes<unknown>>;
|
|
60
|
+
export interface BottomSheetHandleProps extends SheetHandleProps {
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* @remarks
|
|
64
|
+
* `SheetHandle`은 forwardRef가 아니므로 ref 시그니처는 제공하지 않는다. touchArea 슬롯은
|
|
65
|
+
* `SheetHandle` JSX가 정적으로 children을 받지 않는 구조라 적용하지 않는다 (Lynx
|
|
66
|
+
* BackgroundSnapshot이 정적 slot 외의 동적 children 삽입을 허용하지 않음).
|
|
67
|
+
*/
|
|
68
|
+
export declare function BottomSheetHandle(props: BottomSheetHandleProps): import("react").JSX.Element;
|
|
69
|
+
export declare namespace BottomSheetHandle {
|
|
70
|
+
var displayName: string;
|
|
71
|
+
}
|
|
72
|
+
export interface BottomSheetSlotProps {
|
|
73
|
+
children?: ReactNode;
|
|
74
|
+
className?: string;
|
|
75
|
+
style?: CSSProperties;
|
|
76
|
+
}
|
|
77
|
+
export interface BottomSheetHeaderProps extends BottomSheetSlotProps {
|
|
78
|
+
}
|
|
79
|
+
export declare const BottomSheetHeader: import("react").ForwardRefExoticComponent<BottomSheetSlotProps & import("react").RefAttributes<unknown>>;
|
|
80
|
+
export interface BottomSheetBodyProps extends BottomSheetSlotProps {
|
|
81
|
+
}
|
|
82
|
+
export declare const BottomSheetBody: import("react").ForwardRefExoticComponent<BottomSheetSlotProps & import("react").RefAttributes<unknown>>;
|
|
83
|
+
export interface BottomSheetFooterProps extends BottomSheetSlotProps {
|
|
84
|
+
}
|
|
85
|
+
export declare const BottomSheetFooter: import("react").ForwardRefExoticComponent<BottomSheetSlotProps & import("react").RefAttributes<unknown>>;
|
|
86
|
+
export interface BottomSheetTitleProps extends BottomSheetSlotProps {
|
|
87
|
+
}
|
|
88
|
+
export declare const BottomSheetTitle: import("react").ForwardRefExoticComponent<BottomSheetSlotProps & import("react").RefAttributes<unknown>>;
|
|
89
|
+
export interface BottomSheetDescriptionProps extends BottomSheetSlotProps {
|
|
90
|
+
}
|
|
91
|
+
export declare const BottomSheetDescription: import("react").ForwardRefExoticComponent<BottomSheetSlotProps & import("react").RefAttributes<unknown>>;
|
|
92
|
+
//# sourceMappingURL=BottomSheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/components/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAOL,KAAK,SAAS,EAGf,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAwE3C,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAE9C,MAAM,WAAW,oBACf,SAAQ,uBAAuB,EAC7B,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;IAC/D;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,+GAuD3B,CAAC;AAOF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB,6GA4B7B,CAAC;AAOH,MAAM,WAAW,0BAA2B,SAAQ,cAAc;CAAG;AAErE;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,gHAGjC,CAAC;AAYF,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB;CAAG;AAEvE,eAAO,MAAM,mBAAmB,8GAG/B,CAAC;AAGF,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;CAAG;AAErE,eAAO,MAAM,kBAAkB,6GAiB7B,CAAC;AAOH,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;CAAG;AAEnE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BAK9D;yBALe,iBAAiB;;;AAkBjC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAsCD,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;CAAG;AACvE,eAAO,MAAM,iBAAiB,0GAA2B,CAAC;AAG1D,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;CAAG;AACrE,eAAO,MAAM,eAAe,0GAAyB,CAAC;AAGtD,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;CAAG;AACvE,eAAO,MAAM,iBAAiB,0GAA2B,CAAC;AAG1D,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;CAAG;AACtE,eAAO,MAAM,gBAAgB,0GAA0B,CAAC;AAGxD,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;CAAG;AAC5E,eAAO,MAAM,sBAAsB,0GAAgC,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { bottomSheet, } from "@seed-design/lynx-css/recipes/bottom-sheet";
|
|
2
|
+
import { bottomSheetHandle } from "@seed-design/lynx-css/recipes/bottom-sheet-handle";
|
|
3
|
+
import { SheetBackdrop, SheetContent, SheetHandle, SheetRoot, SheetView, } from "@lynx-js/lynx-ui-sheet";
|
|
4
|
+
import { createContext, forwardRef, useCallback, useContext, useMemo, useRef, } from "@lynx-js/react";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
|
|
7
|
+
const { ClassNamesProvider, useClassNames, withContext } = createSlotRecipeContext(bottomSheet);
|
|
8
|
+
const DEFAULT_SNAP_POINTS = ["fit"];
|
|
9
|
+
const SKIP_ANIMATION_TRANSITION = {
|
|
10
|
+
type: "tween",
|
|
11
|
+
duration: 0,
|
|
12
|
+
};
|
|
13
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
// SEED Transitions — 웹 SEED BottomSheet (recipe: d6/d4 + enter-expressive/enter/exit)
|
|
15
|
+
// 의 감각을 lynx-ui-sheet의 spring으로 근사한 기본값.
|
|
16
|
+
//
|
|
17
|
+
// spring을 사용하는 이유:
|
|
18
|
+
// - lynx-ui-sheet 내장 main-thread 구현이라 stiffness/damping/mass만 JSON 직렬화로
|
|
19
|
+
// 안전 전달 (ease 함수 크로스스레드 문제 없음)
|
|
20
|
+
// - lynx-ui 공식 예제도 spring 기본 — 런타임 안정성 검증됨
|
|
21
|
+
//
|
|
22
|
+
// 튜닝 기준 (300ms 수준의 빠르고 약간의 탄성감):
|
|
23
|
+
// - 웹 d6 + enter-expressive ≈ stiffness 400, damping 35 (snap 드래그 settle)
|
|
24
|
+
// - 웹 d6 + enter ≈ stiffness 350, damping 32 (첫 open)
|
|
25
|
+
// - 웹 d4 + exit ≈ stiffness 400, damping 40 (close, critically damped)
|
|
26
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
27
|
+
const SEED_SNAP_ANIMATION = {
|
|
28
|
+
type: "spring",
|
|
29
|
+
stiffness: 400,
|
|
30
|
+
damping: 35,
|
|
31
|
+
};
|
|
32
|
+
const SEED_ENTER_ANIMATION = {
|
|
33
|
+
type: "spring",
|
|
34
|
+
stiffness: 350,
|
|
35
|
+
damping: 32,
|
|
36
|
+
};
|
|
37
|
+
const SEED_EXIT_ANIMATION = {
|
|
38
|
+
type: "spring",
|
|
39
|
+
stiffness: 400,
|
|
40
|
+
damping: 40,
|
|
41
|
+
};
|
|
42
|
+
const BottomSheetContext = createContext(null);
|
|
43
|
+
function useBottomSheetContext() {
|
|
44
|
+
const ctx = useContext(BottomSheetContext);
|
|
45
|
+
if (!ctx) {
|
|
46
|
+
throw new Error("BottomSheet compound components must be used within BottomSheetRoot");
|
|
47
|
+
}
|
|
48
|
+
return ctx;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @platform Lynx — wraps `@lynx-js/lynx-ui-sheet`
|
|
52
|
+
*
|
|
53
|
+
* 웹 대비 미지원 기능:
|
|
54
|
+
* - `lazyMount`, `unmountOnExit`: lynx-ui-sheet의 `forceMount`로 대체
|
|
55
|
+
* - `BottomSheetPositioner`: lynx-ui-sheet의 `SheetView`가 자동 처리하므로 별도 슬롯 없음
|
|
56
|
+
* - `BottomSheetCloseButton`: Tier B (Lynx SVG 지원 후 추가 예정)
|
|
57
|
+
* - `BottomSheetTrigger`의 `asChild`: 미지원 (기본 `<view>`만)
|
|
58
|
+
*/
|
|
59
|
+
export const BottomSheetRoot = forwardRef((props, forwardedRef) => {
|
|
60
|
+
const [variantProps, restProps] = bottomSheet.splitVariantProps(props);
|
|
61
|
+
const { open, defaultOpen, onOpenChange, snapPoints, children, ...nativeProps } = restProps;
|
|
62
|
+
const { headerAlign, skipAnimation } = variantProps;
|
|
63
|
+
const internalRef = useRef(null);
|
|
64
|
+
// `SheetRoot`에 직접 ref를 넘겨 Trigger 컨텍스트와 외부 ref에 같은 인스턴스를 동기화한다.
|
|
65
|
+
// `useImperativeHandle([])`은 마운트 시점 값(null)을 고정시키는 함정이 있어 사용하지 않는다.
|
|
66
|
+
const mergedRef = useCallback((value) => {
|
|
67
|
+
internalRef.current = value;
|
|
68
|
+
if (typeof forwardedRef === "function") {
|
|
69
|
+
forwardedRef(value);
|
|
70
|
+
}
|
|
71
|
+
else if (forwardedRef) {
|
|
72
|
+
forwardedRef.current = value;
|
|
73
|
+
}
|
|
74
|
+
}, [forwardedRef]);
|
|
75
|
+
const classNames = useMemo(() => bottomSheet(variantProps),
|
|
76
|
+
// variantProps 객체는 매 렌더 새로 생성되므로 개별 variant 값으로 의존성을 고정한다.
|
|
77
|
+
[headerAlign, skipAnimation]);
|
|
78
|
+
const shouldSkipAnimation = skipAnimation === true;
|
|
79
|
+
const context = useMemo(() => ({
|
|
80
|
+
rootRef: internalRef,
|
|
81
|
+
options: {
|
|
82
|
+
skipAnimation: shouldSkipAnimation,
|
|
83
|
+
},
|
|
84
|
+
}), [shouldSkipAnimation]);
|
|
85
|
+
return (<BottomSheetContext.Provider value={context}>
|
|
86
|
+
<ClassNamesProvider value={classNames}>
|
|
87
|
+
<SheetRoot ref={mergedRef} show={open} defaultShow={defaultOpen} onShowChange={onOpenChange} snapPoints={snapPoints ?? DEFAULT_SNAP_POINTS} {...nativeProps}>
|
|
88
|
+
{children}
|
|
89
|
+
</SheetRoot>
|
|
90
|
+
</ClassNamesProvider>
|
|
91
|
+
</BottomSheetContext.Provider>);
|
|
92
|
+
});
|
|
93
|
+
BottomSheetRoot.displayName = "BottomSheetRoot";
|
|
94
|
+
export const BottomSheetTrigger = forwardRef((props, ref) => {
|
|
95
|
+
const { children, className, style, bindtap: userBindtap } = props;
|
|
96
|
+
const { rootRef, options } = useBottomSheetContext();
|
|
97
|
+
// `bindtap`을 직접 prop으로 쓰면 React DOM `<view>` 타입(SVG)이 적용되어 TS가 거부한다.
|
|
98
|
+
// Lynx JSX 런타임은 이 prop을 올바르게 처리하므로 spread로 우회한다 (ActionButton과 동일 패턴).
|
|
99
|
+
const handlers = {
|
|
100
|
+
bindtap: () => {
|
|
101
|
+
if (options.skipAnimation) {
|
|
102
|
+
rootRef.current?.open({ animate: false });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
rootRef.current?.open();
|
|
106
|
+
}
|
|
107
|
+
userBindtap?.();
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
return (<view {...(ref ? { ref: ref } : {})} {...handlers} className={className} style={style}>
|
|
111
|
+
{children}
|
|
112
|
+
</view>);
|
|
113
|
+
});
|
|
114
|
+
BottomSheetTrigger.displayName = "BottomSheetTrigger";
|
|
115
|
+
/**
|
|
116
|
+
* Backdrop/Content는 반드시 `BottomSheetPositioner` 안에 배치해야 한다.
|
|
117
|
+
*
|
|
118
|
+
* `SheetView`는 `mounted || forceMount` 조건으로 자식을 gating하므로 시트가 처음
|
|
119
|
+
* 열리기 전까지는 SheetBackdrop/SheetContent가 마운트되지 않아 motion value
|
|
120
|
+
* 초기화 레이스를 피할 수 있다. Trigger는 이 컴포넌트 밖에 두어야 탭 가능하다.
|
|
121
|
+
*
|
|
122
|
+
* recipe의 `positioner` slot className을 자동 적용해 `position: fixed` + 전체
|
|
123
|
+
* 뷰포트 커버 레이아웃을 보장한다.
|
|
124
|
+
*/
|
|
125
|
+
export const BottomSheetPositioner = withContext(SheetView, "positioner");
|
|
126
|
+
BottomSheetPositioner.displayName = "BottomSheetPositioner";
|
|
127
|
+
export const BottomSheetBackdrop = withContext(SheetBackdrop, "backdrop");
|
|
128
|
+
BottomSheetBackdrop.displayName = "BottomSheetBackdrop";
|
|
129
|
+
export const BottomSheetContent = forwardRef((props, ref) => {
|
|
130
|
+
const { className, snapAnimation, enterAnimation, exitAnimation, ...restProps } = props;
|
|
131
|
+
const classNames = useClassNames();
|
|
132
|
+
const { options } = useBottomSheetContext();
|
|
133
|
+
const defaultAnimation = options.skipAnimation ? SKIP_ANIMATION_TRANSITION : undefined;
|
|
134
|
+
return (<SheetContent {...(ref ? { ref } : {})} {...restProps} className={clsx(classNames.content, className)} snapAnimation={snapAnimation ?? defaultAnimation ?? SEED_SNAP_ANIMATION} enterAnimation={enterAnimation ?? defaultAnimation ?? SEED_ENTER_ANIMATION} exitAnimation={exitAnimation ?? defaultAnimation ?? SEED_EXIT_ANIMATION}/>);
|
|
135
|
+
});
|
|
136
|
+
BottomSheetContent.displayName = "BottomSheetContent";
|
|
137
|
+
/**
|
|
138
|
+
* @remarks
|
|
139
|
+
* `SheetHandle`은 forwardRef가 아니므로 ref 시그니처는 제공하지 않는다. touchArea 슬롯은
|
|
140
|
+
* `SheetHandle` JSX가 정적으로 children을 받지 않는 구조라 적용하지 않는다 (Lynx
|
|
141
|
+
* BackgroundSnapshot이 정적 slot 외의 동적 children 삽입을 허용하지 않음).
|
|
142
|
+
*/
|
|
143
|
+
export function BottomSheetHandle(props) {
|
|
144
|
+
const { className, style, ...rest } = props;
|
|
145
|
+
const classNames = bottomSheetHandle();
|
|
146
|
+
return <SheetHandle className={clsx(classNames.root, className)} style={style} {...rest}/>;
|
|
147
|
+
}
|
|
148
|
+
BottomSheetHandle.displayName = "BottomSheetHandle";
|
|
149
|
+
function createViewSlot(slotName) {
|
|
150
|
+
const Slot = forwardRef((props, ref) => {
|
|
151
|
+
const { children, className, style } = props;
|
|
152
|
+
const classNames = useClassNames();
|
|
153
|
+
return (<view {...(ref ? { ref: ref } : {})} className={clsx(classNames[slotName], className)} style={style}>
|
|
154
|
+
{children}
|
|
155
|
+
</view>);
|
|
156
|
+
});
|
|
157
|
+
return Slot;
|
|
158
|
+
}
|
|
159
|
+
function createTextSlot(slotName) {
|
|
160
|
+
const Slot = forwardRef((props, ref) => {
|
|
161
|
+
const { children, className, style } = props;
|
|
162
|
+
const classNames = useClassNames();
|
|
163
|
+
return (<text {...(ref ? { ref: ref } : {})} className={clsx(classNames[slotName], className)} style={style}>
|
|
164
|
+
{children}
|
|
165
|
+
</text>);
|
|
166
|
+
});
|
|
167
|
+
return Slot;
|
|
168
|
+
}
|
|
169
|
+
export const BottomSheetHeader = createViewSlot("header");
|
|
170
|
+
BottomSheetHeader.displayName = "BottomSheetHeader";
|
|
171
|
+
export const BottomSheetBody = createViewSlot("body");
|
|
172
|
+
BottomSheetBody.displayName = "BottomSheetBody";
|
|
173
|
+
export const BottomSheetFooter = createViewSlot("footer");
|
|
174
|
+
BottomSheetFooter.displayName = "BottomSheetFooter";
|
|
175
|
+
export const BottomSheetTitle = createTextSlot("title");
|
|
176
|
+
BottomSheetTitle.displayName = "BottomSheetTitle";
|
|
177
|
+
export const BottomSheetDescription = createTextSlot("description");
|
|
178
|
+
BottomSheetDescription.displayName = "BottomSheetDescription";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { BottomSheetBackdrop as Backdrop, BottomSheetBody as Body, BottomSheetContent as Content, BottomSheetDescription as Description, BottomSheetFooter as Footer, BottomSheetHandle as Handle, BottomSheetHeader as Header, BottomSheetPositioner as Positioner, BottomSheetRoot as Root, BottomSheetTitle as Title, BottomSheetTrigger as Trigger, type BottomSheetBackdropProps as BackdropProps, type BottomSheetBodyProps as BodyProps, type BottomSheetContentProps as ContentProps, type BottomSheetDescriptionProps as DescriptionProps, type BottomSheetFooterProps as FooterProps, type BottomSheetHandleProps as HandleProps, type BottomSheetHeaderProps as HeaderProps, type BottomSheetPositionerProps as PositionerProps, type BottomSheetRootProps as RootProps, type BottomSheetTitleProps as TitleProps, type BottomSheetTriggerProps as TriggerProps, } from "./BottomSheet";
|
|
2
|
+
//# sourceMappingURL=BottomSheet.namespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheet.namespace.d.ts","sourceRoot":"","sources":["../../../src/components/BottomSheet/BottomSheet.namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,IAAI,QAAQ,EAC/B,eAAe,IAAI,IAAI,EACvB,kBAAkB,IAAI,OAAO,EAC7B,sBAAsB,IAAI,WAAW,EACrC,iBAAiB,IAAI,MAAM,EAC3B,iBAAiB,IAAI,MAAM,EAC3B,iBAAiB,IAAI,MAAM,EAC3B,qBAAqB,IAAI,UAAU,EACnC,eAAe,IAAI,IAAI,EACvB,gBAAgB,IAAI,KAAK,EACzB,kBAAkB,IAAI,OAAO,EAC7B,KAAK,wBAAwB,IAAI,aAAa,EAC9C,KAAK,oBAAoB,IAAI,SAAS,EACtC,KAAK,uBAAuB,IAAI,YAAY,EAC5C,KAAK,2BAA2B,IAAI,gBAAgB,EACpD,KAAK,sBAAsB,IAAI,WAAW,EAC1C,KAAK,sBAAsB,IAAI,WAAW,EAC1C,KAAK,sBAAsB,IAAI,WAAW,EAC1C,KAAK,0BAA0B,IAAI,eAAe,EAClD,KAAK,oBAAoB,IAAI,SAAS,EACtC,KAAK,qBAAqB,IAAI,UAAU,EACxC,KAAK,uBAAuB,IAAI,YAAY,GAC7C,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BottomSheetBackdrop as Backdrop, BottomSheetBody as Body, BottomSheetContent as Content, BottomSheetDescription as Description, BottomSheetFooter as Footer, BottomSheetHandle as Handle, BottomSheetHeader as Header, BottomSheetPositioner as Positioner, BottomSheetRoot as Root, BottomSheetTitle as Title, BottomSheetTrigger as Trigger, } from "./BottomSheet";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { BottomSheetBackdrop, type BottomSheetBackdropProps, BottomSheetBody, type BottomSheetBodyProps, BottomSheetContent, type BottomSheetContentProps, BottomSheetDescription, type BottomSheetDescriptionProps, BottomSheetFooter, type BottomSheetFooterProps, BottomSheetHandle, type BottomSheetHandleProps, BottomSheetHeader, type BottomSheetHeaderProps, BottomSheetPositioner, type BottomSheetPositionerProps, BottomSheetRoot, type BottomSheetRootProps, type BottomSheetRootRef, BottomSheetTitle, type BottomSheetTitleProps, BottomSheetTrigger, type BottomSheetTriggerProps, } from "./BottomSheet";
|
|
2
|
+
export * as BottomSheet from "./BottomSheet.namespace";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BottomSheet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,eAAe,EACf,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,sBAAsB,EACtB,KAAK,2BAA2B,EAChC,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { BottomSheetBackdrop, BottomSheetBody, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHandle, BottomSheetHeader, BottomSheetPositioner, BottomSheetRoot, BottomSheetTitle, BottomSheetTrigger, } from "./BottomSheet";
|
|
2
|
+
export * as BottomSheet from "./BottomSheet.namespace";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type CSSProperties, type ReactElement } from "react";
|
|
3
|
+
import type { MainThread } from "@lynx-js/types";
|
|
4
|
+
import type { CheckboxVariantProps } from "@seed-design/lynx-css/recipes/checkbox";
|
|
5
|
+
import type { CheckmarkVariantProps } from "@seed-design/lynx-css/recipes/checkmark";
|
|
6
|
+
export interface CheckboxRootProps extends CheckboxVariantProps, Omit<CheckmarkVariantProps, "size" | "checked" | "disabled" | "indeterminate"> {
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
checked?: boolean;
|
|
10
|
+
defaultChecked?: boolean;
|
|
11
|
+
indeterminate?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare const CheckboxRoot: React.ForwardRefExoticComponent<CheckboxRootProps & React.RefAttributes<unknown>>;
|
|
16
|
+
export interface CheckboxControlProps extends Pick<CheckmarkVariantProps, "tone" | "variant" | "size"> {
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const CheckboxControl: React.ForwardRefExoticComponent<CheckboxControlProps & React.RefAttributes<unknown>>;
|
|
21
|
+
type IconElementProps = {
|
|
22
|
+
className?: string;
|
|
23
|
+
style?: CSSProperties;
|
|
24
|
+
ref?: React.Ref<MainThread.Element>;
|
|
25
|
+
};
|
|
26
|
+
export interface CheckboxIndicatorProps {
|
|
27
|
+
/** Icon rendered when neither checked nor indeterminate. Optional. */
|
|
28
|
+
unchecked?: ReactElement<IconElementProps>;
|
|
29
|
+
/** Icon rendered when `checked=true` and `indeterminate=false`. */
|
|
30
|
+
checked: ReactElement<IconElementProps>;
|
|
31
|
+
/** Icon rendered when `indeterminate=true`. */
|
|
32
|
+
indeterminate?: ReactElement<IconElementProps>;
|
|
33
|
+
className?: string;
|
|
34
|
+
style?: CSSProperties;
|
|
35
|
+
}
|
|
36
|
+
export declare function CheckboxIndicator(props: CheckboxIndicatorProps): React.ReactElement<IconElementProps, string | React.JSXElementConstructor<any>> | null;
|
|
37
|
+
export declare namespace CheckboxIndicator {
|
|
38
|
+
var displayName: string;
|
|
39
|
+
}
|
|
40
|
+
export interface CheckboxLabelProps {
|
|
41
|
+
children?: React.ReactNode;
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const CheckboxLabel: React.ForwardRefExoticComponent<CheckboxLabelProps & React.RefAttributes<unknown>>;
|
|
45
|
+
export interface CheckboxGroupProps {
|
|
46
|
+
children?: React.ReactNode;
|
|
47
|
+
className?: string;
|
|
48
|
+
}
|
|
49
|
+
export declare const CheckboxGroup: React.ForwardRefExoticComponent<CheckboxGroupProps & React.RefAttributes<unknown>>;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=Checkbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAgC,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAE5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAEnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AA8DrF,MAAM,WAAW,iBACf,SAAQ,oBAAoB,EAC1B,IAAI,CAAC,qBAAqB,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,eAAe,CAAC;IAChF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,eAAO,MAAM,YAAY,mFAgDvB,CAAC;AAKH,MAAM,WAAW,oBACf,SAAQ,IAAI,CAAC,qBAAqB,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IAChE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,sFAiC1B,CAAC;AAKH,KAAK,gBAAgB,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,SAAS,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC3C,mEAAmE;IACnE,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACxC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,0FA8C9D;yBA9Ce,iBAAiB;;;AAmDjC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,oFAcxB,CAAC;AAKH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,oFAaxB,CAAC"}
|