@cleartrip/ct-design-container 4.0.0-SNAPSHOT-testrnwclean.5 → 4.0.0-SNAPSHOT-test.5
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/dist/Container.native.d.ts +5 -0
- package/dist/Container.native.d.ts.map +1 -0
- package/dist/index.native.d.ts +3 -0
- package/dist/index.native.d.ts.map +1 -0
- package/dist/style.native.d.ts +32 -0
- package/dist/style.native.d.ts.map +1 -0
- package/package.json +14 -7
- package/src/Container.native.tsx +139 -0
- package/src/Container.tsx +115 -0
- package/src/index.native.tsx +2 -0
- package/src/index.ts +2 -0
- package/src/style.native.ts +98 -0
- package/src/style.ts +72 -0
- package/src/type.ts +174 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Container.native.d.ts","sourceRoot":"","sources":["../packages/components/Container/src/Container.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsF,MAAM,OAAO,CAAC;AAE3G,OAAO,KAAK,EAAE,UAAU,EAAQ,YAAY,EAAE,MAAM,QAAQ,CAAC;AAS7D,QAAA,MAAM,SAAS,iFA2Hd,CAAC;AAIF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../packages/components/Container/src/index.native.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
export declare const getContainerStyles: (props: {
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
alignItems?: ViewStyle['alignItems'];
|
|
5
|
+
borderRadius?: ViewStyle['borderRadius'];
|
|
6
|
+
bottom?: ViewStyle['bottom'];
|
|
7
|
+
display?: ViewStyle['display'];
|
|
8
|
+
flex?: ViewStyle['flex'];
|
|
9
|
+
justifyContent?: ViewStyle['justifyContent'];
|
|
10
|
+
flexWrap?: ViewStyle['flexWrap'];
|
|
11
|
+
flexDirection?: ViewStyle['flexDirection'];
|
|
12
|
+
rowGap?: number | undefined;
|
|
13
|
+
columnGap?: number | undefined;
|
|
14
|
+
left?: ViewStyle['left'];
|
|
15
|
+
position?: ViewStyle['position'];
|
|
16
|
+
right?: ViewStyle['right'];
|
|
17
|
+
top?: ViewStyle['top'];
|
|
18
|
+
zIndex?: ViewStyle['zIndex'];
|
|
19
|
+
paddingTop?: ViewStyle['paddingTop'];
|
|
20
|
+
paddingBottom?: ViewStyle['paddingBottom'];
|
|
21
|
+
paddingLeft?: ViewStyle['paddingLeft'];
|
|
22
|
+
paddingRight?: ViewStyle['paddingRight'];
|
|
23
|
+
marginTop?: ViewStyle['marginTop'];
|
|
24
|
+
marginBottom?: ViewStyle['marginBottom'];
|
|
25
|
+
marginLeft?: ViewStyle['marginLeft'];
|
|
26
|
+
marginRight?: ViewStyle['marginRight'];
|
|
27
|
+
backgroundColor?: ViewStyle['backgroundColor'];
|
|
28
|
+
width?: ViewStyle['width'];
|
|
29
|
+
height?: ViewStyle['height'];
|
|
30
|
+
textAlign?: any;
|
|
31
|
+
}) => ViewStyle;
|
|
32
|
+
//# sourceMappingURL=style.native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.native.d.ts","sourceRoot":"","sources":["../packages/components/Container/src/style.native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAM9C,eAAO,MAAM,kBAAkB;;iBAChB,SAAS,CAAC,YAAY,CAAC;mBACrB,SAAS,CAAC,cAAc,CAAC;aAC/B,SAAS,CAAC,QAAQ,CAAC;cAClB,SAAS,CAAC,SAAS,CAAC;WACvB,SAAS,CAAC,MAAM,CAAC;qBACP,SAAS,CAAC,gBAAgB,CAAC;eACjC,SAAS,CAAC,UAAU,CAAC;oBAChB,SAAS,CAAC,eAAe,CAAC;;;WAGnC,SAAS,CAAC,MAAM,CAAC;eACb,SAAS,CAAC,UAAU,CAAC;YACxB,SAAS,CAAC,OAAO,CAAC;UACpB,SAAS,CAAC,KAAK,CAAC;aACb,SAAS,CAAC,QAAQ,CAAC;iBACf,SAAS,CAAC,YAAY,CAAC;oBACpB,SAAS,CAAC,eAAe,CAAC;kBAC5B,SAAS,CAAC,aAAa,CAAC;mBACvB,SAAS,CAAC,cAAc,CAAC;gBAC5B,SAAS,CAAC,WAAW,CAAC;mBACnB,SAAS,CAAC,cAAc,CAAC;iBAC3B,SAAS,CAAC,YAAY,CAAC;kBACtB,SAAS,CAAC,aAAa,CAAC;sBACpB,SAAS,CAAC,iBAAiB,CAAC;YACtC,SAAS,CAAC,OAAO,CAAC;aACjB,SAAS,CAAC,QAAQ,CAAC;;MAG1B,SA8DH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleartrip/ct-design-container",
|
|
3
|
-
"version": "4.0.0-SNAPSHOT-
|
|
3
|
+
"version": "4.0.0-SNAPSHOT-test.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/ct-design-container.cjs.js",
|
|
7
7
|
"jsnext:main": "dist/ct-design-container.esm.js",
|
|
8
8
|
"module": "dist/ct-design-container.esm.js",
|
|
9
|
-
"react-native": "index.native.
|
|
9
|
+
"react-native": "src/index.native.tsx",
|
|
10
10
|
"sideEffects": false,
|
|
11
11
|
"browser": {
|
|
12
12
|
"./dist/ct-design-container.esm.js": "./dist/ct-design-container.browser.esm.js",
|
|
13
13
|
"./dist/ct-design-container.cjs.js": "./dist/ct-design-container.browser.cjs.js"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
17
18
|
],
|
|
18
19
|
"dependencies": {
|
|
19
|
-
"@cleartrip/ct-design-style-manager": "4.0.0-SNAPSHOT-
|
|
20
|
+
"@cleartrip/ct-design-style-manager": "4.0.0-SNAPSHOT-test.5"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@emotion/babel-plugin": "^11.12.0",
|
|
23
|
-
"@cleartrip/ct-design-
|
|
24
|
-
"@cleartrip/ct-design-
|
|
24
|
+
"@cleartrip/ct-design-theme": "4.0.0-SNAPSHOT-test.5",
|
|
25
|
+
"@cleartrip/ct-design-types": "4.0.0-SNAPSHOT-test.5"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"react": ">=16.8.0",
|
|
28
|
-
"react-dom": ">=16.8.0"
|
|
29
|
+
"react-dom": ">=16.8.0",
|
|
30
|
+
"react-native": ">=0.71.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"react-native": {
|
|
34
|
+
"optional": true
|
|
35
|
+
}
|
|
29
36
|
},
|
|
30
37
|
"publishConfig": {
|
|
31
38
|
"access": "public"
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback, useImperativeHandle, useRef, type MutableRefObject } from 'react';
|
|
2
|
+
import { View, StyleSheet, Pressable, type LayoutChangeEvent, type NativeSyntheticEvent } from 'react-native';
|
|
3
|
+
import type { IContainer, Rect, ContainerRef } from './type';
|
|
4
|
+
import { getContainerStyles } from './style.native';
|
|
5
|
+
|
|
6
|
+
const defaultRootStyle = StyleSheet.create({
|
|
7
|
+
root: {
|
|
8
|
+
flexDirection: 'column',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const Container = forwardRef<ContainerRef, IContainer>(
|
|
13
|
+
(
|
|
14
|
+
{
|
|
15
|
+
id,
|
|
16
|
+
children,
|
|
17
|
+
styleConfig,
|
|
18
|
+
onLayout,
|
|
19
|
+
pointerEvents,
|
|
20
|
+
testID,
|
|
21
|
+
nativeID,
|
|
22
|
+
collapsable,
|
|
23
|
+
removeClippedSubviews,
|
|
24
|
+
shouldRasterizeIOS,
|
|
25
|
+
focusable,
|
|
26
|
+
onClick,
|
|
27
|
+
...rest
|
|
28
|
+
},
|
|
29
|
+
forwardedRef,
|
|
30
|
+
) => {
|
|
31
|
+
const localRef = useRef<View>(null);
|
|
32
|
+
const layoutRef = useRef<Rect>({ x: 0, y: 0, width: 0, height: 0 });
|
|
33
|
+
|
|
34
|
+
const handleLayout = useCallback(
|
|
35
|
+
(event: NativeSyntheticEvent<LayoutChangeEvent>) => {
|
|
36
|
+
const { layout } = event.nativeEvent;
|
|
37
|
+
layoutRef.current = {
|
|
38
|
+
x: layout.x,
|
|
39
|
+
y: layout.y,
|
|
40
|
+
width: layout.width,
|
|
41
|
+
height: layout.height,
|
|
42
|
+
};
|
|
43
|
+
onLayout?.(event);
|
|
44
|
+
},
|
|
45
|
+
[onLayout],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const handleFocus = useCallback(() => {
|
|
49
|
+
(localRef.current as unknown as { focus?: () => void })?.focus?.();
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const handleGetBoundingRect = useCallback((callback?: (rect: Rect) => void) => {
|
|
53
|
+
const measure = () => {
|
|
54
|
+
localRef.current?.measureInWindow((x, y, width, height) => {
|
|
55
|
+
const rect = { x, y, width, height };
|
|
56
|
+
layoutRef.current = rect;
|
|
57
|
+
callback?.(rect);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
if (layoutRef.current.width !== 0 || layoutRef.current.height !== 0) {
|
|
61
|
+
callback?.(layoutRef.current);
|
|
62
|
+
} else {
|
|
63
|
+
measure();
|
|
64
|
+
}
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
const handleAddEventListener = useCallback(
|
|
68
|
+
(_type: string, _listener: EventListener, _options?: boolean | AddEventListenerOptions) => {
|
|
69
|
+
// No-op on React Native View; retain API compatibility with web ref
|
|
70
|
+
},
|
|
71
|
+
[],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const handleRemoveEventListener = useCallback(
|
|
75
|
+
(_type: string, _listener: EventListener, _options?: boolean | EventListenerOptions) => {
|
|
76
|
+
// No-op on React Native View; retain API compatibility with web ref
|
|
77
|
+
},
|
|
78
|
+
[],
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
useImperativeHandle(
|
|
82
|
+
forwardedRef,
|
|
83
|
+
() =>
|
|
84
|
+
({
|
|
85
|
+
focus: handleFocus,
|
|
86
|
+
getBoundingRectWithCallback: handleGetBoundingRect,
|
|
87
|
+
getElementRef: () => localRef as MutableRefObject<HTMLDivElement | null>,
|
|
88
|
+
classList: {
|
|
89
|
+
add: (_className: string) => {
|
|
90
|
+
// No-op on RN; retain API compatibility
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
addEventListener: handleAddEventListener,
|
|
94
|
+
removeEventListener: handleRemoveEventListener,
|
|
95
|
+
get style() {
|
|
96
|
+
return {} as CSSStyleDeclaration;
|
|
97
|
+
},
|
|
98
|
+
get offsetWidth() {
|
|
99
|
+
return layoutRef.current?.width ?? 0;
|
|
100
|
+
},
|
|
101
|
+
}) as ContainerRef,
|
|
102
|
+
[handleFocus, handleGetBoundingRect, handleAddEventListener, handleRemoveEventListener],
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const { root: rootStyles = [] } = styleConfig || {};
|
|
106
|
+
const mergedStyle = [
|
|
107
|
+
defaultRootStyle.root,
|
|
108
|
+
getContainerStyles(rest as Parameters<typeof getContainerStyles>[0]),
|
|
109
|
+
...(Array.isArray(rootStyles) ? rootStyles : [rootStyles].filter(Boolean)),
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
const viewProps = {
|
|
113
|
+
ref: localRef,
|
|
114
|
+
nativeID: id ?? nativeID,
|
|
115
|
+
testID,
|
|
116
|
+
onLayout: handleLayout,
|
|
117
|
+
pointerEvents,
|
|
118
|
+
collapsable,
|
|
119
|
+
removeClippedSubviews,
|
|
120
|
+
shouldRasterizeIOS,
|
|
121
|
+
focusable,
|
|
122
|
+
style: mergedStyle,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
if (onClick) {
|
|
126
|
+
return (
|
|
127
|
+
<Pressable ref={localRef} onPress={onClick as () => void} {...viewProps}>
|
|
128
|
+
{children}
|
|
129
|
+
</Pressable>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return <View {...viewProps}>{children}</View>;
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
Container.displayName = 'Container';
|
|
138
|
+
|
|
139
|
+
export default Container;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
|
|
2
|
+
import { ForwardRefComponentWithStyle, OwnProps } from '@cleartrip/ct-design-types';
|
|
3
|
+
import styled from '@emotion/styled';
|
|
4
|
+
import { makeStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
|
|
5
|
+
import { getContainerStyles } from './style';
|
|
6
|
+
import { IContainer, Rect, ContainerRef } from './type';
|
|
7
|
+
|
|
8
|
+
type PolymorphicContainer = ForwardRefComponentWithStyle<
|
|
9
|
+
'main' | 'section' | 'article' | 'div' | 'span' | 'p',
|
|
10
|
+
IContainer
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
// Added below to sync with RN as flexDirection is mostly used as column
|
|
14
|
+
const staticContainerStyles = makeStyles(() => {
|
|
15
|
+
return {
|
|
16
|
+
root: {
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const StyledContainer = styled.div<OwnProps<PolymorphicContainer>>(
|
|
23
|
+
({
|
|
24
|
+
id,
|
|
25
|
+
css,
|
|
26
|
+
children,
|
|
27
|
+
onClick,
|
|
28
|
+
onAnimationEnd,
|
|
29
|
+
onAnimationStart,
|
|
30
|
+
onDoubleClick,
|
|
31
|
+
onBlur,
|
|
32
|
+
onTouchStart,
|
|
33
|
+
onTouchEnd,
|
|
34
|
+
onMouseEnter,
|
|
35
|
+
onMouseLeave,
|
|
36
|
+
onFocus,
|
|
37
|
+
onKeyDown,
|
|
38
|
+
onPointerEnter,
|
|
39
|
+
onPointerLeave,
|
|
40
|
+
onTouchCancel,
|
|
41
|
+
onTouchMove,
|
|
42
|
+
...rest
|
|
43
|
+
}) => getContainerStyles({ ...rest, ...css }),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const Container = forwardRef<ContainerRef, IContainer>(
|
|
47
|
+
({ id, as = 'div', children, styleConfig, ...rest }, forwardedRef) => {
|
|
48
|
+
const localRef = useRef<HTMLDivElement | null>(null);
|
|
49
|
+
|
|
50
|
+
// Focuses the container element programmatically
|
|
51
|
+
const handleFocus = useCallback(() => {
|
|
52
|
+
localRef.current?.focus();
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
// Gets the bounding rectangle dimensions and position of the container
|
|
56
|
+
const handleGetBoundingRect = useCallback((callback?: (rect: Rect) => void) => {
|
|
57
|
+
const rect = localRef.current?.getBoundingClientRect();
|
|
58
|
+
// Only invoke callback if the element exists and has a bounding rect
|
|
59
|
+
if (rect) {
|
|
60
|
+
callback?.({
|
|
61
|
+
x: rect.x,
|
|
62
|
+
y: rect.y,
|
|
63
|
+
width: rect.width,
|
|
64
|
+
height: rect.height,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
const handleAddEventListener = useCallback(
|
|
70
|
+
(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) => {
|
|
71
|
+
localRef.current?.addEventListener(type, listener, options);
|
|
72
|
+
},
|
|
73
|
+
[],
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const handleRemoveEventListener = useCallback(
|
|
77
|
+
(type: string, listener: EventListener, options?: boolean | EventListenerOptions) => {
|
|
78
|
+
localRef.current?.removeEventListener(type, listener, options);
|
|
79
|
+
},
|
|
80
|
+
[],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Using useImperativeHandle to limit the number of methods exposed to the parent, In order to sync with RN
|
|
84
|
+
useImperativeHandle(
|
|
85
|
+
forwardedRef,
|
|
86
|
+
() => ({
|
|
87
|
+
focus: handleFocus,
|
|
88
|
+
getBoundingRectWithCallback: handleGetBoundingRect,
|
|
89
|
+
getElementRef: () => localRef,
|
|
90
|
+
addEventListener: handleAddEventListener,
|
|
91
|
+
removeEventListener: handleRemoveEventListener,
|
|
92
|
+
get style() {
|
|
93
|
+
return localRef.current?.style || ({} as CSSStyleDeclaration);
|
|
94
|
+
},
|
|
95
|
+
get offsetWidth() {
|
|
96
|
+
return localRef.current?.offsetWidth || 0;
|
|
97
|
+
},
|
|
98
|
+
// Need more methods if required here
|
|
99
|
+
}),
|
|
100
|
+
[handleFocus, handleGetBoundingRect, handleAddEventListener, handleRemoveEventListener],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const { root: rootStyles = [] } = styleConfig || {};
|
|
104
|
+
|
|
105
|
+
const mergedRootStyles = useWebMergeStyles([staticContainerStyles.root, ...rootStyles], [rootStyles]);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<StyledContainer id={id} ref={localRef} as={as} className={mergedRootStyles} {...rest}>
|
|
109
|
+
{children}
|
|
110
|
+
</StyledContainer>
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
) as PolymorphicContainer;
|
|
114
|
+
|
|
115
|
+
export default Container;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns React Native ViewStyle from container props.
|
|
5
|
+
* Mirrors the web getContainerStyles API for cross-platform usage.
|
|
6
|
+
*/
|
|
7
|
+
export const getContainerStyles = (props: {
|
|
8
|
+
alignItems?: ViewStyle['alignItems'];
|
|
9
|
+
borderRadius?: ViewStyle['borderRadius'];
|
|
10
|
+
bottom?: ViewStyle['bottom'];
|
|
11
|
+
display?: ViewStyle['display'];
|
|
12
|
+
flex?: ViewStyle['flex'];
|
|
13
|
+
justifyContent?: ViewStyle['justifyContent'];
|
|
14
|
+
flexWrap?: ViewStyle['flexWrap'];
|
|
15
|
+
flexDirection?: ViewStyle['flexDirection'];
|
|
16
|
+
rowGap?: number;
|
|
17
|
+
columnGap?: number;
|
|
18
|
+
left?: ViewStyle['left'];
|
|
19
|
+
position?: ViewStyle['position'];
|
|
20
|
+
right?: ViewStyle['right'];
|
|
21
|
+
top?: ViewStyle['top'];
|
|
22
|
+
zIndex?: ViewStyle['zIndex'];
|
|
23
|
+
paddingTop?: ViewStyle['paddingTop'];
|
|
24
|
+
paddingBottom?: ViewStyle['paddingBottom'];
|
|
25
|
+
paddingLeft?: ViewStyle['paddingLeft'];
|
|
26
|
+
paddingRight?: ViewStyle['paddingRight'];
|
|
27
|
+
marginTop?: ViewStyle['marginTop'];
|
|
28
|
+
marginBottom?: ViewStyle['marginBottom'];
|
|
29
|
+
marginLeft?: ViewStyle['marginLeft'];
|
|
30
|
+
marginRight?: ViewStyle['marginRight'];
|
|
31
|
+
backgroundColor?: ViewStyle['backgroundColor'];
|
|
32
|
+
width?: ViewStyle['width'];
|
|
33
|
+
height?: ViewStyle['height'];
|
|
34
|
+
textAlign?: ViewStyle['textAlign'];
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}): ViewStyle => {
|
|
37
|
+
const {
|
|
38
|
+
alignItems,
|
|
39
|
+
borderRadius,
|
|
40
|
+
bottom,
|
|
41
|
+
display,
|
|
42
|
+
flex,
|
|
43
|
+
justifyContent,
|
|
44
|
+
flexWrap,
|
|
45
|
+
flexDirection,
|
|
46
|
+
rowGap,
|
|
47
|
+
columnGap,
|
|
48
|
+
left,
|
|
49
|
+
position,
|
|
50
|
+
right,
|
|
51
|
+
top,
|
|
52
|
+
zIndex,
|
|
53
|
+
paddingTop,
|
|
54
|
+
paddingBottom,
|
|
55
|
+
paddingLeft,
|
|
56
|
+
paddingRight,
|
|
57
|
+
marginTop,
|
|
58
|
+
marginBottom,
|
|
59
|
+
marginLeft,
|
|
60
|
+
marginRight,
|
|
61
|
+
backgroundColor,
|
|
62
|
+
width,
|
|
63
|
+
height,
|
|
64
|
+
textAlign,
|
|
65
|
+
...rest
|
|
66
|
+
} = props;
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
alignItems,
|
|
70
|
+
borderRadius,
|
|
71
|
+
bottom,
|
|
72
|
+
display,
|
|
73
|
+
flex,
|
|
74
|
+
justifyContent,
|
|
75
|
+
flexWrap,
|
|
76
|
+
flexDirection,
|
|
77
|
+
rowGap,
|
|
78
|
+
columnGap,
|
|
79
|
+
left,
|
|
80
|
+
position,
|
|
81
|
+
right,
|
|
82
|
+
top,
|
|
83
|
+
zIndex,
|
|
84
|
+
paddingTop,
|
|
85
|
+
paddingBottom,
|
|
86
|
+
paddingLeft,
|
|
87
|
+
paddingRight,
|
|
88
|
+
marginTop,
|
|
89
|
+
marginBottom,
|
|
90
|
+
marginLeft,
|
|
91
|
+
marginRight,
|
|
92
|
+
backgroundColor,
|
|
93
|
+
width,
|
|
94
|
+
height,
|
|
95
|
+
textAlign,
|
|
96
|
+
...rest,
|
|
97
|
+
} as ViewStyle;
|
|
98
|
+
};
|
package/src/style.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { CSSObject } from '@emotion/styled';
|
|
2
|
+
|
|
3
|
+
export const getContainerStyles = ({
|
|
4
|
+
alignItems,
|
|
5
|
+
borderRadius,
|
|
6
|
+
boxShadow,
|
|
7
|
+
bottom,
|
|
8
|
+
display,
|
|
9
|
+
flex,
|
|
10
|
+
justifyContent,
|
|
11
|
+
flexWrap,
|
|
12
|
+
flexDirection,
|
|
13
|
+
rowGap,
|
|
14
|
+
columnGap,
|
|
15
|
+
left,
|
|
16
|
+
position,
|
|
17
|
+
right,
|
|
18
|
+
top,
|
|
19
|
+
zIndex,
|
|
20
|
+
paddingTop,
|
|
21
|
+
paddingBottom,
|
|
22
|
+
paddingLeft,
|
|
23
|
+
paddingRight,
|
|
24
|
+
marginTop,
|
|
25
|
+
marginBottom,
|
|
26
|
+
marginLeft,
|
|
27
|
+
marginRight,
|
|
28
|
+
backgroundColor,
|
|
29
|
+
cursor,
|
|
30
|
+
width,
|
|
31
|
+
height,
|
|
32
|
+
wordBreak,
|
|
33
|
+
theme,
|
|
34
|
+
textAlign,
|
|
35
|
+
gridTemplateColumns,
|
|
36
|
+
...rest
|
|
37
|
+
}: any): CSSObject => {
|
|
38
|
+
return {
|
|
39
|
+
alignItems,
|
|
40
|
+
borderRadius,
|
|
41
|
+
boxShadow,
|
|
42
|
+
bottom,
|
|
43
|
+
display,
|
|
44
|
+
flex,
|
|
45
|
+
justifyContent,
|
|
46
|
+
flexWrap,
|
|
47
|
+
flexDirection,
|
|
48
|
+
rowGap,
|
|
49
|
+
columnGap,
|
|
50
|
+
left,
|
|
51
|
+
position,
|
|
52
|
+
right,
|
|
53
|
+
top,
|
|
54
|
+
zIndex,
|
|
55
|
+
paddingTop,
|
|
56
|
+
paddingBottom,
|
|
57
|
+
paddingLeft,
|
|
58
|
+
paddingRight,
|
|
59
|
+
marginTop,
|
|
60
|
+
marginBottom,
|
|
61
|
+
marginLeft,
|
|
62
|
+
marginRight,
|
|
63
|
+
backgroundColor,
|
|
64
|
+
cursor,
|
|
65
|
+
width,
|
|
66
|
+
height,
|
|
67
|
+
wordBreak,
|
|
68
|
+
textAlign,
|
|
69
|
+
gridTemplateColumns,
|
|
70
|
+
...rest,
|
|
71
|
+
};
|
|
72
|
+
};
|
package/src/type.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { MouseEventHandler, MouseEvent, KeyboardEvent, MutableRefObject } from 'react';
|
|
2
|
+
import type { CSSProperties } from 'react';
|
|
3
|
+
import type {
|
|
4
|
+
HtmlCompositeAttributes,
|
|
5
|
+
Styles,
|
|
6
|
+
CrossPlatformViewProps,
|
|
7
|
+
LayoutChangeEvent,
|
|
8
|
+
} from '@cleartrip/ct-design-types';
|
|
9
|
+
|
|
10
|
+
export type ContainerDefaultProps = {
|
|
11
|
+
display?: CSSProperties['display'];
|
|
12
|
+
flex?: CSSProperties['flex'];
|
|
13
|
+
alignItems?: CSSProperties['alignItems'];
|
|
14
|
+
borderRadius?: CSSProperties['borderRadius'];
|
|
15
|
+
boxShadow?: CSSProperties['boxShadow'];
|
|
16
|
+
justifyContent?: CSSProperties['justifyContent'];
|
|
17
|
+
flexWrap?: CSSProperties['flexWrap'];
|
|
18
|
+
flexDirection?: CSSProperties['flexDirection'];
|
|
19
|
+
rowGap?: CSSProperties['rowGap'];
|
|
20
|
+
columnGap?: CSSProperties['columnGap'];
|
|
21
|
+
gridTemplateColumns?: CSSProperties['gridTemplateColumns'];
|
|
22
|
+
className?: string;
|
|
23
|
+
position?: CSSProperties['position'];
|
|
24
|
+
top?: CSSProperties['top'];
|
|
25
|
+
bottom?: CSSProperties['bottom'];
|
|
26
|
+
left?: CSSProperties['left'];
|
|
27
|
+
right?: CSSProperties['right'];
|
|
28
|
+
zIndex?: CSSProperties['zIndex'];
|
|
29
|
+
paddingTop?: CSSProperties['paddingTop'];
|
|
30
|
+
paddingBottom?: CSSProperties['paddingBottom'];
|
|
31
|
+
paddingLeft?: CSSProperties['paddingLeft'];
|
|
32
|
+
paddingRight?: CSSProperties['paddingRight'];
|
|
33
|
+
marginTop?: CSSProperties['marginTop'];
|
|
34
|
+
marginBottom?: CSSProperties['marginBottom'];
|
|
35
|
+
marginLeft?: CSSProperties['marginLeft'];
|
|
36
|
+
marginRight?: CSSProperties['marginRight'];
|
|
37
|
+
backgroundColor?: CSSProperties['backgroundColor'];
|
|
38
|
+
cursor?: CSSProperties['cursor'];
|
|
39
|
+
width?: CSSProperties['width'];
|
|
40
|
+
height?: CSSProperties['height'];
|
|
41
|
+
wordBreak?: CSSProperties['wordBreak'];
|
|
42
|
+
textAlign?: CSSProperties['textAlign'];
|
|
43
|
+
borderLeft?: CSSProperties['borderLeft'];
|
|
44
|
+
padding?: CSSProperties['padding'];
|
|
45
|
+
border?: CSSProperties['border'];
|
|
46
|
+
background?: CSSProperties['background'];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export interface ContainerProps
|
|
50
|
+
extends Omit<HtmlCompositeAttributes<ContainerDefaultProps, 'Div'>, 'pointerEvents'>,
|
|
51
|
+
ContainerDefaultProps {}
|
|
52
|
+
|
|
53
|
+
export type HapticVariant = 'subtle' | 'loud';
|
|
54
|
+
|
|
55
|
+
export interface HapticFeedbackProps {
|
|
56
|
+
/**
|
|
57
|
+
* Enables haptic feedback on interaction with the container.
|
|
58
|
+
* When true, the container will trigger haptic feedback on click/tap events.
|
|
59
|
+
* @example
|
|
60
|
+
* <Component hapticEnabled={true} />
|
|
61
|
+
*/
|
|
62
|
+
hapticEnabled?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Specifies the intensity of the haptic feedback.
|
|
66
|
+
* - 'light': Light haptic feedback, suitable for most interactions
|
|
67
|
+
* - 'loud': Strong haptic feedback, for more prominent interactions
|
|
68
|
+
* @example
|
|
69
|
+
* <Component hapticEnabled={true} hapticVariant="subtle" />
|
|
70
|
+
*/
|
|
71
|
+
hapticVariant?: HapticVariant;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* When enabled, the haptic feedback will repeat continuously while the interaction is active.
|
|
75
|
+
* Useful for long-press or drag interactions.
|
|
76
|
+
* @example
|
|
77
|
+
* <Component hapticEnabled={true} hapticRepeat={true} />
|
|
78
|
+
*/
|
|
79
|
+
hapticRepeat?: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface IContainer extends ContainerProps, CrossPlatformViewProps, HapticFeedbackProps {
|
|
83
|
+
/**
|
|
84
|
+
* Unique identifier for the container element
|
|
85
|
+
*/
|
|
86
|
+
id?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Content to be rendered inside the container
|
|
89
|
+
*/
|
|
90
|
+
children?: React.ReactNode;
|
|
91
|
+
/**
|
|
92
|
+
* Controls the visibility of scroll indicators (if applicable)
|
|
93
|
+
*/
|
|
94
|
+
showScrollIndicator?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* The type of HTML element to be used for rendering
|
|
97
|
+
*/
|
|
98
|
+
as?: 'main' | 'section' | 'article' | 'div' | 'p' | 'span';
|
|
99
|
+
/**
|
|
100
|
+
* Callback when user clicks on the container
|
|
101
|
+
*/
|
|
102
|
+
onClick?: ((event: MouseEvent<any>) => void) | ((event: MouseEvent<any> | KeyboardEvent<any>) => void) | (() => void);
|
|
103
|
+
/**
|
|
104
|
+
* Callback for layout changes. Works only for native.
|
|
105
|
+
*/
|
|
106
|
+
onLayout?: (event: LayoutChangeEvent) => void;
|
|
107
|
+
/**
|
|
108
|
+
* Custom style configuration for the container
|
|
109
|
+
*/
|
|
110
|
+
styleConfig?: {
|
|
111
|
+
root?: Styles[];
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Triggered when the mouse enters the container.
|
|
115
|
+
*/
|
|
116
|
+
onMouseEnter?: MouseEventHandler<HTMLElement>;
|
|
117
|
+
/**
|
|
118
|
+
* Triggered when the mouse leaves the container.
|
|
119
|
+
*/
|
|
120
|
+
onMouseLeave?: MouseEventHandler<HTMLElement>;
|
|
121
|
+
/**
|
|
122
|
+
* The component to be used for rendering
|
|
123
|
+
*/
|
|
124
|
+
ComponentToRender?: React.ComponentType<HTMLElement>;
|
|
125
|
+
/**
|
|
126
|
+
* Triggered when the transition ends
|
|
127
|
+
*/
|
|
128
|
+
onTransitionEnd?: () => void;
|
|
129
|
+
}
|
|
130
|
+
export interface Rect {
|
|
131
|
+
x: number;
|
|
132
|
+
y: number;
|
|
133
|
+
width: number;
|
|
134
|
+
height: number;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface ContainerRef {
|
|
138
|
+
/**
|
|
139
|
+
* Focuses the container element programmatically
|
|
140
|
+
*/
|
|
141
|
+
focus: () => void;
|
|
142
|
+
/**
|
|
143
|
+
* Gets the bounding rectangle of the container with a callback
|
|
144
|
+
*/
|
|
145
|
+
getBoundingRectWithCallback: (callback?: (rect: Rect) => void) => void;
|
|
146
|
+
/**
|
|
147
|
+
* Gets the element reference
|
|
148
|
+
*/
|
|
149
|
+
getElementRef: () => MutableRefObject<HTMLDivElement | null>;
|
|
150
|
+
/**
|
|
151
|
+
* Gets the class list of the container
|
|
152
|
+
*/
|
|
153
|
+
classList: {
|
|
154
|
+
add: (className: string) => void;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Adds an event listener to the container element
|
|
158
|
+
*/
|
|
159
|
+
addEventListener: (type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) => void;
|
|
160
|
+
/**
|
|
161
|
+
* Removes an event listener from the container element
|
|
162
|
+
*/
|
|
163
|
+
removeEventListener: (type: string, listener: EventListener, options?: boolean | EventListenerOptions) => void;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Gets the style object of the DOM element
|
|
167
|
+
*/
|
|
168
|
+
readonly style: CSSStyleDeclaration;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Width of the element including padding but excluding borders, margins, and scrollbars
|
|
172
|
+
*/
|
|
173
|
+
readonly offsetWidth: number;
|
|
174
|
+
}
|