@cleartrip/ct-design-segment 4.0.0-TEST.1 → 5.0.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.
Files changed (39) hide show
  1. package/README.md +85 -0
  2. package/dist/Segment.d.ts +3 -26
  3. package/dist/Segment.d.ts.map +1 -1
  4. package/dist/Segment.native.d.ts +5 -0
  5. package/dist/Segment.native.d.ts.map +1 -0
  6. package/dist/SegmentButton.d.ts +5 -0
  7. package/dist/SegmentButton.d.ts.map +1 -0
  8. package/dist/SegmentButton.native.d.ts +5 -0
  9. package/dist/SegmentButton.native.d.ts.map +1 -0
  10. package/dist/constants.d.ts +5 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/ct-design-segment.browser.cjs.js +1 -1
  13. package/dist/ct-design-segment.browser.cjs.js.map +1 -1
  14. package/dist/ct-design-segment.browser.esm.js +1 -1
  15. package/dist/ct-design-segment.browser.esm.js.map +1 -1
  16. package/dist/ct-design-segment.cjs.js +339 -95
  17. package/dist/ct-design-segment.cjs.js.map +1 -1
  18. package/dist/ct-design-segment.esm.js +342 -97
  19. package/dist/ct-design-segment.esm.js.map +1 -1
  20. package/dist/ct-design-segment.umd.js +1986 -128
  21. package/dist/ct-design-segment.umd.js.map +1 -1
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.native.d.ts +4 -0
  25. package/dist/index.native.d.ts.map +1 -0
  26. package/dist/style.d.ts +111 -18
  27. package/dist/style.d.ts.map +1 -1
  28. package/dist/type.d.ts +46 -0
  29. package/dist/type.d.ts.map +1 -0
  30. package/package.json +27 -13
  31. package/src/Segment.native.tsx +284 -0
  32. package/src/Segment.tsx +277 -0
  33. package/src/SegmentButton.native.tsx +110 -0
  34. package/src/SegmentButton.tsx +115 -0
  35. package/src/constants.ts +4 -0
  36. package/src/index.native.ts +3 -0
  37. package/src/index.ts +3 -0
  38. package/src/style.ts +132 -0
  39. package/src/type.ts +85 -0
