@seed-design/lynx-react 0.8.0 → 0.9.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/components/AppBar/AppBar.d.ts.map +1 -1
- package/lib/components/AppBar/AppBar.jsx +3 -8
- package/lib/components/AppBar/context.d.ts +2 -1
- package/lib/components/AppBar/context.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.d.ts +2 -1
- package/lib/components/AppBar/useAppBar.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.js +17 -15
- package/lib/components/Box/Box.d.ts +3 -3
- package/lib/components/Box/Box.d.ts.map +1 -1
- package/lib/components/Stack/Stack.d.ts +7 -9
- package/lib/components/Stack/Stack.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.d.ts +8 -4
- package/lib/hooks/useSafeArea.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.js +22 -20
- package/lib/utils/styled.d.ts +46 -6
- package/lib/utils/styled.d.ts.map +1 -1
- package/lib/utils/styled.js +19 -4
- package/package.json +3 -3
- package/src/components/AppBar/AppBar.test.tsx +21 -3
- package/src/components/AppBar/AppBar.tsx +3 -12
- package/src/components/AppBar/context.ts +3 -1
- package/src/components/AppBar/useAppBar.ts +21 -15
- package/src/components/Box/Box.test.tsx +104 -0
- package/src/components/Box/Box.tsx +9 -6
- package/src/components/Stack/Stack.test.tsx +7 -0
- package/src/components/Stack/Stack.tsx +11 -10
- package/src/hooks/useSafeArea.test.ts +13 -1
- package/src/hooks/useSafeArea.ts +25 -23
- package/src/utils/styled.ts +127 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppBar.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/AppBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAGxC,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EAEtB,aAAa,EAEd,MAAM,aAAa,CAAC;AAoCrB;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AA2DzD,MAAM,WAAW,eAAgB,SAAQ,kBAAkB,EAAE,sBAAsB;CAAG;AAEtF,eAAO,MAAM,UAAU,iFA2BrB,CAAC;AAKH,MAAM,WAAW,eAAgB,SAAQ,sBAAsB;IAC7D,gBAAgB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,UAAU,iFA4BrB,CAAC;AAGH,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D,gBAAgB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,WAAW,kFA4BtB,CAAC;AAKH,MAAM,WAAW,eAAgB,SAAQ,sBAAsB,EAAE,sBAAsB;CAAG;AAE1F,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"AppBar.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/AppBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAGxC,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EAEtB,aAAa,EAEd,MAAM,aAAa,CAAC;AAoCrB;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AA2DzD,MAAM,WAAW,eAAgB,SAAQ,kBAAkB,EAAE,sBAAsB;CAAG;AAEtF,eAAO,MAAM,UAAU,iFA2BrB,CAAC;AAKH,MAAM,WAAW,eAAgB,SAAQ,sBAAsB;IAC7D,gBAAgB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,UAAU,iFA4BrB,CAAC;AAGH,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D,gBAAgB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,WAAW,kFA4BtB,CAAC;AAKH,MAAM,WAAW,eAAgB,SAAQ,sBAAsB,EAAE,sBAAsB;CAAG;AAE1F,eAAO,MAAM,UAAU,iFA0BrB,CAAC;AAGH,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;CAAG;AAE7D,eAAO,MAAM,WAAW,kFAYtB,CAAC;AAGH,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;CAAG;AAEhE,eAAO,MAAM,cAAc,qFAYzB,CAAC;AAKH,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACvC,kBAAkB;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC;IAChD,qBAAqB,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC7D,uBAAuB,CAAC,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IACjE,sBAAsB,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,eAAO,MAAM,gBAAgB,uFA8C3B,CAAC;AAGH,MAAM,WAAW,eAAgB,SAAQ,sBAAsB;IAC7D;;OAEG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,eAAO,MAAM,UAAU,iFAcrB,CAAC"}
|
|
@@ -58,7 +58,7 @@ var AppBarRoot = React.forwardRef((props, ref) => {
|
|
|
58
58
|
return <AppBarProvider value={contextValue}>
|
|
59
59
|
<AppBarClassNamesProvider value={classNames}>
|
|
60
60
|
<view {...mergeProps(ref ? { ref } : {}, nativeProps)} className={clsx(classNames.root, className)} style={{
|
|
61
|
-
"--seed-safe-area-top": contextValue.safeAreaInsetTop,
|
|
61
|
+
"--seed-safe-area-top": contextValue.safeArea.safeAreaInsetTop,
|
|
62
62
|
"--centered-title-padding-x": contextValue.centeredTitlePaddingX,
|
|
63
63
|
...rootLayoutStyle,
|
|
64
64
|
...style
|
|
@@ -99,7 +99,7 @@ var AppBarRight = React.forwardRef((props, ref) => {
|
|
|
99
99
|
});
|
|
100
100
|
AppBarRight.displayName = "AppBarRight";
|
|
101
101
|
var AppBarMain = React.forwardRef((props, ref) => {
|
|
102
|
-
const { centeredTitlePaddingX,
|
|
102
|
+
const { centeredTitlePaddingX, safeArea, sharedVariantProps } = useAppBarContext("AppBarMain");
|
|
103
103
|
const [variantProps, otherProps] = appBarMain.splitVariantProps({
|
|
104
104
|
...sharedVariantProps,
|
|
105
105
|
...props
|
|
@@ -107,14 +107,9 @@ var AppBarMain = React.forwardRef((props, ref) => {
|
|
|
107
107
|
const resolvedTheme = variantProps.theme ?? "cupertino";
|
|
108
108
|
const classNames = appBarMain(variantProps);
|
|
109
109
|
const { children, className, style, ...nativeProps } = otherProps;
|
|
110
|
-
const centeredTitleStyle = variantProps.theme === "cupertino" ? {
|
|
111
|
-
paddingLeft: centeredTitlePaddingX,
|
|
112
|
-
paddingRight: centeredTitlePaddingX
|
|
113
|
-
} : void 0;
|
|
114
110
|
return <AppBarMainClassNamesProvider value={classNames}>
|
|
115
111
|
<view {...mergeProps(ref ? { ref } : {}, nativeProps)} className={clsx(classNames.root, className)} style={{
|
|
116
|
-
...
|
|
117
|
-
...getMainLayoutStyle(resolvedTheme, safeAreaInsetTop),
|
|
112
|
+
...getMainLayoutStyle(resolvedTheme, safeArea, centeredTitlePaddingX),
|
|
118
113
|
...style
|
|
119
114
|
}}>
|
|
120
115
|
{children}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { AppBarMainVariantProps } from '@seed-design/lynx-css/recipes/app-bar-main';
|
|
2
|
+
import { UseSafeAreaReturn } from '../../hooks/useSafeArea';
|
|
2
3
|
import * as React from "@lynx-js/react";
|
|
3
4
|
export type SharedAppBarVariantProps = Pick<AppBarMainVariantProps, "theme" | "tone" | "transitionStyle">;
|
|
4
5
|
export interface AppBarContextValue {
|
|
5
6
|
centeredTitlePaddingX: string;
|
|
6
|
-
|
|
7
|
+
safeArea: UseSafeAreaReturn;
|
|
7
8
|
sharedVariantProps: SharedAppBarVariantProps;
|
|
8
9
|
setLeftWidth: (width: number) => void;
|
|
9
10
|
setRightWidth: (width: number) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,sBAAsB,EACtB,OAAO,GAAG,MAAM,GAAG,iBAAiB,CACrC,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,sBAAsB,EACtB,OAAO,GAAG,MAAM,GAAG,iBAAiB,CACrC,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,kBAAkB,EAAE,wBAAwB,CAAC;IAC7C,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAID,eAAO,MAAM,cAAc,2CAAyB,CAAC;AAErD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAMrE"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AppBarVariantProps, AppBarVariant } from '@seed-design/lynx-css/recipes/app-bar';
|
|
2
2
|
import { AppBarMainVariantProps } from '@seed-design/lynx-css/recipes/app-bar-main';
|
|
3
|
+
import { UseSafeAreaReturn } from '../../hooks/useSafeArea';
|
|
3
4
|
import { LynxViewProps } from '../../types';
|
|
4
5
|
import { AppBarContextValue } from './context';
|
|
5
6
|
type LayoutChangeHandler = NonNullable<LynxViewProps["bindlayoutchange"]>;
|
|
6
7
|
type AppBarStyleObject = Record<string, string | number>;
|
|
7
8
|
export declare function getLayoutWidth(event: Parameters<LayoutChangeHandler>[0]): number | null;
|
|
8
|
-
export declare function getMainLayoutStyle(theme: AppBarMainVariantProps["theme"],
|
|
9
|
+
export declare function getMainLayoutStyle(theme: AppBarMainVariantProps["theme"], safeArea: UseSafeAreaReturn, centeredTitlePaddingX: string): AppBarStyleObject | undefined;
|
|
9
10
|
export declare function useAppBar(variantProps: AppBarVariantProps): {
|
|
10
11
|
contextValue: AppBarContextValue;
|
|
11
12
|
resolvedVariantProps: Partial< AppBarVariant>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAppBar.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/useAppBar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAIzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAA4B,MAAM,WAAW,CAAC;AAO9E,KAAK,mBAAmB,GAAG,WAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1E,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"useAppBar.d.ts","sourceRoot":"","sources":["../../../src/components/AppBar/useAppBar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAIzF,OAAO,EAAE,KAAK,iBAAiB,EAAe,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAA4B,MAAM,WAAW,CAAC;AAO9E,KAAK,mBAAmB,GAAG,WAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1E,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAgBzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAMvF;AAiBD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,sBAAsB,CAAC,OAAO,CAAC,EACtC,QAAQ,EAAE,iBAAiB,EAC3B,qBAAqB,EAAE,MAAM,GAC5B,iBAAiB,GAAG,SAAS,CAS/B;AAED,wBAAgB,SAAS,CAAC,YAAY,EAAE,kBAAkB;;;;EAoCzD"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { useSafeArea } from "../../hooks/useSafeArea.js";
|
|
2
2
|
import * as React from "@lynx-js/react";
|
|
3
|
+
import { topNavigation } from "@seed-design/lynx-css/vars/component";
|
|
3
4
|
//#region src/components/AppBar/useAppBar.ts
|
|
4
|
-
var
|
|
5
|
-
cupertino: "44px",
|
|
6
|
-
android: "56px"
|
|
7
|
-
};
|
|
5
|
+
var ROOT_PADDING_X = 16;
|
|
8
6
|
function getDefaultAppBarTheme() {
|
|
9
7
|
const systemInfo = globalThis.SystemInfo ?? (typeof SystemInfo === "undefined" ? void 0 : SystemInfo);
|
|
10
8
|
if (systemInfo == null) return "cupertino";
|
|
@@ -17,23 +15,27 @@ function getLayoutWidth(event) {
|
|
|
17
15
|
return Math.max(0, nextWidth);
|
|
18
16
|
}
|
|
19
17
|
function getCenteredTitlePadding(leftWidth, rightWidth) {
|
|
20
|
-
return `${Math.max(leftWidth, rightWidth)}px`;
|
|
18
|
+
return `${ROOT_PADDING_X + Math.max(leftWidth, rightWidth)}px`;
|
|
21
19
|
}
|
|
22
|
-
function getRootLayoutStyle(
|
|
20
|
+
function getRootLayoutStyle(safeArea) {
|
|
23
21
|
return {
|
|
24
|
-
height: `calc(${
|
|
25
|
-
paddingTop: safeAreaInsetTop
|
|
22
|
+
height: `calc(${topNavigation.base.enabled.root.height} + ${safeArea.safeAreaInsetTop})`,
|
|
23
|
+
paddingTop: safeArea.safeAreaInsetTop,
|
|
24
|
+
paddingLeft: `calc(${ROOT_PADDING_X}px + ${safeArea.safeAreaInsetLeft})`,
|
|
25
|
+
paddingRight: `calc(${ROOT_PADDING_X}px + ${safeArea.safeAreaInsetRight})`
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
function getMainLayoutStyle(theme,
|
|
28
|
+
function getMainLayoutStyle(theme, safeArea, centeredTitlePaddingX) {
|
|
29
29
|
if (theme !== "cupertino") return void 0;
|
|
30
30
|
return {
|
|
31
|
-
top: safeAreaInsetTop,
|
|
32
|
-
bottom: "0px"
|
|
31
|
+
top: safeArea.safeAreaInsetTop,
|
|
32
|
+
bottom: "0px",
|
|
33
|
+
paddingLeft: `calc(${safeArea.safeAreaInsetLeft} + ${centeredTitlePaddingX})`,
|
|
34
|
+
paddingRight: `calc(${safeArea.safeAreaInsetRight} + ${centeredTitlePaddingX})`
|
|
33
35
|
};
|
|
34
36
|
}
|
|
35
37
|
function useAppBar(variantProps) {
|
|
36
|
-
const
|
|
38
|
+
const safeArea = useSafeArea();
|
|
37
39
|
const [leftWidth, setLeftWidth] = React.useState(0);
|
|
38
40
|
const [rightWidth, setRightWidth] = React.useState(0);
|
|
39
41
|
const resolvedTheme = variantProps.theme ?? getDefaultAppBarTheme();
|
|
@@ -42,7 +44,7 @@ function useAppBar(variantProps) {
|
|
|
42
44
|
theme: resolvedTheme
|
|
43
45
|
};
|
|
44
46
|
const centeredTitlePaddingX = getCenteredTitlePadding(leftWidth, rightWidth);
|
|
45
|
-
const rootLayoutStyle = getRootLayoutStyle(
|
|
47
|
+
const rootLayoutStyle = getRootLayoutStyle(safeArea);
|
|
46
48
|
const sharedVariantProps = React.useMemo(() => ({
|
|
47
49
|
theme: resolvedVariantProps.theme,
|
|
48
50
|
tone: resolvedVariantProps.tone,
|
|
@@ -55,13 +57,13 @@ function useAppBar(variantProps) {
|
|
|
55
57
|
return {
|
|
56
58
|
contextValue: React.useMemo(() => ({
|
|
57
59
|
centeredTitlePaddingX,
|
|
58
|
-
|
|
60
|
+
safeArea,
|
|
59
61
|
sharedVariantProps,
|
|
60
62
|
setLeftWidth,
|
|
61
63
|
setRightWidth
|
|
62
64
|
}), [
|
|
63
65
|
centeredTitlePaddingX,
|
|
64
|
-
|
|
66
|
+
safeArea,
|
|
65
67
|
sharedVariantProps
|
|
66
68
|
]),
|
|
67
69
|
resolvedVariantProps,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LynxPressableProps, LynxStyledElementProps } from '../../types';
|
|
2
|
-
import { StyleProps } from '../../utils/styled';
|
|
2
|
+
import { MarginBleedStyleProps, StyleProps } from '../../utils/styled';
|
|
3
3
|
import * as React from "@lynx-js/react";
|
|
4
4
|
/**
|
|
5
5
|
* @platform Lynx
|
|
@@ -11,10 +11,10 @@ import * as React from "@lynx-js/react";
|
|
|
11
11
|
* 컴포넌트 내부에서는 native tag와 recipe className을 사용하고, inline style은
|
|
12
12
|
* 런타임 값이 필요한 경우에만 제한적으로 사용합니다.
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
14
|
+
export type BoxProps = StyleProps & MarginBleedStyleProps & LynxStyledElementProps & LynxPressableProps & {
|
|
15
15
|
bindtouchstart?: () => void;
|
|
16
16
|
bindtouchend?: () => void;
|
|
17
17
|
bindtouchcancel?: () => void;
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
export declare const Box: React.ForwardRefExoticComponent<BoxProps & React.RefAttributes<unknown>>;
|
|
20
20
|
//# sourceMappingURL=Box.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Box.d.ts","sourceRoot":"","sources":["../../../src/components/Box/Box.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Box.d.ts","sourceRoot":"","sources":["../../../src/components/Box/Box.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAiB,KAAK,qBAAqB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhG;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAC/B,qBAAqB,GACrB,sBAAsB,GACtB,kBAAkB,GAAG;IACnB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEJ,eAAO,MAAM,GAAG,0EAad,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LynxPressableProps, LynxStyledElementProps } from '../../types';
|
|
2
|
-
import { StyleProps } from '../../utils/styled';
|
|
2
|
+
import { MarginBleedStyleProps, StyleProps } from '../../utils/styled';
|
|
3
3
|
import * as React from "@lynx-js/react";
|
|
4
4
|
type StackStyleProps = "display" | "flexDirection" | "alignItems" | "justifyContent" | "flexWrap" | "flexGrow" | "flexShrink";
|
|
5
5
|
interface StackBaseProps extends StyleProps, LynxStyledElementProps, LynxPressableProps {
|
|
@@ -16,18 +16,16 @@ interface StackBaseProps extends StyleProps, LynxStyledElementProps, LynxPressab
|
|
|
16
16
|
* 패키지 컴포넌트 내부에서는 `Box`를 합성하지 않고 native tag와 recipe className을
|
|
17
17
|
* 사용해 primitive 컴포넌트 비용이 누적되지 않도록 합니다.
|
|
18
18
|
*/
|
|
19
|
-
export
|
|
19
|
+
export type StackProps = Omit<StackBaseProps, StackStyleProps> & MarginBleedStyleProps & {
|
|
20
20
|
align?: StackBaseProps["alignItems"];
|
|
21
21
|
justify?: StackBaseProps["justifyContent"];
|
|
22
22
|
wrap?: StackBaseProps["flexWrap"];
|
|
23
23
|
grow?: StackBaseProps["flexGrow"];
|
|
24
24
|
shrink?: StackBaseProps["flexShrink"];
|
|
25
|
-
}
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
export declare const VStack: React.ForwardRefExoticComponent<VStackProps & React.RefAttributes<unknown>>;
|
|
31
|
-
export declare const HStack: React.ForwardRefExoticComponent<HStackProps & React.RefAttributes<unknown>>;
|
|
25
|
+
};
|
|
26
|
+
export type VStackProps = StackProps;
|
|
27
|
+
export type HStackProps = StackProps;
|
|
28
|
+
export declare const VStack: React.ForwardRefExoticComponent<StackProps & React.RefAttributes<unknown>>;
|
|
29
|
+
export declare const HStack: React.ForwardRefExoticComponent<StackProps & React.RefAttributes<unknown>>;
|
|
32
30
|
export {};
|
|
33
31
|
//# sourceMappingURL=Stack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAe,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAiB,KAAK,qBAAqB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhG,KAAK,eAAe,GAChB,SAAS,GACT,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,UAAU,GACV,UAAU,GACV,YAAY,CAAC;AAEjB,UAAU,cAAe,SAAQ,UAAU,EAAE,sBAAsB,EAAE,kBAAkB;IACrF,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,GAC5D,qBAAqB,GAAG;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;CACvC,CAAC;AAEJ,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC;AAuDrC,eAAO,MAAM,MAAM,4EAIjB,CAAC;AAIH,eAAO,MAAM,MAAM,4EAIjB,CAAC"}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
declare module "@lynx-js/types" {
|
|
2
2
|
interface GlobalProps {
|
|
3
3
|
safeAreaInsetTop?: number;
|
|
4
|
+
safeAreaInsetRight?: number;
|
|
4
5
|
safeAreaInsetBottom?: number;
|
|
6
|
+
safeAreaInsetLeft?: number;
|
|
5
7
|
}
|
|
6
8
|
}
|
|
7
9
|
export interface UseSafeAreaReturn {
|
|
8
10
|
safeAreaInsetTop: string;
|
|
11
|
+
safeAreaInsetRight: string;
|
|
9
12
|
safeAreaInsetBottom: string;
|
|
13
|
+
safeAreaInsetLeft: string;
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
|
-
* Lynx 앱에서 top/bottom safe area inset 값을 반환합니다.
|
|
16
|
+
* Lynx 앱에서 top/right/bottom/left safe area inset 값을 반환합니다.
|
|
13
17
|
*
|
|
14
|
-
* `lynx.__globalProps.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
18
|
+
* `lynx.__globalProps.safeAreaInset*` 값을 우선 사용하고, host가 값을 제공하지 않으면
|
|
19
|
+
* Lynx CSS `env(safe-area-inset-*)` 값을 fallback으로 반환합니다. top/bottom은 host가
|
|
20
|
+
* `0`을 제공해도 fallback합니다.
|
|
17
21
|
*/
|
|
18
22
|
export declare function useSafeArea(): UseSafeAreaReturn;
|
|
19
23
|
//# sourceMappingURL=useSafeArea.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSafeArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useSafeArea.ts"],"names":[],"mappings":"AAIA,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,WAAW;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"useSafeArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useSafeArea.ts"],"names":[],"mappings":"AAIA,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,WAAW;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;CACF;AAgBD,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CAgB/C"}
|
package/lib/hooks/useSafeArea.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
import { useMemo } from "@lynx-js/react";
|
|
2
2
|
//#region src/hooks/useSafeArea.ts
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
7
|
-
function getSafeAreaEnvInset(edge) {
|
|
8
|
-
return `env(safe-area-inset-${edge})`;
|
|
9
|
-
}
|
|
10
|
-
function normalizeSafeAreaValue(value) {
|
|
11
|
-
if (typeof value !== "number" || value <= 0 || !Number.isFinite(value)) return;
|
|
3
|
+
function normalizeSafeAreaValue(edge, value) {
|
|
4
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
|
|
5
|
+
if (value === 0 && (edge === "top" || edge === "bottom")) return void 0;
|
|
12
6
|
return `${value}px`;
|
|
13
7
|
}
|
|
14
|
-
|
|
15
|
-
return normalizeSafeAreaValue(value) ?? getSafeAreaEnvInset(edge);
|
|
16
|
-
}
|
|
8
|
+
var resolveSafeAreaInset = (edge, value) => normalizeSafeAreaValue(edge, value) ?? `env(safe-area-inset-${edge})`;
|
|
17
9
|
/**
|
|
18
|
-
* Lynx 앱에서 top/bottom safe area inset 값을 반환합니다.
|
|
10
|
+
* Lynx 앱에서 top/right/bottom/left safe area inset 값을 반환합니다.
|
|
19
11
|
*
|
|
20
|
-
* `lynx.__globalProps.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
12
|
+
* `lynx.__globalProps.safeAreaInset*` 값을 우선 사용하고, host가 값을 제공하지 않으면
|
|
13
|
+
* Lynx CSS `env(safe-area-inset-*)` 값을 fallback으로 반환합니다. top/bottom은 host가
|
|
14
|
+
* `0`을 제공해도 fallback합니다.
|
|
23
15
|
*/
|
|
24
16
|
function useSafeArea() {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
17
|
+
const globalProps = lynx.__globalProps;
|
|
18
|
+
const safeAreaInsetTop = globalProps?.safeAreaInsetTop;
|
|
19
|
+
const safeAreaInsetRight = globalProps?.safeAreaInsetRight;
|
|
20
|
+
const safeAreaInsetBottom = globalProps?.safeAreaInsetBottom;
|
|
21
|
+
const safeAreaInsetLeft = globalProps?.safeAreaInsetLeft;
|
|
27
22
|
return useMemo(() => ({
|
|
28
23
|
safeAreaInsetTop: resolveSafeAreaInset("top", safeAreaInsetTop),
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
safeAreaInsetRight: resolveSafeAreaInset("right", safeAreaInsetRight),
|
|
25
|
+
safeAreaInsetBottom: resolveSafeAreaInset("bottom", safeAreaInsetBottom),
|
|
26
|
+
safeAreaInsetLeft: resolveSafeAreaInset("left", safeAreaInsetLeft)
|
|
27
|
+
}), [
|
|
28
|
+
safeAreaInsetTop,
|
|
29
|
+
safeAreaInsetRight,
|
|
30
|
+
safeAreaInsetBottom,
|
|
31
|
+
safeAreaInsetLeft
|
|
32
|
+
]);
|
|
31
33
|
}
|
|
32
34
|
//#endregion
|
|
33
35
|
export { useSafeArea };
|
package/lib/utils/styled.d.ts
CHANGED
|
@@ -41,12 +41,12 @@ export interface StyleProps {
|
|
|
41
41
|
py?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
42
42
|
paddingTop?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
43
43
|
pt?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
44
|
-
paddingRight?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
45
|
-
pr?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
44
|
+
paddingRight?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
45
|
+
pr?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
46
46
|
paddingBottom?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
47
47
|
pb?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
48
|
-
paddingLeft?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
49
|
-
pl?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
48
|
+
paddingLeft?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
49
|
+
pl?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
50
50
|
display?: "flex" | "none" | (string & {});
|
|
51
51
|
position?: "relative" | "absolute" | "fixed" | (string & {});
|
|
52
52
|
overflowX?: "visible" | "hidden" | (string & {});
|
|
@@ -63,9 +63,49 @@ export interface StyleProps {
|
|
|
63
63
|
alignSelf?: "flexStart" | "flexEnd" | "center" | "stretch" | (string & {});
|
|
64
64
|
gap?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
type MarginValue = Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "auto" | (string & {});
|
|
67
|
+
/**
|
|
68
|
+
* Dimension tokens are left out: every token resolves to `var()`, and Lynx drops an inline
|
|
69
|
+
* `calc()` that contains `var()`, so a negated token would silently apply no margin.
|
|
70
|
+
*/
|
|
71
|
+
type BleedValue = 0 | `${number}px` | "safeArea";
|
|
72
|
+
interface MarginStyleProps {
|
|
73
|
+
margin?: MarginValue;
|
|
74
|
+
m?: MarginValue;
|
|
75
|
+
marginX?: MarginValue;
|
|
76
|
+
mx?: MarginValue;
|
|
77
|
+
marginY?: MarginValue;
|
|
78
|
+
my?: MarginValue;
|
|
79
|
+
marginTop?: MarginValue;
|
|
80
|
+
mt?: MarginValue;
|
|
81
|
+
marginRight?: MarginValue;
|
|
82
|
+
mr?: MarginValue;
|
|
83
|
+
marginBottom?: MarginValue;
|
|
84
|
+
mb?: MarginValue;
|
|
85
|
+
marginLeft?: MarginValue;
|
|
86
|
+
ml?: MarginValue;
|
|
87
|
+
}
|
|
88
|
+
interface BleedStyleProps {
|
|
89
|
+
bleed?: BleedValue;
|
|
90
|
+
bleedX?: BleedValue;
|
|
91
|
+
bleedY?: BleedValue;
|
|
92
|
+
bleedTop?: BleedValue;
|
|
93
|
+
bleedRight?: BleedValue;
|
|
94
|
+
bleedBottom?: BleedValue;
|
|
95
|
+
bleedLeft?: BleedValue;
|
|
68
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Margin and bleed props both resolve to `margin-*` values, so they are mutually exclusive at
|
|
99
|
+
* the type level.
|
|
100
|
+
*/
|
|
101
|
+
export type MarginBleedStyleProps = (BleedStyleProps & {
|
|
102
|
+
[K in keyof MarginStyleProps]?: never;
|
|
103
|
+
}) | (MarginStyleProps & {
|
|
104
|
+
[K in keyof BleedStyleProps]?: never;
|
|
105
|
+
});
|
|
106
|
+
type UseStyleProps = StyleProps & MarginStyleProps & BleedStyleProps & {
|
|
107
|
+
style?: CSSProperties;
|
|
108
|
+
};
|
|
69
109
|
export declare function useStyleProps<T extends UseStyleProps>(props: T): {
|
|
70
110
|
style: CSSProperties;
|
|
71
111
|
restProps: Omit<T, keyof UseStyleProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styled.d.ts","sourceRoot":"","sources":["../../src/utils/styled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,UAAU,EACV,UAAU,EACV,MAAM,EACN,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,OAOpD;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiB1F;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAC3C,MAAM,GAAG,MAAM,GAAG,SAAS,CAI7B;AAcD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,SAAS,CAMpB;
|
|
1
|
+
{"version":3,"file":"styled.d.ts","sourceRoot":"","sources":["../../src/utils/styled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,UAAU,EACV,UAAU,EACV,MAAM,EACN,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,OAOpD;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiB1F;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAC3C,MAAM,GAAG,MAAM,GAAG,SAAS,CAI7B;AAcD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,SAAS,CAMpB;AAQD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,OAM1D;AA6DD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,OAM9D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,OAMtD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,OAM9D;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,aAAa,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,aAAa,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACpF,KAAK,CAAC,EAAE,aAAa,GAAG,kBAAkB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrE,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACvC,gBAAgB,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1C,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1C,mBAAmB,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACjD,oBAAoB,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClD,uBAAuB,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrD,sBAAsB,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC7F,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChG,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChG,MAAM,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC9F,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACjG,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACjG,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACpF,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3F,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrF,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3F,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrF,UAAU,CAAC,EACP,SAAS,GACT,YAAY,QAAQ,EAAE,GACtB,YAAY,QAAQ,EAAE,GACtB,CAAC,GACD,UAAU,GACV,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClG,YAAY,CAAC,EACT,SAAS,GACT,YAAY,QAAQ,EAAE,GACtB,YAAY,QAAQ,EAAE,GACtB,CAAC,GACD,UAAU,GACV,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClG,aAAa,CAAC,EACV,SAAS,GACT,YAAY,QAAQ,EAAE,GACtB,YAAY,QAAQ,EAAE,GACtB,CAAC,GACD,UAAU,GACV,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClG,WAAW,CAAC,EACR,SAAS,GACT,YAAY,QAAQ,EAAE,GACtB,YAAY,QAAQ,EAAE,GACtB,CAAC,GACD,UAAU,GACV,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClG,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACjD,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;IAC/C,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;IACnD,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,YAAY,GAAG,eAAe,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClF,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACvC,cAAc,CAAC,EACX,WAAW,GACX,SAAS,GACT,QAAQ,GACR,cAAc,GACd,aAAa,GACb,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC5E,YAAY,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC9E,SAAS,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3E,GAAG,CAAC,EAAE,SAAS,GAAG,YAAY,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;CACvF;AAED,KAAK,WAAW,GACZ,SAAS,GACT,YAAY,QAAQ,EAAE,GACtB,YAAY,QAAQ,EAAE,GACtB,CAAC,GACD,MAAM,GACN,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;;GAGG;AACH,KAAK,UAAU,GAAG,CAAC,GAAG,GAAG,MAAM,IAAI,GAAG,UAAU,CAAC;AAEjD,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,CAAC,CAAC,EAAE,WAAW,CAAC;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,EAAE,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAC7B,CAAC,eAAe,GAAG;KAAG,CAAC,IAAI,MAAM,gBAAgB,CAAC,CAAC,EAAE,KAAK;CAAE,CAAC,GAC7D,CAAC,gBAAgB,GAAG;KAAG,CAAC,IAAI,MAAM,eAAe,CAAC,CAAC,EAAE,KAAK;CAAE,CAAC,CAAC;AAElE,KAAK,aAAa,GAAG,UAAU,GAC7B,gBAAgB,GAChB,eAAe,GAAG;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEJ,wBAAgB,aAAa,CAAC,CAAC,SAAS,aAAa,EACnD,KAAK,EAAE,CAAC,GACP;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC,CAAC;CACzC,CAgLA;AAED,MAAM,MAAM,SAAS,GACjB,aAAa,GACb,aAAa,GACb,aAAa,GACb,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,cAAc,GACd,cAAc,GACd,eAAe,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,aAAa,GAAG,kBAAkB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3D,QAAQ,CAAC,EAAE,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACrC"}
|
package/lib/utils/styled.js
CHANGED
|
@@ -27,6 +27,10 @@ function handlePaddingWithSafeArea(padding, safeAreaInset) {
|
|
|
27
27
|
if (padding === "safeArea") return safeAreaInset;
|
|
28
28
|
return handleDimension(padding);
|
|
29
29
|
}
|
|
30
|
+
function handleBleed(bleed, safeAreaInset) {
|
|
31
|
+
if (bleed == null) return void 0;
|
|
32
|
+
return `calc(${bleed === "safeArea" ? safeAreaInset : bleed === 0 ? "0px" : bleed} * -1)`;
|
|
33
|
+
}
|
|
30
34
|
function handleRadius(radius) {
|
|
31
35
|
if (radius == null) return;
|
|
32
36
|
return vars.$radius[radius] ?? radius;
|
|
@@ -79,16 +83,23 @@ function handleLineHeight(lineHeight) {
|
|
|
79
83
|
return vars.$lineHeight[lineHeight] ?? lineHeight;
|
|
80
84
|
}
|
|
81
85
|
function useStyleProps(props) {
|
|
82
|
-
const { background, bg, color, borderColor, borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, borderRadius, borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius, width, minWidth, maxWidth, height, minHeight, maxHeight, padding, paddingX, paddingY, paddingTop, paddingRight, paddingBottom, paddingLeft, p, px, py, pt, pr, pb, pl, bottom, left, right, top, display, position, overflowX, overflowY, zIndex, flexGrow, flexShrink, flexDirection, flexWrap, justifyContent, justifySelf, alignItems, alignContent, alignSelf, gap, style, ...restProps } = props;
|
|
83
|
-
const { safeAreaInsetTop, safeAreaInsetBottom } = useSafeArea();
|
|
86
|
+
const { background, bg, color, borderColor, borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, borderRadius, borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius, width, minWidth, maxWidth, height, minHeight, maxHeight, padding, paddingX, paddingY, paddingTop, paddingRight, paddingBottom, paddingLeft, p, px, py, pt, pr, pb, pl, margin, m, marginX, mx, marginY, my, marginTop, mt, marginRight, mr, marginBottom, mb, marginLeft, ml, bleed, bleedX, bleedY, bleedTop, bleedRight, bleedBottom, bleedLeft, bottom, left, right, top, display, position, overflowX, overflowY, zIndex, flexGrow, flexShrink, flexDirection, flexWrap, justifyContent, justifySelf, alignItems, alignContent, alignSelf, gap, style, ...restProps } = props;
|
|
87
|
+
const { safeAreaInsetTop, safeAreaInsetRight, safeAreaInsetBottom, safeAreaInsetLeft } = useSafeArea();
|
|
84
88
|
const backgroundValue = handleColor(background ?? bg);
|
|
85
89
|
const paddingValue = handleDimension(padding ?? p);
|
|
86
90
|
const paddingXValue = handleDimension(paddingX ?? px) ?? paddingValue;
|
|
87
91
|
const paddingYValue = handleDimension(paddingY ?? py) ?? paddingValue;
|
|
88
92
|
const paddingTopValue = handlePaddingWithSafeArea(paddingTop ?? pt, safeAreaInsetTop) ?? paddingYValue;
|
|
89
|
-
const paddingRightValue =
|
|
93
|
+
const paddingRightValue = handlePaddingWithSafeArea(paddingRight ?? pr, safeAreaInsetRight) ?? paddingXValue;
|
|
90
94
|
const paddingBottomValue = handlePaddingWithSafeArea(paddingBottom ?? pb, safeAreaInsetBottom) ?? paddingYValue;
|
|
91
|
-
const paddingLeftValue =
|
|
95
|
+
const paddingLeftValue = handlePaddingWithSafeArea(paddingLeft ?? pl, safeAreaInsetLeft) ?? paddingXValue;
|
|
96
|
+
const marginValue = handleDimension(margin ?? m);
|
|
97
|
+
const marginXValue = handleDimension(marginX ?? mx) ?? marginValue;
|
|
98
|
+
const marginYValue = handleDimension(marginY ?? my) ?? marginValue;
|
|
99
|
+
const marginTopValue = handleDimension(marginTop ?? mt) ?? marginYValue ?? handleBleed(bleedTop ?? bleedY ?? bleed, safeAreaInsetTop);
|
|
100
|
+
const marginRightValue = handleDimension(marginRight ?? mr) ?? marginXValue ?? handleBleed(bleedRight ?? bleedX ?? bleed, safeAreaInsetRight);
|
|
101
|
+
const marginBottomValue = handleDimension(marginBottom ?? mb) ?? marginYValue ?? handleBleed(bleedBottom ?? bleedY ?? bleed, safeAreaInsetBottom);
|
|
102
|
+
const marginLeftValue = handleDimension(marginLeft ?? ml) ?? marginXValue ?? handleBleed(bleedLeft ?? bleedX ?? bleed, safeAreaInsetLeft);
|
|
92
103
|
const hasBorderStyle = borderColor != null || borderWidth != null || borderTopWidth != null || borderRightWidth != null || borderBottomWidth != null || borderLeftWidth != null;
|
|
93
104
|
return {
|
|
94
105
|
style: {
|
|
@@ -116,6 +127,10 @@ function useStyleProps(props) {
|
|
|
116
127
|
paddingRight: paddingRightValue,
|
|
117
128
|
paddingBottom: paddingBottomValue,
|
|
118
129
|
paddingLeft: paddingLeftValue,
|
|
130
|
+
marginTop: marginTopValue,
|
|
131
|
+
marginRight: marginRightValue,
|
|
132
|
+
marginBottom: marginBottomValue,
|
|
133
|
+
marginLeft: marginLeftValue,
|
|
119
134
|
top: handleDimension(top),
|
|
120
135
|
left: handleDimension(left),
|
|
121
136
|
right: handleDimension(right),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seed-design/lynx-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/daangn/seed-design.git",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@lynx-js/react": ">=0.117.0",
|
|
36
36
|
"@lynx-js/types": ">=3.9.0",
|
|
37
|
-
"@seed-design/lynx-css": "0.
|
|
37
|
+
"@seed-design/lynx-css": "^0.13.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@lynx-js/react": "^0.117.0",
|
|
41
41
|
"@lynx-js/types": "^3.9.0",
|
|
42
|
-
"@seed-design/lynx-css": "0.
|
|
42
|
+
"@seed-design/lynx-css": "0.13.0",
|
|
43
43
|
"@testing-library/jest-dom": "^6.9.1",
|
|
44
44
|
"jsdom": "^29.0.2",
|
|
45
45
|
"preact": "npm:@lynx-js/internal-preact@10.28.4-ee7bb26",
|
|
@@ -22,7 +22,9 @@ interface TestLynxGlobal {
|
|
|
22
22
|
lynx?: {
|
|
23
23
|
__globalProps?: {
|
|
24
24
|
safeAreaInsetTop?: number;
|
|
25
|
+
safeAreaInsetRight?: number;
|
|
25
26
|
safeAreaInsetBottom?: number;
|
|
27
|
+
safeAreaInsetLeft?: number;
|
|
26
28
|
};
|
|
27
29
|
};
|
|
28
30
|
lynxTestingEnv?: {
|
|
@@ -153,11 +155,22 @@ describe("AppBar", () => {
|
|
|
153
155
|
render(<AppBar.Root theme="cupertino" />);
|
|
154
156
|
|
|
155
157
|
expectStyle(getAppBarRoot().style, {
|
|
156
|
-
height: "calc(
|
|
158
|
+
height: "calc(103px)",
|
|
157
159
|
"padding-top": "47px",
|
|
158
160
|
});
|
|
159
161
|
});
|
|
160
162
|
|
|
163
|
+
it("adds left and right safe area insets to the root padding", () => {
|
|
164
|
+
setGlobalProps({ safeAreaInsetRight: 0, safeAreaInsetLeft: 59 });
|
|
165
|
+
|
|
166
|
+
render(<AppBar.Root theme="cupertino" />);
|
|
167
|
+
|
|
168
|
+
expectStyle(getAppBarRoot().style, {
|
|
169
|
+
"padding-left": "calc(75px)",
|
|
170
|
+
"padding-right": "calc(16px)",
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
161
174
|
it("does not read the safe area CSS variable override as the JS layout source", () => {
|
|
162
175
|
setGlobalProps({ safeAreaInsetTop: 47 });
|
|
163
176
|
|
|
@@ -169,7 +182,7 @@ describe("AppBar", () => {
|
|
|
169
182
|
);
|
|
170
183
|
|
|
171
184
|
expectStyle(getAppBarRoot().style, {
|
|
172
|
-
height: "calc(
|
|
185
|
+
height: "calc(103px)",
|
|
173
186
|
"padding-top": "47px",
|
|
174
187
|
});
|
|
175
188
|
});
|
|
@@ -240,6 +253,8 @@ describe("AppBar", () => {
|
|
|
240
253
|
});
|
|
241
254
|
|
|
242
255
|
it("updates centered title padding from left and right layout widths", async () => {
|
|
256
|
+
setGlobalProps({ safeAreaInsetRight: 0, safeAreaInsetLeft: 59 });
|
|
257
|
+
|
|
243
258
|
render(
|
|
244
259
|
<AppBar.Root>
|
|
245
260
|
<AppBar.Left>
|
|
@@ -269,7 +284,10 @@ describe("AppBar", () => {
|
|
|
269
284
|
});
|
|
270
285
|
|
|
271
286
|
await waitFor(() => {
|
|
272
|
-
expect(main).toHaveStyle({
|
|
287
|
+
expect(main).toHaveStyle({
|
|
288
|
+
paddingLeft: "calc(59px + 88px)",
|
|
289
|
+
paddingRight: "calc(0px + 88px)",
|
|
290
|
+
});
|
|
273
291
|
});
|
|
274
292
|
});
|
|
275
293
|
|
|
@@ -128,7 +128,7 @@ export const AppBarRoot = React.forwardRef<unknown, AppBarRootProps>((props, ref
|
|
|
128
128
|
className={clsx(classNames.root, className)}
|
|
129
129
|
style={
|
|
130
130
|
{
|
|
131
|
-
"--seed-safe-area-top": contextValue.safeAreaInsetTop,
|
|
131
|
+
"--seed-safe-area-top": contextValue.safeArea.safeAreaInsetTop,
|
|
132
132
|
"--centered-title-padding-x": contextValue.centeredTitlePaddingX,
|
|
133
133
|
...rootLayoutStyle,
|
|
134
134
|
...style,
|
|
@@ -221,8 +221,7 @@ AppBarRight.displayName = "AppBarRight";
|
|
|
221
221
|
export interface AppBarMainProps extends AppBarMainVariantProps, LynxStyledElementProps {}
|
|
222
222
|
|
|
223
223
|
export const AppBarMain = React.forwardRef<unknown, AppBarMainProps>((props, ref) => {
|
|
224
|
-
const { centeredTitlePaddingX,
|
|
225
|
-
useAppBarContext("AppBarMain");
|
|
224
|
+
const { centeredTitlePaddingX, safeArea, sharedVariantProps } = useAppBarContext("AppBarMain");
|
|
226
225
|
const [variantProps, otherProps] = appBarMain.splitVariantProps({
|
|
227
226
|
...sharedVariantProps,
|
|
228
227
|
...props,
|
|
@@ -230,13 +229,6 @@ export const AppBarMain = React.forwardRef<unknown, AppBarMainProps>((props, ref
|
|
|
230
229
|
const resolvedTheme = variantProps.theme ?? "cupertino";
|
|
231
230
|
const classNames = appBarMain(variantProps);
|
|
232
231
|
const { children, className, style, ...nativeProps } = otherProps;
|
|
233
|
-
const centeredTitleStyle =
|
|
234
|
-
variantProps.theme === "cupertino"
|
|
235
|
-
? {
|
|
236
|
-
paddingLeft: centeredTitlePaddingX,
|
|
237
|
-
paddingRight: centeredTitlePaddingX,
|
|
238
|
-
}
|
|
239
|
-
: undefined;
|
|
240
232
|
|
|
241
233
|
return (
|
|
242
234
|
<AppBarMainClassNamesProvider value={classNames}>
|
|
@@ -245,8 +237,7 @@ export const AppBarMain = React.forwardRef<unknown, AppBarMainProps>((props, ref
|
|
|
245
237
|
className={clsx(classNames.root, className)}
|
|
246
238
|
style={
|
|
247
239
|
{
|
|
248
|
-
...
|
|
249
|
-
...getMainLayoutStyle(resolvedTheme, safeAreaInsetTop),
|
|
240
|
+
...getMainLayoutStyle(resolvedTheme, safeArea, centeredTitlePaddingX),
|
|
250
241
|
...style,
|
|
251
242
|
} as LynxViewProps["style"]
|
|
252
243
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type AppBarMainVariantProps } from "@seed-design/lynx-css/recipes/app-bar-main";
|
|
2
2
|
import * as React from "@lynx-js/react";
|
|
3
3
|
|
|
4
|
+
import type { UseSafeAreaReturn } from "../../hooks/useSafeArea";
|
|
5
|
+
|
|
4
6
|
export type SharedAppBarVariantProps = Pick<
|
|
5
7
|
AppBarMainVariantProps,
|
|
6
8
|
"theme" | "tone" | "transitionStyle"
|
|
@@ -8,7 +10,7 @@ export type SharedAppBarVariantProps = Pick<
|
|
|
8
10
|
|
|
9
11
|
export interface AppBarContextValue {
|
|
10
12
|
centeredTitlePaddingX: string;
|
|
11
|
-
|
|
13
|
+
safeArea: UseSafeAreaReturn;
|
|
12
14
|
sharedVariantProps: SharedAppBarVariantProps;
|
|
13
15
|
setLeftWidth: (width: number) => void;
|
|
14
16
|
setRightWidth: (width: number) => void;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { AppBarVariantProps } from "@seed-design/lynx-css/recipes/app-bar";
|
|
2
2
|
import type { AppBarMainVariantProps } from "@seed-design/lynx-css/recipes/app-bar-main";
|
|
3
|
+
import { topNavigation as topNavigationVars } from "@seed-design/lynx-css/vars/component";
|
|
3
4
|
import * as React from "@lynx-js/react";
|
|
4
5
|
|
|
5
|
-
import { useSafeArea } from "../../hooks/useSafeArea";
|
|
6
|
+
import { type UseSafeAreaReturn, useSafeArea } from "../../hooks/useSafeArea";
|
|
6
7
|
import type { LynxViewProps } from "../../types";
|
|
7
8
|
import type { AppBarContextValue, SharedAppBarVariantProps } from "./context";
|
|
8
9
|
|
|
@@ -14,10 +15,8 @@ type AppBarTheme = NonNullable<AppBarVariantProps["theme"]>;
|
|
|
14
15
|
type LayoutChangeHandler = NonNullable<LynxViewProps["bindlayoutchange"]>;
|
|
15
16
|
type AppBarStyleObject = Record<string, string | number>;
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
android: "56px",
|
|
20
|
-
};
|
|
18
|
+
// Mirrors the recipe's `dimension.x4` as a literal: Lynx drops an inline `calc()` that contains `var()`.
|
|
19
|
+
const ROOT_PADDING_X = 16;
|
|
21
20
|
|
|
22
21
|
function getDefaultAppBarTheme(): AppBarTheme {
|
|
23
22
|
const globalSystemInfo = (globalThis as typeof globalThis & { SystemInfo?: LynxSystemInfo })
|
|
@@ -38,31 +37,38 @@ export function getLayoutWidth(event: Parameters<LayoutChangeHandler>[0]): numbe
|
|
|
38
37
|
return Math.max(0, nextWidth);
|
|
39
38
|
}
|
|
40
39
|
|
|
40
|
+
// The left/right areas sit inside the root padding, so the title clears that padding plus the wider area.
|
|
41
41
|
function getCenteredTitlePadding(leftWidth: number, rightWidth: number): string {
|
|
42
|
-
return `${Math.max(leftWidth, rightWidth)}px`;
|
|
42
|
+
return `${ROOT_PADDING_X + Math.max(leftWidth, rightWidth)}px`;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
function getRootLayoutStyle(
|
|
45
|
+
function getRootLayoutStyle(safeArea: UseSafeAreaReturn): AppBarStyleObject {
|
|
46
46
|
return {
|
|
47
|
-
height: `calc(${
|
|
48
|
-
paddingTop: safeAreaInsetTop,
|
|
47
|
+
height: `calc(${topNavigationVars.base.enabled.root.height} + ${safeArea.safeAreaInsetTop})`,
|
|
48
|
+
paddingTop: safeArea.safeAreaInsetTop,
|
|
49
|
+
paddingLeft: `calc(${ROOT_PADDING_X}px + ${safeArea.safeAreaInsetLeft})`,
|
|
50
|
+
paddingRight: `calc(${ROOT_PADDING_X}px + ${safeArea.safeAreaInsetRight})`,
|
|
49
51
|
};
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
// The title clears the same distance past each side's inset, so it stays centered in the safe area.
|
|
52
55
|
export function getMainLayoutStyle(
|
|
53
56
|
theme: AppBarMainVariantProps["theme"],
|
|
54
|
-
|
|
57
|
+
safeArea: UseSafeAreaReturn,
|
|
58
|
+
centeredTitlePaddingX: string,
|
|
55
59
|
): AppBarStyleObject | undefined {
|
|
56
60
|
if (theme !== "cupertino") return undefined;
|
|
57
61
|
|
|
58
62
|
return {
|
|
59
|
-
top: safeAreaInsetTop,
|
|
63
|
+
top: safeArea.safeAreaInsetTop,
|
|
60
64
|
bottom: "0px",
|
|
65
|
+
paddingLeft: `calc(${safeArea.safeAreaInsetLeft} + ${centeredTitlePaddingX})`,
|
|
66
|
+
paddingRight: `calc(${safeArea.safeAreaInsetRight} + ${centeredTitlePaddingX})`,
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
export function useAppBar(variantProps: AppBarVariantProps) {
|
|
65
|
-
const
|
|
71
|
+
const safeArea = useSafeArea();
|
|
66
72
|
const [leftWidth, setLeftWidth] = React.useState(0);
|
|
67
73
|
const [rightWidth, setRightWidth] = React.useState(0);
|
|
68
74
|
const resolvedTheme = variantProps.theme ?? getDefaultAppBarTheme();
|
|
@@ -72,7 +78,7 @@ export function useAppBar(variantProps: AppBarVariantProps) {
|
|
|
72
78
|
theme: resolvedTheme,
|
|
73
79
|
};
|
|
74
80
|
const centeredTitlePaddingX = getCenteredTitlePadding(leftWidth, rightWidth);
|
|
75
|
-
const rootLayoutStyle = getRootLayoutStyle(
|
|
81
|
+
const rootLayoutStyle = getRootLayoutStyle(safeArea);
|
|
76
82
|
const sharedVariantProps = React.useMemo<SharedAppBarVariantProps>(
|
|
77
83
|
() => ({
|
|
78
84
|
theme: resolvedVariantProps.theme,
|
|
@@ -84,12 +90,12 @@ export function useAppBar(variantProps: AppBarVariantProps) {
|
|
|
84
90
|
const contextValue = React.useMemo<AppBarContextValue>(
|
|
85
91
|
() => ({
|
|
86
92
|
centeredTitlePaddingX,
|
|
87
|
-
|
|
93
|
+
safeArea,
|
|
88
94
|
sharedVariantProps,
|
|
89
95
|
setLeftWidth,
|
|
90
96
|
setRightWidth,
|
|
91
97
|
}),
|
|
92
|
-
[centeredTitlePaddingX,
|
|
98
|
+
[centeredTitlePaddingX, safeArea, sharedVariantProps],
|
|
93
99
|
);
|
|
94
100
|
|
|
95
101
|
return {
|
|
@@ -9,7 +9,9 @@ interface TestLynxGlobal {
|
|
|
9
9
|
lynx?: {
|
|
10
10
|
__globalProps?: {
|
|
11
11
|
safeAreaInsetTop?: number;
|
|
12
|
+
safeAreaInsetRight?: number;
|
|
12
13
|
safeAreaInsetBottom?: number;
|
|
14
|
+
safeAreaInsetLeft?: number;
|
|
13
15
|
};
|
|
14
16
|
};
|
|
15
17
|
lynxTestingEnv?: {
|
|
@@ -82,4 +84,106 @@ describe("Box", () => {
|
|
|
82
84
|
"padding-bottom": "34px",
|
|
83
85
|
});
|
|
84
86
|
});
|
|
87
|
+
|
|
88
|
+
it("resolves left and right safe area padding from global props", () => {
|
|
89
|
+
setGlobalProps({
|
|
90
|
+
safeAreaInsetRight: 62,
|
|
91
|
+
safeAreaInsetLeft: 59,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
render(
|
|
95
|
+
<Box className="box-test" pl="safeArea" pr="safeArea">
|
|
96
|
+
<Text>Box content</Text>
|
|
97
|
+
</Box>,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
101
|
+
|
|
102
|
+
expect(box).toBeInTheDocument();
|
|
103
|
+
expectStyle((box as HTMLElement).style, {
|
|
104
|
+
"padding-left": "59px",
|
|
105
|
+
"padding-right": "62px",
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("resolves margin with side over axis over all", () => {
|
|
110
|
+
render(<Box className="box-test" m="x1" mx="x2" ml="x3" />);
|
|
111
|
+
|
|
112
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
113
|
+
|
|
114
|
+
expectStyle((box as HTMLElement).style, {
|
|
115
|
+
"margin-top": "var(--seed-dimension-x1)",
|
|
116
|
+
"margin-right": "var(--seed-dimension-x2)",
|
|
117
|
+
"margin-bottom": "var(--seed-dimension-x1)",
|
|
118
|
+
"margin-left": "var(--seed-dimension-x3)",
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("keeps auto margin", () => {
|
|
123
|
+
render(<Box className="box-test" ml="auto" />);
|
|
124
|
+
|
|
125
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
126
|
+
|
|
127
|
+
expectStyle((box as HTMLElement).style, { "margin-left": "auto" });
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("negates bleed values with side over axis over all", () => {
|
|
131
|
+
render(<Box className="box-test" bleed="4px" bleedX="8px" bleedLeft="12px" />);
|
|
132
|
+
|
|
133
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
134
|
+
|
|
135
|
+
// happy-dom folds the constant `calc(4px * -1)` that Box emits.
|
|
136
|
+
expectStyle((box as HTMLElement).style, {
|
|
137
|
+
"margin-top": "calc(-4px)",
|
|
138
|
+
"margin-right": "calc(-8px)",
|
|
139
|
+
"margin-bottom": "calc(-4px)",
|
|
140
|
+
"margin-left": "calc(-12px)",
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("negates safe area bleed from global props", () => {
|
|
145
|
+
setGlobalProps({
|
|
146
|
+
safeAreaInsetRight: 62,
|
|
147
|
+
safeAreaInsetLeft: 59,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
render(<Box className="box-test" bleedX="safeArea" />);
|
|
151
|
+
|
|
152
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
153
|
+
|
|
154
|
+
expectStyle((box as HTMLElement).style, {
|
|
155
|
+
"margin-left": "calc(-59px)",
|
|
156
|
+
"margin-right": "calc(-62px)",
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("negates the env() fallback when the host omits safe area bleed insets", () => {
|
|
161
|
+
render(<Box className="box-test" bleedX="safeArea" />);
|
|
162
|
+
|
|
163
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
164
|
+
|
|
165
|
+
// happy-dom normalizes the `calc(env(...) * -1)` that Box emits.
|
|
166
|
+
expectStyle((box as HTMLElement).style, {
|
|
167
|
+
"margin-left": "calc(env(safe-area-inset-left) *-1)",
|
|
168
|
+
"margin-right": "calc(env(safe-area-inset-right) *-1)",
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("rejects dimension tokens as bleed values", () => {
|
|
173
|
+
// @ts-expect-error Lynx drops an inline calc() that contains a token's var().
|
|
174
|
+
render(<Box bleedX="x4" />);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("lets style override margin props", () => {
|
|
178
|
+
render(<Box className="box-test" mt="x4" style={{ marginTop: "3px" }} />);
|
|
179
|
+
|
|
180
|
+
const box = getRenderedRoot().querySelector(".box-test");
|
|
181
|
+
|
|
182
|
+
expectStyle((box as HTMLElement).style, { "margin-top": "3px" });
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("rejects margin and bleed props together", () => {
|
|
186
|
+
// @ts-expect-error margin and bleed props both resolve to margin-*.
|
|
187
|
+
render(<Box m="x1" bleedX="8px" />);
|
|
188
|
+
});
|
|
85
189
|
});
|
|
@@ -2,7 +2,7 @@ import clsx from "clsx";
|
|
|
2
2
|
import * as React from "@lynx-js/react";
|
|
3
3
|
|
|
4
4
|
import type { LynxPressableProps, LynxStyledElementProps, LynxViewRef } from "../../types";
|
|
5
|
-
import { useStyleProps, type StyleProps } from "../../utils/styled";
|
|
5
|
+
import { useStyleProps, type MarginBleedStyleProps, type StyleProps } from "../../utils/styled";
|
|
6
6
|
import { mergeProps } from "../../utils/merge-props";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -15,11 +15,14 @@ import { mergeProps } from "../../utils/merge-props";
|
|
|
15
15
|
* 컴포넌트 내부에서는 native tag와 recipe className을 사용하고, inline style은
|
|
16
16
|
* 런타임 값이 필요한 경우에만 제한적으로 사용합니다.
|
|
17
17
|
*/
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
export type BoxProps = StyleProps &
|
|
19
|
+
MarginBleedStyleProps &
|
|
20
|
+
LynxStyledElementProps &
|
|
21
|
+
LynxPressableProps & {
|
|
22
|
+
bindtouchstart?: () => void;
|
|
23
|
+
bindtouchend?: () => void;
|
|
24
|
+
bindtouchcancel?: () => void;
|
|
25
|
+
};
|
|
23
26
|
|
|
24
27
|
export const Box = React.forwardRef<unknown, BoxProps>((props, ref) => {
|
|
25
28
|
const { style, restProps } = useStyleProps(props);
|
|
@@ -64,4 +64,11 @@ describe("Stack", () => {
|
|
|
64
64
|
|
|
65
65
|
expect(getRenderedRoot()).toHaveStyle({ rowGap: "24px" });
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it("applies bleed as a negative margin", () => {
|
|
69
|
+
render(<HStack bleedX="16px" />);
|
|
70
|
+
|
|
71
|
+
expect(getRenderedRoot().style.getPropertyValue("margin-left")).toBe("calc(-16px)");
|
|
72
|
+
expect(getRenderedRoot().style.getPropertyValue("margin-right")).toBe("calc(-16px)");
|
|
73
|
+
});
|
|
67
74
|
});
|
|
@@ -2,7 +2,7 @@ import clsx from "clsx";
|
|
|
2
2
|
import * as React from "@lynx-js/react";
|
|
3
3
|
|
|
4
4
|
import type { LynxPressableProps, LynxStyledElementProps, LynxViewRef } from "../../types";
|
|
5
|
-
import { useStyleProps, type StyleProps } from "../../utils/styled";
|
|
5
|
+
import { useStyleProps, type MarginBleedStyleProps, type StyleProps } from "../../utils/styled";
|
|
6
6
|
import { mergeProps } from "../../utils/merge-props";
|
|
7
7
|
|
|
8
8
|
type StackStyleProps =
|
|
@@ -29,17 +29,18 @@ interface StackBaseProps extends StyleProps, LynxStyledElementProps, LynxPressab
|
|
|
29
29
|
* 패키지 컴포넌트 내부에서는 `Box`를 합성하지 않고 native tag와 recipe className을
|
|
30
30
|
* 사용해 primitive 컴포넌트 비용이 누적되지 않도록 합니다.
|
|
31
31
|
*/
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
export type StackProps = Omit<StackBaseProps, StackStyleProps> &
|
|
33
|
+
MarginBleedStyleProps & {
|
|
34
|
+
align?: StackBaseProps["alignItems"];
|
|
35
|
+
justify?: StackBaseProps["justifyContent"];
|
|
36
|
+
wrap?: StackBaseProps["flexWrap"];
|
|
37
|
+
grow?: StackBaseProps["flexGrow"];
|
|
38
|
+
shrink?: StackBaseProps["flexShrink"];
|
|
39
|
+
};
|
|
39
40
|
|
|
40
|
-
export
|
|
41
|
+
export type VStackProps = StackProps;
|
|
41
42
|
|
|
42
|
-
export
|
|
43
|
+
export type HStackProps = StackProps;
|
|
43
44
|
|
|
44
45
|
function getStackProps(props: StackProps) {
|
|
45
46
|
const { align, justify, wrap, grow, shrink, ...restProps } = props;
|
|
@@ -7,7 +7,9 @@ interface TestLynxGlobal {
|
|
|
7
7
|
lynx?: {
|
|
8
8
|
__globalProps?: {
|
|
9
9
|
safeAreaInsetTop?: number;
|
|
10
|
+
safeAreaInsetRight?: number;
|
|
10
11
|
safeAreaInsetBottom?: number;
|
|
12
|
+
safeAreaInsetLeft?: number;
|
|
11
13
|
};
|
|
12
14
|
};
|
|
13
15
|
lynxTestingEnv?: {
|
|
@@ -49,35 +51,45 @@ describe("useSafeArea", () => {
|
|
|
49
51
|
|
|
50
52
|
expect(result.current).toEqual({
|
|
51
53
|
safeAreaInsetTop: "env(safe-area-inset-top)",
|
|
54
|
+
safeAreaInsetRight: "env(safe-area-inset-right)",
|
|
52
55
|
safeAreaInsetBottom: "env(safe-area-inset-bottom)",
|
|
56
|
+
safeAreaInsetLeft: "env(safe-area-inset-left)",
|
|
53
57
|
});
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
it("uses flat globalProps values before env fallback", () => {
|
|
57
61
|
setGlobalProps({
|
|
58
62
|
safeAreaInsetTop: 48,
|
|
63
|
+
safeAreaInsetRight: 62,
|
|
59
64
|
safeAreaInsetBottom: 35,
|
|
65
|
+
safeAreaInsetLeft: 59,
|
|
60
66
|
});
|
|
61
67
|
|
|
62
68
|
const { result } = renderHook(() => useSafeArea());
|
|
63
69
|
|
|
64
70
|
expect(result.current).toEqual({
|
|
65
71
|
safeAreaInsetTop: "48px",
|
|
72
|
+
safeAreaInsetRight: "62px",
|
|
66
73
|
safeAreaInsetBottom: "35px",
|
|
74
|
+
safeAreaInsetLeft: "59px",
|
|
67
75
|
});
|
|
68
76
|
});
|
|
69
77
|
|
|
70
|
-
it("falls back to Lynx env values when host flat global props are zero", () => {
|
|
78
|
+
it("falls back to Lynx env values only for top and bottom when host flat global props are zero", () => {
|
|
71
79
|
setGlobalProps({
|
|
72
80
|
safeAreaInsetTop: 0,
|
|
81
|
+
safeAreaInsetRight: 0,
|
|
73
82
|
safeAreaInsetBottom: 0,
|
|
83
|
+
safeAreaInsetLeft: 0,
|
|
74
84
|
});
|
|
75
85
|
|
|
76
86
|
const { result } = renderHook(() => useSafeArea());
|
|
77
87
|
|
|
78
88
|
expect(result.current).toEqual({
|
|
79
89
|
safeAreaInsetTop: "env(safe-area-inset-top)",
|
|
90
|
+
safeAreaInsetRight: "0px",
|
|
80
91
|
safeAreaInsetBottom: "env(safe-area-inset-bottom)",
|
|
92
|
+
safeAreaInsetLeft: "0px",
|
|
81
93
|
});
|
|
82
94
|
});
|
|
83
95
|
});
|
package/src/hooks/useSafeArea.ts
CHANGED
|
@@ -1,56 +1,58 @@
|
|
|
1
1
|
import { useMemo } from "@lynx-js/react";
|
|
2
2
|
|
|
3
|
-
type SafeAreaEdge = "top" | "bottom";
|
|
3
|
+
type SafeAreaEdge = "top" | "right" | "bottom" | "left";
|
|
4
4
|
|
|
5
5
|
declare module "@lynx-js/types" {
|
|
6
6
|
interface GlobalProps {
|
|
7
7
|
safeAreaInsetTop?: number;
|
|
8
|
+
safeAreaInsetRight?: number;
|
|
8
9
|
safeAreaInsetBottom?: number;
|
|
10
|
+
safeAreaInsetLeft?: number;
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
bottom: "safeAreaInsetBottom",
|
|
15
|
-
};
|
|
14
|
+
function normalizeSafeAreaValue(edge: SafeAreaEdge, value: number | undefined) {
|
|
15
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return undefined;
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function normalizeSafeAreaValue(value: number | undefined): string | undefined {
|
|
22
|
-
if (typeof value !== "number" || value <= 0 || !Number.isFinite(value)) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
17
|
+
// TODO: confirm why a host-provided 0 falls back to `env()` on top and bottom. The reason isn't
|
|
18
|
+
// recorded anywhere, and a host that subtracts insets its parent already consumed (Android
|
|
19
|
+
// Compose) passes 0 on purpose, which `env()` may then override with the window's inset.
|
|
20
|
+
if (value === 0 && (edge === "top" || edge === "bottom")) return undefined;
|
|
25
21
|
|
|
26
22
|
return `${value}px`;
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
25
|
+
const resolveSafeAreaInset = (edge: SafeAreaEdge, value: number | undefined) =>
|
|
26
|
+
normalizeSafeAreaValue(edge, value) ?? `env(safe-area-inset-${edge})`;
|
|
32
27
|
|
|
33
28
|
export interface UseSafeAreaReturn {
|
|
34
29
|
safeAreaInsetTop: string;
|
|
30
|
+
safeAreaInsetRight: string;
|
|
35
31
|
safeAreaInsetBottom: string;
|
|
32
|
+
safeAreaInsetLeft: string;
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
/**
|
|
39
|
-
* Lynx 앱에서 top/bottom safe area inset 값을 반환합니다.
|
|
36
|
+
* Lynx 앱에서 top/right/bottom/left safe area inset 값을 반환합니다.
|
|
40
37
|
*
|
|
41
|
-
* `lynx.__globalProps.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
38
|
+
* `lynx.__globalProps.safeAreaInset*` 값을 우선 사용하고, host가 값을 제공하지 않으면
|
|
39
|
+
* Lynx CSS `env(safe-area-inset-*)` 값을 fallback으로 반환합니다. top/bottom은 host가
|
|
40
|
+
* `0`을 제공해도 fallback합니다.
|
|
44
41
|
*/
|
|
45
42
|
export function useSafeArea(): UseSafeAreaReturn {
|
|
46
|
-
const
|
|
47
|
-
const
|
|
43
|
+
const globalProps = lynx.__globalProps;
|
|
44
|
+
const safeAreaInsetTop = globalProps?.safeAreaInsetTop;
|
|
45
|
+
const safeAreaInsetRight = globalProps?.safeAreaInsetRight;
|
|
46
|
+
const safeAreaInsetBottom = globalProps?.safeAreaInsetBottom;
|
|
47
|
+
const safeAreaInsetLeft = globalProps?.safeAreaInsetLeft;
|
|
48
48
|
|
|
49
49
|
return useMemo(
|
|
50
50
|
() => ({
|
|
51
51
|
safeAreaInsetTop: resolveSafeAreaInset("top", safeAreaInsetTop),
|
|
52
|
+
safeAreaInsetRight: resolveSafeAreaInset("right", safeAreaInsetRight),
|
|
52
53
|
safeAreaInsetBottom: resolveSafeAreaInset("bottom", safeAreaInsetBottom),
|
|
54
|
+
safeAreaInsetLeft: resolveSafeAreaInset("left", safeAreaInsetLeft),
|
|
53
55
|
}),
|
|
54
|
-
[safeAreaInsetTop, safeAreaInsetBottom],
|
|
56
|
+
[safeAreaInsetTop, safeAreaInsetRight, safeAreaInsetBottom, safeAreaInsetLeft],
|
|
55
57
|
);
|
|
56
58
|
}
|
package/src/utils/styled.ts
CHANGED
|
@@ -76,6 +76,12 @@ export function handlePaddingWithSafeArea(
|
|
|
76
76
|
return handleDimension(padding);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
function handleBleed(bleed: BleedValue | undefined, safeAreaInset: string) {
|
|
80
|
+
if (bleed == null) return undefined;
|
|
81
|
+
|
|
82
|
+
return `calc(${bleed === "safeArea" ? safeAreaInset : bleed === 0 ? "0px" : bleed} * -1)`;
|
|
83
|
+
}
|
|
84
|
+
|
|
79
85
|
export function handleRadius(radius: string | 0 | undefined) {
|
|
80
86
|
if (radius == null) {
|
|
81
87
|
return undefined;
|
|
@@ -206,8 +212,14 @@ export interface StyleProps {
|
|
|
206
212
|
| "safeArea"
|
|
207
213
|
| (string & {});
|
|
208
214
|
pt?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
209
|
-
paddingRight?:
|
|
210
|
-
|
|
215
|
+
paddingRight?:
|
|
216
|
+
| Dimension
|
|
217
|
+
| `spacingX.${SpacingX}`
|
|
218
|
+
| `spacingY.${SpacingY}`
|
|
219
|
+
| 0
|
|
220
|
+
| "safeArea"
|
|
221
|
+
| (string & {});
|
|
222
|
+
pr?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
211
223
|
paddingBottom?:
|
|
212
224
|
| Dimension
|
|
213
225
|
| `spacingX.${SpacingX}`
|
|
@@ -216,8 +228,14 @@ export interface StyleProps {
|
|
|
216
228
|
| "safeArea"
|
|
217
229
|
| (string & {});
|
|
218
230
|
pb?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
219
|
-
paddingLeft?:
|
|
220
|
-
|
|
231
|
+
paddingLeft?:
|
|
232
|
+
| Dimension
|
|
233
|
+
| `spacingX.${SpacingX}`
|
|
234
|
+
| `spacingY.${SpacingY}`
|
|
235
|
+
| 0
|
|
236
|
+
| "safeArea"
|
|
237
|
+
| (string & {});
|
|
238
|
+
pl?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | "safeArea" | (string & {});
|
|
221
239
|
display?: "flex" | "none" | (string & {});
|
|
222
240
|
position?: "relative" | "absolute" | "fixed" | (string & {});
|
|
223
241
|
overflowX?: "visible" | "hidden" | (string & {});
|
|
@@ -241,10 +259,61 @@ export interface StyleProps {
|
|
|
241
259
|
gap?: Dimension | `spacingX.${SpacingX}` | `spacingY.${SpacingY}` | 0 | (string & {});
|
|
242
260
|
}
|
|
243
261
|
|
|
244
|
-
|
|
245
|
-
|
|
262
|
+
type MarginValue =
|
|
263
|
+
| Dimension
|
|
264
|
+
| `spacingX.${SpacingX}`
|
|
265
|
+
| `spacingY.${SpacingY}`
|
|
266
|
+
| 0
|
|
267
|
+
| "auto"
|
|
268
|
+
| (string & {});
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Dimension tokens are left out: every token resolves to `var()`, and Lynx drops an inline
|
|
272
|
+
* `calc()` that contains `var()`, so a negated token would silently apply no margin.
|
|
273
|
+
*/
|
|
274
|
+
type BleedValue = 0 | `${number}px` | "safeArea";
|
|
275
|
+
|
|
276
|
+
interface MarginStyleProps {
|
|
277
|
+
margin?: MarginValue;
|
|
278
|
+
m?: MarginValue;
|
|
279
|
+
marginX?: MarginValue;
|
|
280
|
+
mx?: MarginValue;
|
|
281
|
+
marginY?: MarginValue;
|
|
282
|
+
my?: MarginValue;
|
|
283
|
+
marginTop?: MarginValue;
|
|
284
|
+
mt?: MarginValue;
|
|
285
|
+
marginRight?: MarginValue;
|
|
286
|
+
mr?: MarginValue;
|
|
287
|
+
marginBottom?: MarginValue;
|
|
288
|
+
mb?: MarginValue;
|
|
289
|
+
marginLeft?: MarginValue;
|
|
290
|
+
ml?: MarginValue;
|
|
246
291
|
}
|
|
247
292
|
|
|
293
|
+
interface BleedStyleProps {
|
|
294
|
+
bleed?: BleedValue;
|
|
295
|
+
bleedX?: BleedValue;
|
|
296
|
+
bleedY?: BleedValue;
|
|
297
|
+
bleedTop?: BleedValue;
|
|
298
|
+
bleedRight?: BleedValue;
|
|
299
|
+
bleedBottom?: BleedValue;
|
|
300
|
+
bleedLeft?: BleedValue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Margin and bleed props both resolve to `margin-*` values, so they are mutually exclusive at
|
|
305
|
+
* the type level.
|
|
306
|
+
*/
|
|
307
|
+
export type MarginBleedStyleProps =
|
|
308
|
+
| (BleedStyleProps & { [K in keyof MarginStyleProps]?: never })
|
|
309
|
+
| (MarginStyleProps & { [K in keyof BleedStyleProps]?: never });
|
|
310
|
+
|
|
311
|
+
type UseStyleProps = StyleProps &
|
|
312
|
+
MarginStyleProps &
|
|
313
|
+
BleedStyleProps & {
|
|
314
|
+
style?: CSSProperties;
|
|
315
|
+
};
|
|
316
|
+
|
|
248
317
|
export function useStyleProps<T extends UseStyleProps>(
|
|
249
318
|
props: T,
|
|
250
319
|
): {
|
|
@@ -286,6 +355,27 @@ export function useStyleProps<T extends UseStyleProps>(
|
|
|
286
355
|
pr,
|
|
287
356
|
pb,
|
|
288
357
|
pl,
|
|
358
|
+
margin,
|
|
359
|
+
m,
|
|
360
|
+
marginX,
|
|
361
|
+
mx,
|
|
362
|
+
marginY,
|
|
363
|
+
my,
|
|
364
|
+
marginTop,
|
|
365
|
+
mt,
|
|
366
|
+
marginRight,
|
|
367
|
+
mr,
|
|
368
|
+
marginBottom,
|
|
369
|
+
mb,
|
|
370
|
+
marginLeft,
|
|
371
|
+
ml,
|
|
372
|
+
bleed,
|
|
373
|
+
bleedX,
|
|
374
|
+
bleedY,
|
|
375
|
+
bleedTop,
|
|
376
|
+
bleedRight,
|
|
377
|
+
bleedBottom,
|
|
378
|
+
bleedLeft,
|
|
289
379
|
bottom,
|
|
290
380
|
left,
|
|
291
381
|
right,
|
|
@@ -308,7 +398,8 @@ export function useStyleProps<T extends UseStyleProps>(
|
|
|
308
398
|
style,
|
|
309
399
|
...restProps
|
|
310
400
|
} = props;
|
|
311
|
-
const { safeAreaInsetTop, safeAreaInsetBottom } =
|
|
401
|
+
const { safeAreaInsetTop, safeAreaInsetRight, safeAreaInsetBottom, safeAreaInsetLeft } =
|
|
402
|
+
useSafeArea();
|
|
312
403
|
|
|
313
404
|
const backgroundValue = handleColor(background ?? bg);
|
|
314
405
|
const paddingValue = handleDimension(padding ?? p);
|
|
@@ -316,10 +407,33 @@ export function useStyleProps<T extends UseStyleProps>(
|
|
|
316
407
|
const paddingYValue = handleDimension(paddingY ?? py) ?? paddingValue;
|
|
317
408
|
const paddingTopValue =
|
|
318
409
|
handlePaddingWithSafeArea(paddingTop ?? pt, safeAreaInsetTop) ?? paddingYValue;
|
|
319
|
-
const paddingRightValue =
|
|
410
|
+
const paddingRightValue =
|
|
411
|
+
handlePaddingWithSafeArea(paddingRight ?? pr, safeAreaInsetRight) ?? paddingXValue;
|
|
320
412
|
const paddingBottomValue =
|
|
321
413
|
handlePaddingWithSafeArea(paddingBottom ?? pb, safeAreaInsetBottom) ?? paddingYValue;
|
|
322
|
-
const paddingLeftValue =
|
|
414
|
+
const paddingLeftValue =
|
|
415
|
+
handlePaddingWithSafeArea(paddingLeft ?? pl, safeAreaInsetLeft) ?? paddingXValue;
|
|
416
|
+
|
|
417
|
+
const marginValue = handleDimension(margin ?? m);
|
|
418
|
+
const marginXValue = handleDimension(marginX ?? mx) ?? marginValue;
|
|
419
|
+
const marginYValue = handleDimension(marginY ?? my) ?? marginValue;
|
|
420
|
+
const marginTopValue =
|
|
421
|
+
handleDimension(marginTop ?? mt) ??
|
|
422
|
+
marginYValue ??
|
|
423
|
+
handleBleed(bleedTop ?? bleedY ?? bleed, safeAreaInsetTop);
|
|
424
|
+
const marginRightValue =
|
|
425
|
+
handleDimension(marginRight ?? mr) ??
|
|
426
|
+
marginXValue ??
|
|
427
|
+
handleBleed(bleedRight ?? bleedX ?? bleed, safeAreaInsetRight);
|
|
428
|
+
const marginBottomValue =
|
|
429
|
+
handleDimension(marginBottom ?? mb) ??
|
|
430
|
+
marginYValue ??
|
|
431
|
+
handleBleed(bleedBottom ?? bleedY ?? bleed, safeAreaInsetBottom);
|
|
432
|
+
const marginLeftValue =
|
|
433
|
+
handleDimension(marginLeft ?? ml) ??
|
|
434
|
+
marginXValue ??
|
|
435
|
+
handleBleed(bleedLeft ?? bleedX ?? bleed, safeAreaInsetLeft);
|
|
436
|
+
|
|
323
437
|
const hasBorderStyle =
|
|
324
438
|
borderColor != null ||
|
|
325
439
|
borderWidth != null ||
|
|
@@ -354,6 +468,10 @@ export function useStyleProps<T extends UseStyleProps>(
|
|
|
354
468
|
paddingRight: paddingRightValue,
|
|
355
469
|
paddingBottom: paddingBottomValue,
|
|
356
470
|
paddingLeft: paddingLeftValue,
|
|
471
|
+
marginTop: marginTopValue,
|
|
472
|
+
marginRight: marginRightValue,
|
|
473
|
+
marginBottom: marginBottomValue,
|
|
474
|
+
marginLeft: marginLeftValue,
|
|
357
475
|
top: handleDimension(top),
|
|
358
476
|
left: handleDimension(left),
|
|
359
477
|
right: handleDimension(right),
|