ctms-common-components 1.0.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.
Files changed (61) hide show
  1. package/.babelrc +3 -0
  2. package/.czrc +3 -0
  3. package/.github/CODEOWNERS +1 -0
  4. package/.github/workflows/cd.yml +38 -0
  5. package/.github/workflows/ci.yml +29 -0
  6. package/.storybook/main.js +22 -0
  7. package/.storybook/preview.js +14 -0
  8. package/CHANGELOG.md +11 -0
  9. package/README.md +1 -0
  10. package/dist/index.js.LICENSE.txt +50 -0
  11. package/package.json +58 -0
  12. package/public/fonts/lato-latin.woff2 +0 -0
  13. package/public/index.html +17 -0
  14. package/src/assets/components/index.css +3 -0
  15. package/src/assets/components/index.jsx +607 -0
  16. package/src/assets/pngs/background-logo.png +0 -0
  17. package/src/assets/pngs/logo.png +0 -0
  18. package/src/assets/styles/tailwind.css +3 -0
  19. package/src/assets/svgs/edit-icon.svg +12 -0
  20. package/src/assets/svgs/overflow-icon.svg +20 -0
  21. package/src/assets/svgs/tick-mark.svg +3 -0
  22. package/src/components/Button.jsx +50 -0
  23. package/src/components/Pagination/PaginationStyles.js +49 -0
  24. package/src/components/Pagination/index.jsx +85 -0
  25. package/src/components/PoojaCard/index.jsx +216 -0
  26. package/src/components/StatusCard/index.jsx +102 -0
  27. package/src/components/TokenCard/index.jsx +205 -0
  28. package/src/components/button.css +50 -0
  29. package/src/components/custom-Table/AdvancedTableBody.jsx +186 -0
  30. package/src/components/custom-Table/AdvancedTableHead.jsx +315 -0
  31. package/src/components/custom-Table/EllipsisCell.jsx +137 -0
  32. package/src/components/custom-Table/Loader.jsx +24 -0
  33. package/src/components/custom-Table/index.jsx +340 -0
  34. package/src/components/index.js +7 -0
  35. package/src/components/more-actions/MenuStyles.js +54 -0
  36. package/src/components/more-actions/index.jsx +50 -0
  37. package/src/index.jsx +11 -0
  38. package/src/lib.js +133 -0
  39. package/src/stories/AdvancedTable.stories.jsx +108 -0
  40. package/src/stories/Button.stories.js +45 -0
  41. package/src/stories/PoojaCard.stories.jsx +108 -0
  42. package/src/stories/StatusCard.stories.jsx +51 -0
  43. package/src/stories/TokenCard.stories.jsx +75 -0
  44. package/src/theme/README.md +23 -0
  45. package/src/theme/components/button.js +42 -0
  46. package/src/theme/components/checkbox.js +20 -0
  47. package/src/theme/components/index.js +27 -0
  48. package/src/theme/foundations/blur.js +12 -0
  49. package/src/theme/foundations/borders.js +9 -0
  50. package/src/theme/foundations/breakpoints.js +10 -0
  51. package/src/theme/foundations/colors.js +196 -0
  52. package/src/theme/foundations/index.js +27 -0
  53. package/src/theme/foundations/radius.js +13 -0
  54. package/src/theme/foundations/shadows.js +16 -0
  55. package/src/theme/foundations/sizes.js +60 -0
  56. package/src/theme/foundations/spacing.js +37 -0
  57. package/src/theme/foundations/transition.js +25 -0
  58. package/src/theme/foundations/typography.js +55 -0
  59. package/src/theme/foundations/z-index.js +17 -0
  60. package/src/theme/index.js +20 -0
  61. package/webpack.config.js +34 -0
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import './button.css';
4
+
5
+ /**
6
+ * Primary UI component for user interaction
7
+ */
8
+ export const Button = ({ primary, backgroundColor, size, label="Hiii", ...props }) => {
9
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
10
+ return (
11
+ <button
12
+ type="button"
13
+ className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
14
+ style={backgroundColor && { backgroundColor }}
15
+ {...props}
16
+ >
17
+ {label}
18
+ </button>
19
+ );
20
+ };
21
+
22
+ Button.propTypes = {
23
+ /**
24
+ * Is this the principal call to action on the page?
25
+ */
26
+ primary: PropTypes.bool,
27
+ /**
28
+ * What background color to use
29
+ */
30
+ backgroundColor: PropTypes.string,
31
+ /**
32
+ * How large should the button be?
33
+ */
34
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
35
+ /**
36
+ * Button contents
37
+ */
38
+ label: PropTypes.string.isRequired,
39
+ /**
40
+ * Optional click handler
41
+ */
42
+ onClick: PropTypes.func,
43
+ };
44
+
45
+ Button.defaultProps = {
46
+ backgroundColor: null,
47
+ primary: false,
48
+ size: 'medium',
49
+ onClick: undefined,
50
+ };
@@ -0,0 +1,49 @@
1
+ import colors from '../../theme/foundations/colors';
2
+
3
+ const component = {};
4
+ const style = {
5
+ '.center': {
6
+ display: 'flex',
7
+ justifyContent: 'center',
8
+ marginTop: '10px',
9
+ paddingTop: '20px !important'
10
+ },
11
+ '.p-20': {
12
+ paddingRight: '20px'
13
+ },
14
+ '.rows': {
15
+ color: 'gray.400'
16
+ },
17
+ '#rowsPerPage': {
18
+ background: 'white'
19
+ },
20
+ '.mr-5': {
21
+ marginRight: '5px'
22
+ },
23
+ '.prevBtn, .NxtBtn, .indexBtn': {
24
+ borderRadius: '5px',
25
+ marginRight: '5px',
26
+ border: `1px solid ${colors.tertiary[500]}`,
27
+ background: 'colors.white',
28
+ color: 'tertiary.500',
29
+ fontWeight: 'bold',
30
+ cursor: 'pointer',
31
+ padding: '0px 10px 0px 10px'
32
+ },
33
+ '.activePrevBtn, .activeIndexBtn, .activeNxtBtn': {
34
+ borderRadius: '5px',
35
+ marginRight: '5px',
36
+ border: `1px solid ${colors.blue[200]}`,
37
+ background: 'tertiary.500',
38
+ color: 'white',
39
+ fontWeight: 'bold',
40
+ cursor: 'pointer',
41
+ padding: '0px 10px 0px 10px'
42
+ },
43
+ '.flex': {
44
+ display: 'flex'
45
+ }
46
+
47
+ };
48
+
49
+ export default { component, style };
@@ -0,0 +1,85 @@
1
+ import React from 'react';
2
+ import './PaginationStyles.js';
3
+
4
+ const ROWS_PER_PAGE_OPTIONS = [5, 10, 25, 50];
5
+
6
+ const Pagination = ({
7
+ currentPage = 1,
8
+ itemsPerPage = ROWS_PER_PAGE_OPTIONS[0] || 5,
9
+ totalItems = 0,
10
+ handlePageChange = () => {},
11
+ prevButton = '<',
12
+ nxtButton = '>',
13
+ showFirstButton = false,
14
+ firstBtnLabel = '|<',
15
+ LastBtnLabel = '>|',
16
+ boundaryCount = 1 // Number of buttons to show at the start and end
17
+ }) => {
18
+ const totalPages = Math.ceil(totalItems / itemsPerPage);
19
+ const buttons = [];
20
+
21
+ const startButton = Math.max(1, currentPage - boundaryCount);
22
+ const endButton = Math.min(totalPages, currentPage + boundaryCount);
23
+
24
+ if (startButton > 1) {
25
+ buttons.push(
26
+ <button key={1} onClick={() => handlePageChange(1)} className="indexBtn">
27
+ 1
28
+ </button>
29
+ );
30
+ if (startButton > 2) {
31
+ buttons.push(<span key="dots-start">...</span>);
32
+ }
33
+ }
34
+
35
+ for (let i = startButton; i <= endButton; i += 1) {
36
+ buttons.push(
37
+ <button key={i} onClick={() => handlePageChange(i)} className={currentPage === i ? 'activeIndexBtn' : 'indexBtn'}>
38
+ {i}
39
+ </button>
40
+ );
41
+ }
42
+
43
+ if (endButton < totalPages) {
44
+ if (endButton < totalPages - 1) {
45
+ buttons.push(<span key="dots-end">...</span>);
46
+ }
47
+ buttons.push(
48
+ <button key={totalPages} onClick={() => handlePageChange(totalPages)} className="indexBtn">
49
+ {totalPages}
50
+ </button>
51
+ );
52
+ }
53
+
54
+ return (
55
+ <div>
56
+ {itemsPerPage > 0 && (
57
+ <div className="center">
58
+ {showFirstButton && (
59
+ <button disabled={currentPage === 1} onClick={() => handlePageChange(1)} className="mr-5">
60
+ {firstBtnLabel}
61
+ </button>
62
+ )}
63
+ <button disabled={currentPage === 1} onClick={() => handlePageChange(currentPage - 1)} className="prevBtn">
64
+ {prevButton}
65
+ </button>
66
+ {buttons}
67
+ <button
68
+ disabled={currentPage === totalPages}
69
+ onClick={() => handlePageChange(currentPage + 1)}
70
+ className="NxtBtn"
71
+ >
72
+ {nxtButton}
73
+ </button>
74
+ {showFirstButton && (
75
+ <button disabled={currentPage === totalPages} onClick={() => handlePageChange(totalPages)} className="mr-5">
76
+ {LastBtnLabel}
77
+ </button>
78
+ )}
79
+ </div>
80
+ )}
81
+ </div>
82
+ );
83
+ };
84
+
85
+ export default Pagination;
@@ -0,0 +1,216 @@
1
+ import React from 'react';
2
+ import {
3
+ Card,
4
+ Box,
5
+ Typography,
6
+ Chip,
7
+ Button,
8
+ Avatar,
9
+ Stack,
10
+ Divider
11
+ } from '@mui/material';
12
+
13
+ import AccessTimeIcon from '@mui/icons-material/AccessTime';
14
+ import EventSeatIcon from '@mui/icons-material/EventSeat';
15
+
16
+ const colorVariants = {
17
+ saffron: {
18
+ primary: '#F4B942',
19
+ secondary: '#FFF8EE',
20
+ accent: '#7A1C1C'
21
+ },
22
+ maroon: {
23
+ primary: '#7A1C1C',
24
+ secondary: '#FFF5F5',
25
+ accent: '#5A0E16'
26
+ },
27
+ navy: {
28
+ primary: '#1B2950',
29
+ secondary: '#F4F7FC',
30
+ accent: '#0E1A36'
31
+ }
32
+ };
33
+
34
+ const sizeVariants = {
35
+ small: {
36
+ cardWidth: 340,
37
+ image: 64,
38
+ title: '1.2rem',
39
+ subtitle: '0.8rem',
40
+ padding: 1.5
41
+ },
42
+ medium: {
43
+ cardWidth: 460,
44
+ image: 78,
45
+ title: '1.5rem',
46
+ subtitle: '0.95rem',
47
+ padding: 2
48
+ },
49
+ large: {
50
+ cardWidth: 620,
51
+ image: 90,
52
+ title: '1.8rem',
53
+ subtitle: '1rem',
54
+ padding: 2.5
55
+ }
56
+ };
57
+
58
+ const PoojaCard = ({
59
+ title = 'Abhishekam',
60
+ subtitle = 'അഭിഷേകം',
61
+ duration = '30 min',
62
+ priest = 'Shiva',
63
+ slots = 8,
64
+ amount = 500,
65
+ image = 'https://cdn-icons-png.flaticon.com/512/4359/4359963.png',
66
+ variant = 'maroon',
67
+ size = 'medium',
68
+ badge = 'Popular',
69
+ buttonText = 'Book Now',
70
+ showButton = true
71
+ }) => {
72
+ const colors = colorVariants[variant];
73
+ const dimensions = sizeVariants[size];
74
+
75
+ return (
76
+ <Card
77
+ elevation={3}
78
+ sx={{
79
+ width: '100%',
80
+ maxWidth: 700,
81
+ borderRadius: '24px',
82
+ overflow: 'hidden',
83
+ background: '#fff',
84
+ p: 2
85
+ }}
86
+ >
87
+ <Box
88
+ display="flex"
89
+ alignItems="center"
90
+ justifyContent="space-between"
91
+ gap={2}
92
+ flexWrap="wrap"
93
+ >
94
+ {/* LEFT SECTION */}
95
+ <Box display="flex" alignItems="center" gap={2} flex={1}>
96
+ {/* IMAGE */}
97
+ <Avatar
98
+ src={image}
99
+ variant="rounded"
100
+ sx={{
101
+ width: 90,
102
+ height: 90,
103
+ borderRadius: '20px'
104
+ }}
105
+ />
106
+
107
+ {/* CONTENT */}
108
+ <Box>
109
+ <Box display="flex" alignItems="center" gap={1} flexWrap="wrap">
110
+ <Typography
111
+ fontWeight={700}
112
+ sx={{
113
+ fontSize: '2rem'
114
+ }}
115
+ >
116
+ {title}
117
+ </Typography>
118
+
119
+ <Chip
120
+ label={badge}
121
+ size="small"
122
+ sx={{
123
+ background: '#F6E3B4',
124
+ color: '#6B4A00',
125
+ fontWeight: 700
126
+ }}
127
+ />
128
+ </Box>
129
+
130
+ <Typography
131
+ sx={{
132
+ color: '#555',
133
+ fontSize: '1rem',
134
+ mt: 0.3
135
+ }}
136
+ >
137
+ {subtitle}
138
+ </Typography>
139
+
140
+ <Box
141
+ display="flex"
142
+ alignItems="center"
143
+ gap={0.7}
144
+ mt={1}
145
+ >
146
+ <AccessTimeIcon
147
+ sx={{
148
+ fontSize: 18,
149
+ color: '#777'
150
+ }}
151
+ />
152
+
153
+ <Typography color="#444">
154
+ {duration} • {priest}
155
+ </Typography>
156
+ </Box>
157
+ </Box>
158
+ </Box>
159
+
160
+ {/* RIGHT SECTION */}
161
+ <Box
162
+ display="flex"
163
+ flexDirection="column"
164
+ alignItems="flex-end"
165
+ gap={1.5}
166
+ >
167
+ <Typography
168
+ sx={{
169
+ fontSize: '2.3rem',
170
+ fontWeight: 800,
171
+ color: '#1B2950'
172
+ }}
173
+ >
174
+ ₹{amount}
175
+ </Typography>
176
+
177
+ <Chip
178
+ icon={<EventSeatIcon />}
179
+ label={`${slots} slots`}
180
+ sx={{
181
+ background: '#DDF7E3',
182
+ color: '#166534',
183
+ fontWeight: 700
184
+ }}
185
+ />
186
+
187
+ {showButton && (
188
+ <Button
189
+ variant="contained"
190
+
191
+ sx={{
192
+ background: '#F4D5BD',
193
+ color: '#5A1623',
194
+ borderRadius: '16px',
195
+ px: 3,
196
+ py: 1,
197
+ ml:2,
198
+ textTransform: 'none',
199
+ fontWeight: 700,
200
+ boxShadow: 'none',
201
+ '&:hover': {
202
+ background: '#EAC4A5',
203
+ boxShadow: 'none'
204
+ }
205
+ }}
206
+ >
207
+ {buttonText}
208
+ </Button>
209
+ )}
210
+ </Box>
211
+ </Box>
212
+ </Card>
213
+ );
214
+ };
215
+
216
+ export default PoojaCard;
@@ -0,0 +1,102 @@
1
+ import React from 'react';
2
+ import { Card, Typography, Box } from '@mui/material';
3
+
4
+ const colorVariants = {
5
+ saffron: {
6
+ primary: '#F4C430',
7
+ secondary: '#A16B00',
8
+ bg: '#FFF8E1'
9
+ },
10
+ maroon: {
11
+ primary: '#7A1C1C',
12
+ secondary: '#A94442',
13
+ bg: '#F8EEEE'
14
+ },
15
+ navy: {
16
+ primary: '#0B1F4D',
17
+ secondary: '#304878',
18
+ bg: '#EEF2FA'
19
+ }
20
+ };
21
+
22
+ const sizeVariants = {
23
+ small: {
24
+ cardWidth: 80,
25
+ cardHeight: 52,
26
+ codeSize: '16px',
27
+ labelSize: '10px',
28
+ padding: '8px 12px'
29
+ },
30
+ medium: {
31
+ cardWidth: 100,
32
+ cardHeight: 64,
33
+ codeSize: '22px',
34
+ labelSize: '12px',
35
+ padding: '10px 16px'
36
+ },
37
+ large: {
38
+ cardWidth: 130,
39
+ cardHeight: 84,
40
+ codeSize: '30px',
41
+ labelSize: '16px',
42
+ padding: '14px 20px'
43
+ }
44
+ };
45
+
46
+ const StatusCard = ({
47
+ code = 'A-044',
48
+ label = 'Current',
49
+ color = 'maroon',
50
+ size = 'medium'
51
+ }) => {
52
+ const theme = colorVariants[color];
53
+ const dimensions = sizeVariants[size];
54
+
55
+ return (
56
+ <Card
57
+ elevation={0}
58
+ sx={{
59
+ width: dimensions.cardWidth,
60
+ height: dimensions.cardHeight,
61
+ borderRadius: '14px',
62
+ backgroundColor: theme.bg,
63
+ display: 'flex',
64
+ alignItems: 'center',
65
+ justifyContent: 'center',
66
+ px: 2,
67
+ transition: '0.3s ease',
68
+ cursor: 'pointer',
69
+ '&:hover': {
70
+ transform: 'translateY(-2px)',
71
+ boxShadow: '0 6px 18px rgba(0,0,0,0.08)'
72
+ }
73
+ }}
74
+ >
75
+ <Box>
76
+ <Typography
77
+ sx={{
78
+ fontSize: dimensions.codeSize,
79
+ fontWeight: 700,
80
+ lineHeight: 1,
81
+ color: theme.primary
82
+ }}
83
+ >
84
+ {code}
85
+ </Typography>
86
+
87
+ <Typography
88
+ sx={{
89
+ mt: 0.5,
90
+ fontSize: dimensions.labelSize,
91
+ fontWeight: 500,
92
+ color: theme.secondary
93
+ }}
94
+ >
95
+ {label}
96
+ </Typography>
97
+ </Box>
98
+ </Card>
99
+ );
100
+ };
101
+
102
+ export default StatusCard;
@@ -0,0 +1,205 @@
1
+ import React from 'react';
2
+ import {
3
+ Card,
4
+ Typography,
5
+ Box,
6
+ Chip
7
+ } from '@mui/material';
8
+
9
+ const colorVariants = {
10
+ saffron: {
11
+ bg: 'linear-gradient(135deg, #F4B942 0%, #D98C00 100%)',
12
+ text: '#FFFFFF',
13
+ chipBg: '#FFF3D6',
14
+ chipText: '#8A4B00',
15
+ divider: 'rgba(255,255,255,0.25)'
16
+ },
17
+
18
+ maroon: {
19
+ bg: 'linear-gradient(135deg, #8B0E11 0%, #5C0002 100%)',
20
+ text: '#FFFFFF',
21
+ chipBg: '#FFE0B2',
22
+ chipText: '#B45309',
23
+ divider: 'rgba(255,255,255,0.2)'
24
+ },
25
+
26
+ cream: {
27
+ bg: 'linear-gradient(135deg, #FFF8EE 0%, #F5E6D3 100%)',
28
+ text: '#3B2F2F',
29
+ chipBg: '#F4D5BD',
30
+ chipText: '#7A1C1C',
31
+ divider: 'rgba(0,0,0,0.1)'
32
+ },
33
+
34
+ navy: {
35
+ bg: 'linear-gradient(135deg, #1B2950 0%, #0E162B 100%)',
36
+ text: '#FFFFFF',
37
+ chipBg: '#D6E4FF',
38
+ chipText: '#1B2950',
39
+ divider: 'rgba(255,255,255,0.18)'
40
+ },
41
+
42
+ teal: {
43
+ bg: 'linear-gradient(135deg, #0F766E 0%, #115E59 100%)',
44
+ text: '#FFFFFF',
45
+ chipBg: '#D1FAE5',
46
+ chipText: '#065F46',
47
+ divider: 'rgba(255,255,255,0.2)'
48
+ }
49
+ };
50
+
51
+ const sizeVariants = {
52
+ small: {
53
+ width: 220,
54
+ height: 180,
55
+ tokenSize: '3rem',
56
+ titleSize: '0.7rem'
57
+ },
58
+
59
+ medium: {
60
+ width: 280,
61
+ height: 220,
62
+ tokenSize: '4.2rem',
63
+ titleSize: '0.8rem'
64
+ },
65
+
66
+ large: {
67
+ width: 340,
68
+ height: 260,
69
+ tokenSize: '5rem',
70
+ titleSize: '0.9rem'
71
+ }
72
+ };
73
+
74
+ const TokenCard = ({
75
+ token = 'A-045',
76
+ status = 'Waiting',
77
+ waitingCount = 12,
78
+ estimatedTime = '18 min',
79
+ variant = 'maroon',
80
+ size = 'medium'
81
+ }) => {
82
+ const colors = colorVariants[variant];
83
+ const dimensions = sizeVariants[size];
84
+
85
+ return (
86
+ <Card
87
+ elevation={4}
88
+ sx={{
89
+ width: dimensions.width,
90
+ height: dimensions.height,
91
+ borderRadius: '24px',
92
+ background: colors.bg,
93
+ color: colors.text,
94
+ p: 3,
95
+ display: 'flex',
96
+ flexDirection: 'column',
97
+ justifyContent: 'space-between',
98
+ position: 'relative',
99
+ overflow: 'hidden',
100
+ transition: '0.3s ease',
101
+ '&:hover': {
102
+ transform: 'translateY(-4px)',
103
+ boxShadow: '0 14px 30px rgba(0,0,0,0.18)'
104
+ }
105
+ }}
106
+ >
107
+ {/* TOP */}
108
+ <Box textAlign="center">
109
+ <Typography
110
+ sx={{
111
+ fontSize: dimensions.titleSize,
112
+ fontWeight: 600,
113
+ letterSpacing: '2px',
114
+ opacity: 0.85
115
+ }}
116
+ >
117
+ YOUR TOKEN NUMBER
118
+ </Typography>
119
+
120
+ <Typography
121
+ sx={{
122
+ fontSize: dimensions.tokenSize,
123
+ fontWeight: 900,
124
+ lineHeight: 1.1,
125
+ mt: 1
126
+ }}
127
+ >
128
+ {token}
129
+ </Typography>
130
+
131
+ <Chip
132
+ label={status}
133
+ size="small"
134
+ sx={{
135
+ mt: 1.5,
136
+ background: colors.chipBg,
137
+ color: colors.chipText,
138
+ fontWeight: 700,
139
+ borderRadius: '10px'
140
+ }}
141
+ />
142
+ </Box>
143
+
144
+ {/* DIVIDER */}
145
+ <Box
146
+ sx={{
147
+ width: '100%',
148
+ height: '1px',
149
+ background: colors.divider,
150
+ my: 2
151
+ }}
152
+ />
153
+
154
+ {/* BOTTOM */}
155
+ <Box
156
+ sx={{ display: 'flex', justifyContent:'space-between' }}
157
+
158
+ alignItems="center"
159
+ >
160
+ <Box
161
+ textAlign="center">
162
+ <Typography
163
+ sx={{
164
+ fontSize: '0.75rem',
165
+ opacity: 0.8
166
+ }}
167
+ >
168
+ Ahead of you
169
+ </Typography>
170
+
171
+ <Typography
172
+ sx={{
173
+ fontSize: '2rem',
174
+ fontWeight: 800
175
+ }}
176
+ >
177
+ {waitingCount}
178
+ </Typography>
179
+ </Box>
180
+
181
+ <Box textAlign="center">
182
+ <Typography
183
+ sx={{
184
+ fontSize: '0.75rem',
185
+ opacity: 0.8
186
+ }}
187
+ >
188
+ Est. Wait
189
+ </Typography>
190
+
191
+ <Typography
192
+ sx={{
193
+ fontSize: '2rem',
194
+ fontWeight: 800
195
+ }}
196
+ >
197
+ ~{estimatedTime}
198
+ </Typography>
199
+ </Box>
200
+ </Box>
201
+ </Card>
202
+ );
203
+ };
204
+
205
+ export default TokenCard;