@licklist/design 0.78.32 → 0.78.34

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 (138) hide show
  1. package/dist/Maintenance/MaintenancePage.js +1 -0
  2. package/dist/index.js +8 -1
  3. package/dist/v2/components/ActionMenu/ActionMenu.d.ts +14 -0
  4. package/dist/v2/components/ActionMenu/ActionMenu.d.ts.map +1 -0
  5. package/dist/v2/components/ActionMenu/ActionMenu.js +159 -0
  6. package/dist/v2/components/ActionMenu/ActionMenu.scss.js +6 -0
  7. package/dist/v2/components/ActionMenu/index.d.ts +2 -0
  8. package/dist/v2/components/ActionMenu/index.d.ts.map +1 -0
  9. package/dist/v2/components/Alert/Alert.d.ts.map +1 -1
  10. package/dist/v2/components/Alert/Alert.js +48 -1
  11. package/dist/v2/components/Alert/Alert.scss.js +1 -1
  12. package/dist/v2/components/Badge/Badge.d.ts +10 -0
  13. package/dist/v2/components/Badge/Badge.d.ts.map +1 -0
  14. package/dist/v2/components/Badge/Badge.js +19 -0
  15. package/dist/v2/components/Badge/Badge.scss.js +6 -0
  16. package/dist/v2/components/Badge/index.d.ts +2 -0
  17. package/dist/v2/components/Badge/index.d.ts.map +1 -0
  18. package/dist/v2/components/Button/Button.d.ts +3 -2
  19. package/dist/v2/components/Button/Button.d.ts.map +1 -1
  20. package/dist/v2/components/Button/Button.js +13 -6
  21. package/dist/v2/components/Button/Button.scss.js +1 -1
  22. package/dist/v2/components/Button/GhostButton.scss.js +1 -1
  23. package/dist/v2/components/Button/index.d.ts +2 -0
  24. package/dist/v2/components/Button/index.d.ts.map +1 -1
  25. package/dist/v2/components/Checkbox/Checkbox.scss.js +1 -1
  26. package/dist/v2/components/FormField/FormField.d.ts.map +1 -1
  27. package/dist/v2/components/FormField/FormField.scss.js +1 -1
  28. package/dist/v2/components/Modal/DeleteModal.d.ts +15 -0
  29. package/dist/v2/components/Modal/DeleteModal.d.ts.map +1 -0
  30. package/dist/v2/components/Modal/DeleteModal.js +151 -0
  31. package/dist/v2/components/Modal/DeleteModal.scss.js +6 -0
  32. package/dist/v2/components/Modal/index.d.ts +3 -0
  33. package/dist/v2/components/Modal/index.d.ts.map +1 -0
  34. package/dist/v2/components/NPSScore/NPSScore.d.ts +3 -1
  35. package/dist/v2/components/NPSScore/NPSScore.d.ts.map +1 -1
  36. package/dist/v2/components/NPSScore/NPSScore.js +11 -27
  37. package/dist/v2/components/NPSScore/NPSScore.scss.js +1 -1
  38. package/dist/v2/components/NewInput/NewInput.d.ts +2 -0
  39. package/dist/v2/components/NewInput/NewInput.d.ts.map +1 -1
  40. package/dist/v2/components/NewInput/NewInput.js +37 -12
  41. package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts +4 -1
  42. package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts.map +1 -1
  43. package/dist/v2/components/NewPageHeader/NewPageHeader.js +18 -11
  44. package/dist/v2/components/NewPageHeader/NewPageHeader.scss.js +1 -1
  45. package/dist/v2/components/NewTable/NewTable.d.ts +21 -0
  46. package/dist/v2/components/NewTable/NewTable.d.ts.map +1 -0
  47. package/dist/v2/components/NewTable/NewTable.js +63 -0
  48. package/dist/v2/components/NewTable/NewTable.scss.js +6 -0
  49. package/dist/v2/components/NewTable/index.d.ts +2 -0
  50. package/dist/v2/components/NewTable/index.d.ts.map +1 -0
  51. package/dist/v2/components/Pagination/Pagination.d.ts +13 -0
  52. package/dist/v2/components/Pagination/Pagination.d.ts.map +1 -0
  53. package/dist/v2/components/Pagination/Pagination.js +76 -0
  54. package/dist/v2/components/Pagination/Pagination.scss.js +6 -0
  55. package/dist/v2/components/Pagination/index.d.ts +2 -0
  56. package/dist/v2/components/Pagination/index.d.ts.map +1 -0
  57. package/dist/v2/components/QuickFilter/QuickFilter.d.ts +14 -0
  58. package/dist/v2/components/QuickFilter/QuickFilter.d.ts.map +1 -0
  59. package/dist/v2/components/QuickFilter/QuickFilter.js +70 -0
  60. package/dist/v2/components/QuickFilter/QuickFilter.scss.js +6 -0
  61. package/dist/v2/components/QuickFilter/index.d.ts +2 -0
  62. package/dist/v2/components/QuickFilter/index.d.ts.map +1 -0
  63. package/dist/v2/components/SectionHeader/SectionHeader.d.ts.map +1 -1
  64. package/dist/v2/components/Select/Select.d.ts +7 -4
  65. package/dist/v2/components/Select/Select.d.ts.map +1 -1
  66. package/dist/v2/components/Select/Select.js +53 -24
  67. package/dist/v2/components/Select/Select.scss.js +1 -1
  68. package/dist/v2/components/TableSortIcon/TableSortIcon.d.ts +9 -0
  69. package/dist/v2/components/TableSortIcon/TableSortIcon.d.ts.map +1 -0
  70. package/dist/v2/components/TableSortIcon/TableSortIcon.js +14 -0
  71. package/dist/v2/components/TableSortIcon/index.d.ts +2 -0
  72. package/dist/v2/components/TableSortIcon/index.d.ts.map +1 -0
  73. package/dist/v2/components/WYSIWYGEditor/Icons.js +2 -2
  74. package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss.js +1 -1
  75. package/dist/v2/components/index.d.ts +17 -4
  76. package/dist/v2/components/index.d.ts.map +1 -1
  77. package/dist/v2/icons/index.d.ts +46 -0
  78. package/dist/v2/icons/index.d.ts.map +1 -1
  79. package/dist/v2/icons/index.js +358 -4
  80. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.d.ts.map +1 -1
  81. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.js +4 -8
  82. package/dist/v2/pages/Settings/SettingsPage.scss.js +1 -1
  83. package/dist/v2/pages/Settings/SettingsTabs.scss.js +1 -1
  84. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +9 -3
  85. package/dist/v2/pages/Settings/components/SidebarCustomisation.scss.js +1 -1
  86. package/dist/v2/pages/Settings/components/SidebarNavItem.js +9 -3
  87. package/dist/v2/pages/Settings/components/SidebarNavItem.scss.js +1 -1
  88. package/dist/v2/styles/form/NewInput.scss.js +1 -1
  89. package/package.json +3 -3
  90. package/src/v2/components/ActionMenu/ActionMenu.scss +106 -0
  91. package/src/v2/components/ActionMenu/ActionMenu.tsx +115 -0
  92. package/src/v2/components/ActionMenu/index.ts +1 -0
  93. package/src/v2/components/Alert/Alert.scss +8 -19
  94. package/src/v2/components/Alert/Alert.tsx +24 -1
  95. package/src/v2/components/Badge/Badge.scss +82 -0
  96. package/src/v2/components/Badge/Badge.tsx +25 -0
  97. package/src/v2/components/Badge/index.ts +1 -0
  98. package/src/v2/components/Button/Button.tsx +18 -4
  99. package/src/v2/components/Button/GhostButton.scss +11 -1
  100. package/src/v2/components/Button/index.ts +2 -0
  101. package/src/v2/components/Customer/CustomerDetail.scss +319 -0
  102. package/src/v2/components/Customer/CustomersList.scss +815 -0
  103. package/src/v2/components/FormField/FormField.tsx +19 -21
  104. package/src/v2/components/Modal/DeleteModal.scss +254 -0
  105. package/src/v2/components/Modal/DeleteModal.tsx +102 -0
  106. package/src/v2/components/Modal/index.ts +3 -0
  107. package/src/v2/components/NPSScore/NPSScore.scss +40 -59
  108. package/src/v2/components/NPSScore/NPSScore.tsx +15 -16
  109. package/src/v2/components/NewInput/NewInput.stories.tsx +3 -18
  110. package/src/v2/components/NewInput/NewInput.tsx +35 -12
  111. package/src/v2/components/NewPageHeader/NewPageHeader.scss +17 -8
  112. package/src/v2/components/NewPageHeader/NewPageHeader.tsx +17 -10
  113. package/src/v2/components/NewTable/NewTable.scss +126 -0
  114. package/src/v2/components/NewTable/NewTable.tsx +92 -0
  115. package/src/v2/components/NewTable/index.ts +1 -0
  116. package/src/v2/components/Pagination/Pagination.scss +142 -0
  117. package/src/v2/components/Pagination/Pagination.tsx +80 -0
  118. package/src/v2/components/Pagination/index.ts +1 -0
  119. package/src/v2/components/QuickFilter/QuickFilter.scss +67 -0
  120. package/src/v2/components/QuickFilter/QuickFilter.tsx +51 -0
  121. package/src/v2/components/QuickFilter/index.ts +1 -0
  122. package/src/v2/components/SectionHeader/SectionHeader.tsx +5 -7
  123. package/src/v2/components/Select/Select.scss +61 -24
  124. package/src/v2/components/Select/Select.stories.tsx +77 -1
  125. package/src/v2/components/Select/Select.tsx +63 -34
  126. package/src/v2/components/TableSortIcon/TableSortIcon.tsx +20 -0
  127. package/src/v2/components/TableSortIcon/index.ts +1 -0
  128. package/src/v2/components/WYSIWYGEditor/Icons.tsx +2 -2
  129. package/src/v2/components/index.ts +44 -5
  130. package/src/v2/icons/index.tsx +123 -3
  131. package/src/v2/navigation/DashboardLayout/ProviderSidebar.tsx +3 -1
  132. package/src/v2/navigation/config.tsx +1 -1
  133. package/src/v2/pages/Settings/components/SidebarCustomisation.tsx +1 -1
  134. package/src/v2/styles/common.scss +7 -0
  135. package/src/v2/styles/components/Button.scss +34 -2
  136. package/src/v2/styles/form/NewInput.scss +45 -21
  137. package/src/v2/styles/index.scss +1 -0
  138. package/src/v2/styles/tokens/_colors.scss +6 -0
