@cleartrip/ct-design-container 4.0.0 → 4.1.0-SNAPSHOT-native-main.1

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.
@@ -0,0 +1,137 @@
1
+ import {
2
+ CSSProperties,
3
+ forwardRef,
4
+ MutableRefObject,
5
+ useCallback,
6
+ useImperativeHandle,
7
+ useLayoutEffect,
8
+ useRef,
9
+ } from 'react';
10
+ import { makeStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
11
+ import { IContainer, Rect, ContainerRef } from './type';
12
+
13
+ // Added below to sync with RN as flexDirection is mostly used as column
14
+ const staticContainerStyles = makeStyles(() => {
15
+ return {
16
+ root: {
17
+ display: 'flex',
18
+ flexDirection: 'column',
19
+ },
20
+ };
21
+ });
22
+
23
+ const Container = forwardRef<ContainerRef, IContainer>(
24
+ (
25
+ {
26
+ id,
27
+ as: ContainerAs = 'div',
28
+ children,
29
+ styleConfig,
30
+ onClick,
31
+ onLayout,
32
+ onMouseEnter,
33
+ onMouseLeave,
34
+ onTransitionEnd,
35
+ onTouchStart,
36
+ onTouchEnd,
37
+ onTouchCancel,
38
+ onTouchMove,
39
+ },
40
+ forwardedRef,
41
+ ) => {
42
+ const localRef = useRef<HTMLDivElement | null>(null);
43
+
44
+ // Focuses the container element programmatically
45
+ const handleFocus = useCallback(() => {
46
+ localRef.current?.focus();
47
+ }, []);
48
+
49
+ // Gets the bounding rectangle dimensions and position of the container
50
+ const handleGetBoundingRect = useCallback((callback?: (rect: Rect) => void) => {
51
+ const rect = localRef.current?.getBoundingClientRect();
52
+ // Only invoke callback if the element exists and has a bounding rect
53
+ if (rect) {
54
+ callback?.({
55
+ x: rect.x,
56
+ y: rect.y,
57
+ width: rect.width,
58
+ height: rect.height,
59
+ });
60
+ }
61
+ }, []);
62
+
63
+ const handleAddEventListener = useCallback(
64
+ (type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) => {
65
+ localRef.current?.addEventListener(type, listener, options);
66
+ },
67
+ [],
68
+ );
69
+
70
+ const handleRemoveEventListener = useCallback(
71
+ (type: string, listener: EventListener, options?: boolean | EventListenerOptions) => {
72
+ localRef.current?.removeEventListener(type, listener, options);
73
+ },
74
+ [],
75
+ );
76
+
77
+ // Using useImperativeHandle to limit the number of methods exposed to the parent, In order to sync with RN
78
+ useImperativeHandle(
79
+ forwardedRef,
80
+ () => ({
81
+ focus: handleFocus,
82
+ getBoundingRectWithCallback: handleGetBoundingRect,
83
+ getElementRef: () => localRef as MutableRefObject<ContainerRef | null>,
84
+ style: (localRef.current?.style || {}) as CSSProperties,
85
+ classList: {
86
+ add: (className: string) => {
87
+ localRef.current?.classList.add(className);
88
+ },
89
+ },
90
+ measure: (
91
+ _callback: (x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void,
92
+ ) => {
93
+ localRef.current?.getBoundingClientRect();
94
+ },
95
+ addEventListener: handleAddEventListener,
96
+ removeEventListener: handleRemoveEventListener,
97
+ }),
98
+ [handleFocus, handleGetBoundingRect, handleAddEventListener, handleRemoveEventListener],
99
+ );
100
+
101
+ const { root: rootStyles = [] } = styleConfig || {};
102
+
103
+ const mergedRootStyles = useWebMergeStyles([staticContainerStyles.root, ...rootStyles], [rootStyles]);
104
+
105
+ useLayoutEffect(() => {
106
+ onLayout?.({
107
+ layout: {
108
+ height: localRef.current?.clientHeight ?? 0,
109
+ width: localRef.current?.clientWidth ?? 0,
110
+ x: localRef.current?.getBoundingClientRect().x ?? 0,
111
+ y: localRef.current?.getBoundingClientRect().y ?? 0,
112
+ },
113
+ });
114
+ }, [onLayout]);
115
+
116
+ return (
117
+ <ContainerAs
118
+ id={id}
119
+ ref={localRef}
120
+ className={mergedRootStyles}
121
+ onClick={onClick}
122
+ onMouseEnter={onMouseEnter}
123
+ onMouseLeave={onMouseLeave}
124
+ onTransitionEnd={onTransitionEnd}
125
+ onTouchStart={onTouchStart}
126
+ onTouchEnd={onTouchEnd}
127
+ onTouchCancel={onTouchCancel}
128
+ onTouchMove={onTouchMove}
129
+ >
130
+ {children}
131
+ </ContainerAs>
132
+ );
133
+ },
134
+ );
135
+
136
+ Container.displayName = 'Container';
137
+ export default Container;
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as Container } from './Container';
2
+ export type * from './type';
package/src/type.ts ADDED
@@ -0,0 +1,143 @@
1
+ import { MouseEventHandler, MutableRefObject } from 'react';
2
+
3
+ import type { Styles } from '@cleartrip/ct-design-types';
4
+ import { INativeUIEvent } from '@cleartrip/ct-design-types';
5
+
6
+ export type HapticVariant = 'subtle' | 'loud';
7
+
8
+ export interface HapticFeedbackProps {
9
+ /**
10
+ * Enables haptic feedback on interaction with the container.
11
+ * When true, the container will trigger haptic feedback on click/tap events.
12
+ * @example
13
+ * <Component hapticEnabled={true} />
14
+ */
15
+ hapticEnabled?: boolean;
16
+
17
+ /**
18
+ * Specifies the intensity of the haptic feedback.
19
+ * - 'light': Light haptic feedback, suitable for most interactions
20
+ * - 'loud': Strong haptic feedback, for more prominent interactions
21
+ * @example
22
+ * <Component hapticEnabled={true} hapticVariant="subtle" />
23
+ */
24
+ hapticVariant?: HapticVariant;
25
+
26
+ /**
27
+ * When enabled, the haptic feedback will repeat continuously while the interaction is active.
28
+ * Useful for long-press or drag interactions.
29
+ * @example
30
+ * <Component hapticEnabled={true} hapticRepeat={true} />
31
+ */
32
+ hapticRepeat?: boolean;
33
+ }
34
+
35
+ export interface IHapticFeedbackProps {
36
+ pattern?: number | number[];
37
+ repeat?: boolean;
38
+ variant: HapticVariant;
39
+ intensity?: number;
40
+ }
41
+
42
+ export interface IContainer extends HapticFeedbackProps {
43
+ /**
44
+ * The id of the container
45
+ */
46
+ id?: string;
47
+ /**
48
+ * The children of the container
49
+ */
50
+ children?: React.ReactNode;
51
+ /**
52
+ * The type of HTML element to be used for rendering
53
+ */
54
+ as?: 'main' | 'section' | 'article' | 'div' | 'p';
55
+ /**
56
+ * Callback when user clicks on the container
57
+ */
58
+ onClick?: (event: INativeUIEvent) => void;
59
+ /**
60
+ * Callback for layout changes. Works only for native.
61
+ */
62
+ onLayout?: (event: {
63
+ layout: {
64
+ height: number;
65
+ width: number;
66
+ x: number;
67
+ y: number;
68
+ };
69
+ }) => void;
70
+ /**
71
+ * Custom style configuration for the container
72
+ */
73
+ styleConfig?: {
74
+ root?: Styles[];
75
+ };
76
+ /**
77
+ * Triggered when the mouse enters the container.
78
+ */
79
+ onMouseEnter?: MouseEventHandler<HTMLElement>;
80
+ /**
81
+ * Triggered when the mouse leaves the container.
82
+ */
83
+ onMouseLeave?: () => void;
84
+ onTouchStart?: () => void;
85
+ onTouchEnd?: () => void;
86
+ onTouchCancel?: () => void;
87
+ onTouchMove?: () => void;
88
+ /**
89
+ * Triggered when the transition ends.
90
+ */
91
+ onTransitionEnd?: () => void;
92
+
93
+ /**
94
+ * Sets additional distance outside of element in which a press can be detected.
95
+ */
96
+ hitSlop?: {
97
+ top: number;
98
+ bottom: number;
99
+ left: number;
100
+ right: number;
101
+ };
102
+ /**
103
+ * Sets the pointer events for the container.
104
+ * @example
105
+ * <Component pointerEvents="box-none" />
106
+ */
107
+ pointerEvents?: 'box-none' | 'box-only' | 'auto';
108
+ }
109
+
110
+ export interface Rect {
111
+ x: number;
112
+ y: number;
113
+ width: number;
114
+ height: number;
115
+ }
116
+
117
+ export interface ContainerRef {
118
+ /**
119
+ * Focuses the container element
120
+ */
121
+ focus: () => void;
122
+ /**
123
+ * Gets the bounding rectangle of the container with a callback
124
+ */
125
+ getBoundingRectWithCallback: (callback?: (rect: Rect) => void) => void;
126
+ /**
127
+ * Measures the container's dimensions and position
128
+ */
129
+ measure: (
130
+ callback: (x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void,
131
+ ) => void;
132
+
133
+ style: React.CSSProperties;
134
+
135
+ getElementRef: () => MutableRefObject<ContainerRef | null>;
136
+
137
+ classList: {
138
+ add: (className: string) => void;
139
+ };
140
+
141
+ addEventListener: (event: string, callback: () => void) => void;
142
+ removeEventListener: (event: string, callback: () => void) => void;
143
+ }
package/dist/style.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import type { CSSObject } from 'styled-components';
2
- import { CSSWithTheme } from '@cleartrip/ct-design-types';
3
- export declare const getContainerStyles: ({ alignItems, borderRadius, boxShadow, bottom, display, flex, justifyContent, flexWrap, flexDirection, rowGap, columnGap, left, position, right, top, zIndex, paddingTop, paddingBottom, paddingLeft, paddingRight, marginTop, marginBottom, marginLeft, marginRight, backgroundColor, cursor, width, height, wordBreak, theme, textAlign, gridTemplateColumns, ...rest }: CSSWithTheme) => CSSObject;
4
- //# sourceMappingURL=style.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../packages/components/Container/src/style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,eAAO,MAAM,kBAAkB,8WAkC5B,YAAY,KAAG,SAmCjB,CAAC"}