@@ -0,0 +1,115 @@
1
+ import React from 'react';
2
+
3
+ import { Button, ButtonColor, ButtonSize, ButtonVariant } from '@cleartrip/ct-design-button';
4
+ import { useStyles } from '@cleartrip/ct-design-style-manager';
5
+ import { useTheme } from '@cleartrip/ct-design-theme';
6
+
7
+ import { ISegmentButtonProps } from './type';
8
+ import { SegmentVariant } from './constants';
9
+ import { getStyledSegmentButtonStyles, segmentStaticStyles } from './style';
10
+
11
+ export const SegmentButton: React.FC<ISegmentButtonProps> = ({
12
+ option,
13
+ index,
14
+ activeIndex,
15
+ disabled,
16
+ onOptionClick,
17
+ styleConfig,
18
+ variant,
19
+ optionLength: _optionLength,
20
+ }) => {
21
+ const theme = useTheme();
22
+ const isActive = index === activeIndex;
23
+
24
+ const { segmentButton = {}, segmentText = {} } = styleConfig || {};
25
+
26
+ const shell = useStyles(
27
+ (t) => ({
28
+ rowCell: {
29
+ flexGrow: 1,
30
+ flexBasis: 0,
31
+ flexShrink: 1,
32
+ minWidth: 0,
33
+ minHeight: 0,
34
+ width: undefined,
35
+ alignSelf: 'stretch',
36
+ height: t.size[10],
37
+ maxHeight: t.size[10],
38
+ paddingHorizontal: 0,
39
+ paddingTop: 0,
40
+ paddingBottom: 0,
41
+ paddingVertical: 0,
42
+ justifyContent: 'center',
43
+ alignItems: 'center',
44
+ },
45
+ }),
46
+ [],
47
+ );
48
+
49
+ const dynamicStyles = useStyles(
50
+ (innerTheme) => {
51
+ if (variant === SegmentVariant.DARK) {
52
+ return {
53
+ typography: {
54
+ fontSize: innerTheme.typography.size[14],
55
+ fontWeight: innerTheme.typography.weight.medium,
56
+ lineHeight: innerTheme.size[5],
57
+ textAlign: 'center' as const,
58
+ display: 'flex' as const,
59
+ justifyContent: 'center' as const,
60
+ alignItems: 'center' as const,
61
+ paddingTop: 0,
62
+ paddingBottom: 0,
63
+ marginTop: 0,
64
+ marginBottom: 0,
65
+ color: isActive ? theme.color.text.neutral : innerTheme.color.text.primary,
66
+ },
67
+ };
68
+ }
69
+ return {
70
+ typography: {
71
+ ...getStyledSegmentButtonStyles({ theme: innerTheme, isActive }),
72
+ textAlign: 'center' as const,
73
+ display: 'flex' as const,
74
+ justifyContent: 'center' as const,
75
+ alignItems: 'center' as const,
76
+ paddingTop: 0,
77
+ paddingBottom: 0,
78
+ marginTop: 0,
79
+ marginBottom: 0,
80
+ },
81
+ };
82
+ },
83
+ [isActive, variant, theme],
84
+ );
85
+
86
+ const segmentTextRoot =
87
+ segmentText.root === undefined ? [] : Array.isArray(segmentText.root) ? segmentText.root : [segmentText.root];
88
+
89
+ return (
90
+ <Button
91
+ variant={ButtonVariant.BARE}
92
+ color={ButtonColor.TERTIARY}
93
+ size={ButtonSize.SMALL}
94
+ isFullWidth={false}
95
+ prefixIcon={option?.icon}
96
+ onClick={() => {
97
+ if (disabled) return;
98
+ onOptionClick(option.tabId, index);
99
+ }}
100
+ disabled={disabled}
101
+ styleConfig={{
102
+ ...segmentButton,
103
+ root: [segmentStaticStyles.button, ...(segmentButton.root ?? []), shell.rowCell],
104
+ typography: {
105
+ ...segmentText,
106
+ root: [dynamicStyles.typography, ...segmentTextRoot],
107
+ },
108
+ }}
109
+ >
110
+ {option?.text ?? ''}
111
+ </Button>
112
+ );
113
+ };
114
+
115
+ export default SegmentButton;
@@ -0,0 +1,4 @@
1
+ export enum SegmentVariant {
2
+ DEFAULT = 'default',
3
+ DARK = 'dark',
4
+ }
@@ -0,0 +1,3 @@
1
+ export { default as Segment } from './Segment.native';
2
+ export type * from './type';
3
+ export * from './constants';
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { default as Segment } from './Segment';
2
+ export type * from './type';
3
+ export * from './constants';
package/src/style.ts ADDED
@@ -0,0 +1,132 @@
1
+ import type { Theme } from '@cleartrip/ct-design-theme';
2
+ import { makeStyles } from '@cleartrip/ct-design-style-manager';
3
+ import type { TextStyle } from '@cleartrip/ct-design-types';
4
+
5
+ import { SegmentVariantType } from './type';
6
+ import { SegmentVariant } from './constants';
7
+
8
+ export const SEGMENT_THUMB_BOX_SHADOW = '0px 0px 4px rgba(0, 0, 0, 0.12)' as const;
9
+
10
+ export const segmentThumbShadowNative = {
11
+ shadowColor: '#000000',
12
+ shadowOffset: { width: 0, height: 0 },
13
+ shadowOpacity: 0.12,
14
+ shadowRadius: 4,
15
+ elevation: 3,
16
+ } as const;
17
+
18
+ export const segmentStaticStyles = makeStyles((theme) => {
19
+ const trackHeight = theme.size[10];
20
+ const borderWidth = theme.border.width.sm;
21
+ const trackInnerHeight = Math.max(trackHeight - borderWidth * 2, 0);
22
+ const thumbInset = Math.max(theme.spacing[0.25], 0);
23
+ const trackRadius = Math.max(0, trackHeight / 2);
24
+ const trackInnerRadius = Math.max(0, trackInnerHeight / 2);
25
+ const thumbRadius = Math.max(0, trackInnerRadius - thumbInset);
26
+
27
+ return {
28
+ root: {
29
+ display: 'flex',
30
+ flexDirection: 'row',
31
+ borderWidth,
32
+ borderColor: 'transparent',
33
+ borderRadius: trackRadius,
34
+ overflow: 'hidden',
35
+ backgroundColor: theme.color.background.disabled,
36
+ position: 'relative',
37
+ height: trackHeight,
38
+ alignItems: 'stretch',
39
+ padding: theme.spacing[1],
40
+ },
41
+ button: {
42
+ backgroundColor: 'transparent',
43
+ fontSize: theme.typography.size[14],
44
+ fontWeight: theme.typography.weight.medium,
45
+ lineHeight: theme.size[5],
46
+ borderColor: theme.color.border.default,
47
+ borderRadius: thumbRadius,
48
+ textAlign: 'center',
49
+ justifyContent: 'center',
50
+ alignItems: 'center',
51
+ },
52
+ animatedBlock: {
53
+ position: 'absolute',
54
+ top: 0,
55
+ height: '100%',
56
+ borderRadius: thumbRadius,
57
+ backgroundColor: theme.color.background.neutral,
58
+ },
59
+ animatedContainer: {
60
+ flexDirection: 'row',
61
+ alignItems: 'stretch',
62
+ justifyContent: 'flex-start',
63
+ position: 'relative',
64
+ height: '100%',
65
+ width: '100%',
66
+ },
67
+ tabMeasureCell: {
68
+ flexGrow: 1,
69
+ flexShrink: 1,
70
+ flexBasis: 0,
71
+ minWidth: 0,
72
+ },
73
+ animatedBlockWidth: {
74
+ width: theme.size['100P'],
75
+ },
76
+ };
77
+ });
78
+
79
+ export const segmentWebThumbStyles = makeStyles((theme) => {
80
+ const trackHeight = theme.size[10];
81
+ const borderWidth = theme.border.width.sm;
82
+ const trackInnerHeight = Math.max(trackHeight - borderWidth * 2, 0);
83
+ const thumbInset = Math.max(theme.spacing[0.25], 0);
84
+ const thumbHeight = Math.max(trackInnerHeight - thumbInset * 2, 0);
85
+ const trackInnerRadius = Math.max(0, trackInnerHeight / 2);
86
+ const thumbRadius = Math.max(0, trackInnerRadius - thumbInset);
87
+
88
+ return {
89
+ root: {
90
+ position: 'absolute',
91
+ height: thumbHeight,
92
+ borderRadius: thumbRadius,
93
+ backgroundColor: theme.color.background.neutral,
94
+ top: thumbInset,
95
+ boxShadow: SEGMENT_THUMB_BOX_SHADOW,
96
+ },
97
+ };
98
+ });
99
+
100
+ export const getStyledSegmentButtonStyles = ({ theme, isActive }: { isActive: boolean; theme: Theme }): TextStyle => {
101
+ const color = isActive ? theme.color.tab.selectedPrimaryLabel : theme.color.tab.nonSelectedPrimaryLabel;
102
+ return {
103
+ color,
104
+ fontSize: theme.typography.size[14],
105
+ fontWeight: theme.typography.weight.medium,
106
+ lineHeight: theme.size[5],
107
+ };
108
+ };
109
+
110
+ export const getSegmentVariantStyles = (variant: SegmentVariantType, theme: Theme) => {
111
+ switch (variant) {
112
+ case SegmentVariant.DARK:
113
+ return {
114
+ animatedBlock: { style: { backgroundColor: theme.color.background.defaultDarkest } },
115
+ segmentButton: { style: { color: theme.color.text.primary } },
116
+ segmentButtonActive: { style: { color: theme.color.text.neutral } },
117
+ root: {
118
+ style: {
119
+ backgroundColor: theme.color.background.neutral,
120
+ borderColor: theme.color.border.disabledDark,
121
+ },
122
+ },
123
+ };
124
+ case SegmentVariant.DEFAULT:
125
+ default:
126
+ return {
127
+ animatedBlock: {},
128
+ segmentButton: {},
129
+ segmentButtonActive: {},
130
+ };
131
+ }
132
+ };
package/src/type.ts ADDED
@@ -0,0 +1,85 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import type { TextStyle, Styles } from '@cleartrip/ct-design-types';
4
+ import { TypographyStyleConfigProps } from '@cleartrip/ct-design-typography';
5
+ import type { IButtonProps } from '@cleartrip/ct-design-button';
6
+ import { SegmentVariant } from './constants';
7
+ export interface IOption {
8
+ tabId: string;
9
+ text: string;
10
+ icon?: ReactNode;
11
+ disabled?: boolean;
12
+ }
13
+
14
+ export type SegmentVariantType = `${SegmentVariant}`;
15
+
16
+ export interface SegmentStyleConfigProps {
17
+ root?: Styles[];
18
+ optionButtonWrapper?: Styles[];
19
+ segmentButton?: ISegmentButtonProps['styleConfig'];
20
+ animatedContainer?: Styles[];
21
+ animatedBlock?: Styles[];
22
+ optionButtonWrapperActive?: Styles[];
23
+ segmentButtonActive?: TextStyle[];
24
+ }
25
+
26
+ export interface ISegmentProps {
27
+ /**
28
+ * If true, the segment takes the full width of its parent.
29
+ */
30
+ block?: boolean;
31
+
32
+ /**
33
+ * Disables all segment options.
34
+ */
35
+ disabled?: boolean;
36
+
37
+ /**
38
+ * Visual variant for the segment.
39
+ */
40
+ variant?: SegmentVariantType;
41
+
42
+ /**
43
+ * Allow `onChange` to fire even when an option is disabled.
44
+ */
45
+ enableTabClick?: boolean;
46
+
47
+ /**
48
+ * Fired when the active tab changes.
49
+ */
50
+ onChange: (value: string | number) => void;
51
+
52
+ /**
53
+ * Options rendered inside the segment.
54
+ */
55
+ options: IOption[];
56
+
57
+ /**
58
+ * Controlled active tab id.
59
+ */
60
+ activeTabId?: string;
61
+
62
+ /**
63
+ * Duration (ms) of the indicator slide animation.
64
+ */
65
+ animationDuration?: number;
66
+
67
+ /**
68
+ * Per-slot style overrides.
69
+ */
70
+ styleConfig?: SegmentStyleConfigProps;
71
+ }
72
+
73
+ export interface ISegmentButtonProps {
74
+ option: IOption;
75
+ index: number;
76
+ activeIndex: number;
77
+ disabled: boolean;
78
+ onOptionClick: (tabId: string, index: number) => void;
79
+ optionLength: number;
80
+ styleConfig?: {
81
+ segmentButton?: IButtonProps['styleConfig'];
82
+ segmentText?: TypographyStyleConfigProps;
83
+ };
84
+ variant: SegmentVariantType;
85
+ }