@@ -1,13 +1,17 @@
1
1
  import React, { useState } from 'react'
2
2
  import './NPSScore.scss'
3
+ import { Button } from '../Button'
4
+ import { Alert } from '../Alert'
3
5
 
4
6
  export interface NPSScoreProps {
5
7
  /** User's first name for personalized greeting */
6
8
  firstName?: string
7
9
  /** Callback when NPS is submitted */
8
10
  onSubmit?: (data: NPSSubmitData) => void
9
- /** Callback when dismissed */
11
+ /** Callback when dismissed without submitting */
10
12
  onDismiss?: () => void
13
+ /** Callback when success alert is dismissed after submission */
14
+ onSubmitDismiss?: () => void
11
15
  }
12
16
 
13
17
  export interface NPSSubmitData {
@@ -42,6 +46,7 @@ export const NPSScore: React.FC<NPSScoreProps> = ({
42
46
  firstName,
43
47
  onSubmit,
44
48
  onDismiss,
49
+ onSubmitDismiss,
45
50
  }) => {
46
51
  const [selectedScore, setSelectedScore] = useState<number | null>(null)
47
52
  const [reason, setReason] = useState('')
@@ -54,11 +59,7 @@ export const NPSScore: React.FC<NPSScoreProps> = ({
54
59
  const handleSubmit = async () => {
55
60
  if (!selectedScore) return
56
61
 
57
- // Validate required fields - reason required for all scores
58
62
  const newErrors: { reason?: string; role?: string } = {}
59
- if (!reason.trim()) {
60
- newErrors.reason = 'Please provide a reason for your score'
61
- }
62
63
  if (!role) {
63
64
  newErrors.role = 'Please select your role'
64
65
  }
@@ -86,13 +87,12 @@ export const NPSScore: React.FC<NPSScoreProps> = ({
86
87
  if (isSubmitted) {
87
88
  return (
88
89
  <div className="nps-score">
89
- <div className="nps-score__container">
90
- <div className="nps-score__success">
91
- <IconBigSmile size={48} className="nps-score__success-icon" />
92
- <h3 className="nps-score__success-title">Thank you!</h3>
93
- <p className="nps-score__success-message">Your feedback has been submitted successfully.</p>
94
- </div>
95
- </div>
90
+ <Alert
91
+ variant="success"
92
+ title="Thank you!"
93
+ message="Your feedback has been submitted successfully."
94
+ onDismiss={onSubmitDismiss}
95
+ />
96
96
  </div>
97
97
  )
98
98
  }
@@ -142,7 +142,7 @@ export const NPSScore: React.FC<NPSScoreProps> = ({
142
142
  {/* Reason textarea - always visible */}
143
143
  <div className="nps-score__field">
144
144
  <label className="nps-score__field-label">
145
- Reason for this score?
145
+ Reason for this score? (Optional)
146
146
  </label>
147
147
  <textarea
148
148
  value={reason}
@@ -192,13 +192,12 @@ export const NPSScore: React.FC<NPSScoreProps> = ({
192
192
  </div>
193
193
 
194
194
  {/* Submit button */}
195
- <button
195
+ <Button
196
196
  onClick={handleSubmit}
197
197
  disabled={isSubmitting}
198
- className="nps-score__submit"
199
198
  >
200
199
  {isSubmitting ? 'Submitting...' : 'Submit'}
201
- </button>
200
+ </Button>
202
201
  </div>
203
202
  )}
204
203
  </div>
@@ -1,6 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react'
2
2
  import { NewInput } from './NewInput'
3
3
  import { useState } from 'react'
4
+ import { SearchIcon, CalendarSmallIcon } from '../../icons'
4
5
 
5
6
  const meta: Meta<typeof NewInput> = {
6
7
  title: 'V2/Components/NewInput',
@@ -121,6 +122,7 @@ export const DateInput: Story = {
121
122
  args: {
122
123
  label: 'Date of Birth',
123
124
  type: 'date',
125
+ icon: <CalendarSmallIcon />,
124
126
  },
125
127
  }
126
128
 
@@ -202,24 +204,7 @@ export const RequiredField: Story = {
202
204
  export const WithIcon: Story = {
203
205
  args: {
204
206
  label: 'Search',
205
- placeholder: 'Search...',
206
- icon: (
207
- <svg
208
- width="20"
209
- height="20"
210
- viewBox="0 0 20 20"
211
- fill="none"
212
- xmlns="http://www.w3.org/2000/svg"
213
- >
214
- <path
215
- d="M9 17A8 8 0 1 0 9 1a8 8 0 0 0 0 16zM18 18l-4.35-4.35"
216
- stroke="currentColor"
217
- strokeWidth="2"
218
- strokeLinecap="round"
219
- strokeLinejoin="round"
220
- />
221
- </svg>
222
- ),
207
+ icon: <SearchIcon />,
223
208
  },
224
209
  }
225
210
 
@@ -7,7 +7,9 @@ type CommonInputProps = {
7
7
  helperText?: string;
8
8
  error?: string;
9
9
  icon?: ReactNode;
10
+ iconPosition?: 'left' | 'right';
10
11
  required?: boolean;
12
+ onIconClick?: () => void;
11
13
  }
12
14
 
13
15
  type InputProps = CommonInputProps & {
@@ -21,7 +23,8 @@ type TextareaProps = CommonInputProps & {
21
23
  export type NewInputProps = InputProps | TextareaProps
22
24
 
23
25
  export const NewInput = forwardRef<HTMLInputElement | HTMLTextAreaElement, NewInputProps>(
24
- ({label, optional, helperText, error, icon, as = 'input', required, className = '', ...props}, ref) => {
26
+ ({label, optional, helperText, error, icon, iconPosition = 'left', as = 'input', required, className = '', onIconClick, ...props}, ref) => {
27
+ const inputRef = React.useRef<HTMLInputElement>(null);
25
28
  const isError = !!error;
26
29
  const containerClasses = [
27
30
  'new-form-input',
@@ -30,6 +33,17 @@ export const NewInput = forwardRef<HTMLInputElement | HTMLTextAreaElement, NewIn
30
33
  className
31
34
  ].filter(Boolean).join(' ');
32
35
 
36
+ // Merge refs
37
+ React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);
38
+
39
+ const handleIconClick = () => {
40
+ if (onIconClick) {
41
+ onIconClick();
42
+ } else if (inputRef.current && (props as any).type === 'date') {
43
+ inputRef.current.showPicker?.();
44
+ }
45
+ };
46
+
33
47
  const renderInput = () => {
34
48
  if (as === 'textarea') {
35
49
  return (
@@ -43,12 +57,26 @@ export const NewInput = forwardRef<HTMLInputElement | HTMLTextAreaElement, NewIn
43
57
 
44
58
  if (icon) {
45
59
  return (
46
- <div className="new-form-input__input-with-icon">
60
+ <div className={`new-form-input__input-with-icon new-form-input__input-with-icon--${iconPosition}`}>
47
61
  <input
48
- ref={ref as React.Ref<HTMLInputElement>}
62
+ ref={inputRef}
49
63
  {...(props as React.InputHTMLAttributes<HTMLInputElement>)}
50
64
  />
51
- <div className="icon">{icon}</div>
65
+ <div
66
+ className="icon"
67
+ role="button"
68
+ tabIndex={0}
69
+ onClick={handleIconClick}
70
+ onKeyDown={(e) => {
71
+ if (e.key === 'Enter' || e.key === ' ') {
72
+ e.preventDefault();
73
+ handleIconClick();
74
+ }
75
+ }}
76
+ style={{ cursor: (onIconClick || (props as any).type === 'date') ? 'pointer' : 'default' }}
77
+ >
78
+ {icon}
79
+ </div>
52
80
  </div>
53
81
  );
54
82
  }
@@ -65,14 +93,9 @@ export const NewInput = forwardRef<HTMLInputElement | HTMLTextAreaElement, NewIn
65
93
  return (
66
94
  <div className={containerClasses}>
67
95
  {(label || optional) && (
68
- <div className="new-form-input__label-row">
69
- {label && (
70
- <label className="new-form-input__label">
71
- {label}
72
- </label>
73
- )}
74
- {optional && <span className="new-form-input__label-optional">Optional</span>}
75
- </div>
96
+ <label className="new-form-input__label">
97
+ {label} {optional && <span className="new-form-input__label-optional">(Optional)</span>}
98
+ </label>
76
99
  )}
77
100
 
78
101
  {renderInput()}
@@ -2,15 +2,17 @@
2
2
  display: flex;
3
3
  flex-direction: column;
4
4
  align-items: flex-start;
5
- gap: 24px;
5
+ gap: 0;
6
6
  align-self: stretch;
7
- padding-left: 32px;
8
- padding-right: 32px;
7
+ padding: 32px 32px 0px 32px;
9
8
 
10
9
  @media (max-width: 768px) {
11
- padding-left: 16px;
12
- padding-right: 16px;
13
- gap: 16px;
10
+ padding: 16px 16px 0px 16px;
11
+ gap: 0;
12
+ }
13
+
14
+ @media (max-width: 480px) {
15
+ padding: 16px 12px 0px 12px;
14
16
  }
15
17
  }
16
18
 
@@ -29,12 +31,20 @@
29
31
 
30
32
  &__title {
31
33
  color: var(--label-primary);
32
- font-family: 'Geist', sans-serif;
34
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
33
35
  font-size: 24px;
34
36
  font-style: normal;
35
37
  font-weight: 600;
36
38
  line-height: 28px;
37
39
  margin: 0;
40
+ padding: 0;
41
+ }
42
+
43
+ &__actions {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 16px;
47
+ flex-shrink: 0;
38
48
  }
39
49
  }
40
50
 
@@ -43,5 +53,4 @@
43
53
  height: 1px;
44
54
  border: none;
45
55
  background-color: var(--border-primary, #e8e9ef);
46
- margin: 0;
47
56
  }
@@ -6,19 +6,26 @@ export interface NewPageHeaderProps {
6
6
  title: string;
7
7
  cancelLabel?: string;
8
8
  onCancel?: () => void;
9
+ renderRight?: () => React.ReactNode;
9
10
  className?: string;
11
+ showDivider?: boolean;
12
+ dividerClassName?: string;
10
13
  }
11
14
 
12
- export const NewPageHeader: React.FC<NewPageHeaderProps> = ({
15
+ export const NewPageHeader = ({
13
16
  title,
14
17
  cancelLabel = 'Cancel',
15
18
  onCancel,
16
- className = ''
17
- }) => {
18
- return (
19
- <div className={`new-page-header-container ${className}`}>
20
- <div className="new-page-header">
21
- <h1 className="new-page-header__title">{title}</h1>
19
+ renderRight,
20
+ className = '',
21
+ showDivider = true,
22
+ dividerClassName = ''
23
+ }: NewPageHeaderProps) => (
24
+ <div className={`new-page-header-container ${className}`}>
25
+ <div className="new-page-header">
26
+ <h1 className="new-page-header__title">{title}</h1>
27
+ <div className="new-page-header__actions">
28
+ {renderRight && renderRight()}
22
29
  {onCancel && (
23
30
  <Button
24
31
  type="button"
@@ -29,7 +36,7 @@ export const NewPageHeader: React.FC<NewPageHeaderProps> = ({
29
36
  </Button>
30
37
  )}
31
38
  </div>
32
- <hr className="new-page-header__divider" />
33
39
  </div>
34
- );
35
- };
40
+ {showDivider && <hr className={`new-page-header__divider ${dividerClassName}`} />}
41
+ </div>
42
+ );
@@ -0,0 +1,126 @@
1
+ .new-table-wrapper {
2
+ width: 100%;
3
+ overflow-x: auto;
4
+ overflow-y: visible;
5
+
6
+ &.action-menu-open {
7
+ overflow: visible !important;
8
+ }
9
+ }
10
+
11
+ .new-table {
12
+ width: 100%;
13
+ border-collapse: collapse;
14
+ text-align: left;
15
+
16
+ &__head {
17
+ background-color: var(--surface-secondary, #F8F8FA);
18
+ }
19
+
20
+ &__header-cell {
21
+ padding: 16px 24px;
22
+ font-size: var(--text-small-size, 13px);
23
+ font-weight: 500;
24
+ color: var(--label-secondary, #9399B3);
25
+ border-bottom: 1px solid var(--border-primary, #E8E9EF);
26
+ white-space: nowrap;
27
+ }
28
+
29
+ &__body {
30
+ background-color: var(--neutral-white, #FFFFFF);
31
+ }
32
+
33
+ &__row {
34
+ border-bottom: 1px solid var(--border-primary, #E8E9EF);
35
+ transition: background-color 0.2s ease;
36
+ overflow: visible;
37
+
38
+ &.action-menu-open {
39
+ overflow: visible !important;
40
+ z-index: 20;
41
+ position: relative;
42
+
43
+ .new-table__cell {
44
+ overflow: visible !important;
45
+ }
46
+ }
47
+
48
+ &:last-child {
49
+ border-bottom: none;
50
+ }
51
+
52
+ &--clickable {
53
+ cursor: pointer;
54
+ &:hover {
55
+ background-color: var(--surface-primary-hover, #F8F8FA);
56
+ }
57
+ }
58
+ }
59
+
60
+ &__cell {
61
+ padding: 16px 24px;
62
+ font-size: var(--text-base-size, 14px);
63
+ color: var(--label-primary, #121E52);
64
+ vertical-align: middle;
65
+ overflow: visible;
66
+ }
67
+
68
+ &__no-data-cell {
69
+ padding: 64px 24px;
70
+ text-align: center;
71
+ font-size: 16px;
72
+ font-weight: 500;
73
+ color: #9399B3;
74
+ }
75
+ }
76
+
77
+ // Mobile styles
78
+ @media (max-width: 768px) {
79
+ .new-table-wrapper {
80
+ -webkit-overflow-scrolling: touch;
81
+ }
82
+
83
+ .new-table {
84
+ min-width: 600px; // Ensure table doesn't collapse too much
85
+
86
+ &__header-cell {
87
+ padding: 12px 16px;
88
+ font-size: 12px;
89
+ }
90
+
91
+ &__cell {
92
+ padding: 12px 16px;
93
+ font-size: 13px;
94
+ }
95
+
96
+ &__no-data-cell {
97
+ padding: 48px 16px;
98
+ font-size: 14px;
99
+ }
100
+ }
101
+ }
102
+
103
+ @media (max-width: 480px) {
104
+ .new-table {
105
+ min-width: 500px;
106
+
107
+ &__header-cell,
108
+ &__cell {
109
+ padding: 10px 12px;
110
+ }
111
+
112
+ &__header-cell {
113
+ font-size: 11px;
114
+ }
115
+
116
+ &__cell {
117
+ font-size: 12px;
118
+ }
119
+
120
+ &__no-data-cell {
121
+ padding: 32px 12px;
122
+ font-size: 13px;
123
+ }
124
+ }
125
+ }
126
+
@@ -0,0 +1,92 @@
1
+ import React from 'react'
2
+ import './NewTable.scss'
3
+
4
+ export interface NewTableColumn<T> {
5
+ header: React.ReactNode
6
+ accessor: keyof T | ((row: T) => React.ReactNode)
7
+ className?: string
8
+ width?: string | number
9
+ disableRowClick?: boolean
10
+ }
11
+
12
+ export interface NewTableProps<T> {
13
+ columns: NewTableColumn<T>[]
14
+ data: T[]
15
+ className?: string
16
+ rowClassName?: string | ((row: T) => string)
17
+ onRowClick?: (row: T) => void
18
+ noDataText?: string
19
+ }
20
+
21
+ export function NewTable<T extends { id?: string | number }>({
22
+ columns,
23
+ data,
24
+ className = '',
25
+ rowClassName = '',
26
+ onRowClick,
27
+ noDataText,
28
+ }: NewTableProps<T>) {
29
+ return (
30
+ <div className={`new-table-wrapper ${className}`}>
31
+ <table className="new-table">
32
+ <thead className="new-table__head">
33
+ <tr>
34
+ {columns.map((column, index) => (
35
+ <th
36
+ key={index}
37
+ className={`new-table__header-cell ${column.className || ''}`}
38
+ style={{ width: column.width }}
39
+ >
40
+ {column.header}
41
+ </th>
42
+ ))}
43
+ </tr>
44
+ </thead>
45
+ <tbody className="new-table__body">
46
+ {data.length > 0 ? (
47
+ data.map((row, rowIndex) => {
48
+ const customRowClass = typeof rowClassName === 'function' ? rowClassName(row) : rowClassName
49
+ return (
50
+ <tr
51
+ key={row.id || rowIndex}
52
+ className={`new-table__row ${onRowClick ? 'new-table__row--clickable' : ''} ${customRowClass}`}
53
+ onClick={() => onRowClick?.(row)}
54
+ >
55
+ {columns.map((column, colIndex) => {
56
+ const content =
57
+ typeof column.accessor === 'function'
58
+ ? column.accessor(row)
59
+ : (row[column.accessor] as React.ReactNode)
60
+
61
+ return (
62
+ <td
63
+ key={colIndex}
64
+ className={`new-table__cell ${column.className || ''}`}
65
+ role="presentation"
66
+ onClick={(e) => {
67
+ if (column.disableRowClick) {
68
+ e.stopPropagation()
69
+ }
70
+ }}
71
+ >
72
+ {content}
73
+ </td>
74
+ )
75
+ })}
76
+ </tr>
77
+ )
78
+ })
79
+ ) : (
80
+ noDataText && (
81
+ <tr className="new-table__no-data-row">
82
+ <td colSpan={columns.length} className="new-table__no-data-cell">
83
+ {noDataText}
84
+ </td>
85
+ </tr>
86
+ )
87
+ )}
88
+ </tbody>
89
+ </table>
90
+ </div>
91
+ )
92
+ }
@@ -0,0 +1 @@
1
+ export * from './NewTable'
@@ -0,0 +1,142 @@
1
+ .v2-pagination {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 16px;
5
+ font-family: var(--font-family-sans, 'Geist', sans-serif), serif;
6
+
7
+ &__controls {
8
+ display: flex;
9
+ gap: 8px;
10
+ }
11
+
12
+ &__button {
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ width: 44px;
17
+ height: 44px;
18
+ border-radius: 50%;
19
+ border: none;
20
+ cursor: pointer;
21
+ background-color: #efeffe; // Light purple background
22
+ color: #6200ee; // Primary purple color
23
+ transition: background-color 0.2s ease, color 0.2s ease;
24
+ flex-shrink: 0; // Prevent button from shrinking
25
+
26
+ &:hover:not(:disabled) {
27
+ background-color: #cdccfc;
28
+ }
29
+
30
+ &:active:not(:disabled) {
31
+ background-color: #b4b4fa;
32
+ }
33
+
34
+ &:focus-visible {
35
+ outline: 2px solid #6200ee;
36
+ outline-offset: 2px;
37
+ }
38
+
39
+ &:disabled {
40
+ background-color: #e5e7eb; // Light gray
41
+ color: #9ca3af; // Gray arrow
42
+ cursor: not-allowed;
43
+ }
44
+
45
+ svg {
46
+ width: 24px;
47
+ height: 24px;
48
+ flex-shrink: 0; // Prevent SVG from shrinking
49
+ }
50
+ }
51
+
52
+ &__info {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: 2px;
56
+ }
57
+
58
+ &__page-number {
59
+ font-size: 15px;
60
+ font-weight: 600;
61
+ color: #14215a; // Main fill primary
62
+ }
63
+
64
+ &__showing {
65
+ font-size: 13px;
66
+ font-weight: 500;
67
+ color: #626a90; // Secondary text color
68
+ }
69
+ }
70
+
71
+ // Mobile styles
72
+ @media (max-width: 768px) {
73
+ .v2-pagination {
74
+ gap: 12px;
75
+
76
+ &__controls {
77
+ gap: 6px;
78
+ }
79
+
80
+ &__button {
81
+ width: 40px;
82
+ height: 40px;
83
+
84
+ svg {
85
+ width: 20px;
86
+ height: 20px;
87
+ }
88
+ }
89
+
90
+ &__info {
91
+ gap: 2px;
92
+ }
93
+
94
+ &__page-number {
95
+ font-size: 14px;
96
+ }
97
+
98
+ &__showing {
99
+ font-size: 12px;
100
+ }
101
+ }
102
+ }
103
+
104
+ @media (max-width: 480px) {
105
+ .v2-pagination {
106
+ flex-direction: column;
107
+ gap: 10px;
108
+ align-items: flex-start;
109
+
110
+ &__controls {
111
+ order: 2;
112
+ width: 100%;
113
+ justify-content: center;
114
+ }
115
+
116
+ &__button {
117
+ width: 36px;
118
+ height: 36px;
119
+
120
+ svg {
121
+ width: 18px;
122
+ height: 18px;
123
+ }
124
+ }
125
+
126
+ &__info {
127
+ order: 1;
128
+ width: 100%;
129
+ text-align: center;
130
+ align-items: center;
131
+ }
132
+
133
+ &__page-number {
134
+ font-size: 13px;
135
+ }
136
+
137
+ &__showing {
138
+ font-size: 11px;
139
+ }
140
+ }
141
+ }
142
+