@shohojdhara/atomix 0.3.4 → 0.3.6

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 (237) hide show
  1. package/README.md +101 -199
  2. package/atomix.config.ts +241 -0
  3. package/dist/atomix.css +269 -189
  4. package/dist/atomix.css.map +1 -0
  5. package/dist/atomix.min.css +15179 -11
  6. package/dist/atomix.min.css.map +1 -0
  7. package/dist/charts.d.ts +1929 -0
  8. package/dist/charts.js +6477 -0
  9. package/dist/charts.js.map +1 -0
  10. package/dist/core.d.ts +1289 -0
  11. package/dist/core.js +3373 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/forms.d.ts +1085 -0
  14. package/dist/forms.js +2466 -0
  15. package/dist/forms.js.map +1 -0
  16. package/dist/heavy.d.ts +636 -0
  17. package/dist/heavy.js +4566 -0
  18. package/dist/heavy.js.map +1 -0
  19. package/dist/index.d.ts +5171 -4792
  20. package/dist/index.esm.js +6098 -4563
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +6291 -4747
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/layout.d.ts +300 -0
  27. package/dist/layout.js +336 -0
  28. package/dist/layout.js.map +1 -0
  29. package/dist/theme.d.ts +2122 -0
  30. package/dist/theme.js +6084 -0
  31. package/dist/theme.js.map +1 -0
  32. package/package.json +59 -27
  33. package/scripts/atomix-cli.js +544 -16
  34. package/scripts/cli/__tests__/cli-commands.test.js +204 -0
  35. package/scripts/cli/__tests__/utils.test.js +201 -0
  36. package/scripts/cli/__tests__/vitest.config.js +26 -0
  37. package/scripts/cli/interactive-init.js +1 -1
  38. package/scripts/cli/token-manager.js +32 -7
  39. package/scripts/cli/utils.js +347 -0
  40. package/src/components/Accordion/Accordion.stories.tsx +50 -17
  41. package/src/components/Accordion/Accordion.tsx +5 -54
  42. package/src/components/Accordion/index.ts +1 -1
  43. package/src/components/AtomixGlass/AtomixGlass.tsx +65 -31
  44. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +11 -4
  45. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
  46. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
  47. package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
  48. package/src/components/Avatar/Avatar.stories.tsx +7 -0
  49. package/src/components/Avatar/Avatar.tsx +3 -3
  50. package/src/components/Badge/Badge.stories.tsx +91 -13
  51. package/src/components/Badge/Badge.tsx +3 -3
  52. package/src/components/Block/Block.stories.tsx +7 -23
  53. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
  54. package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
  55. package/src/components/Button/Button.stories.tsx +141 -22
  56. package/src/components/Button/ButtonGroup.stories.tsx +315 -0
  57. package/src/components/Button/ButtonGroup.tsx +67 -0
  58. package/src/components/Button/index.ts +2 -0
  59. package/src/components/Callout/Callout.stories.tsx +8 -6
  60. package/src/components/Card/Card.stories.tsx +82 -28
  61. package/src/components/Card/ElevationCard.tsx +1 -1
  62. package/src/components/Chart/AnimatedChart.tsx +19 -18
  63. package/src/components/Chart/AreaChart.tsx +5 -2
  64. package/src/components/Chart/BarChart.tsx +1 -1
  65. package/src/components/Chart/BubbleChart.tsx +6 -6
  66. package/src/components/Chart/CandlestickChart.tsx +0 -1
  67. package/src/components/Chart/Chart.stories.tsx +5 -7
  68. package/src/components/Chart/Chart.tsx +0 -16
  69. package/src/components/Chart/ChartRenderer.tsx +1 -1
  70. package/src/components/Chart/ChartToolbar.tsx +1 -0
  71. package/src/components/Chart/DonutChart.tsx +0 -1
  72. package/src/components/Chart/FunnelChart.tsx +1 -2
  73. package/src/components/Chart/GaugeChart.tsx +0 -1
  74. package/src/components/Chart/HeatmapChart.tsx +0 -1
  75. package/src/components/Chart/LineChart.tsx +0 -1
  76. package/src/components/Chart/MultiAxisChart.tsx +0 -1
  77. package/src/components/Chart/PieChart.tsx +0 -1
  78. package/src/components/Chart/RadarChart.tsx +19 -13
  79. package/src/components/Chart/ScatterChart.tsx +3 -4
  80. package/src/components/Chart/TreemapChart.tsx +2 -1
  81. package/src/components/Chart/WaterfallChart.tsx +0 -2
  82. package/src/components/Chart/types.ts +12 -2
  83. package/src/components/Chart/utils.ts +4 -3
  84. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
  85. package/src/components/DataTable/DataTable.stories.tsx +23 -16
  86. package/src/components/DataTable/DataTable.tsx +3 -3
  87. package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
  88. package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
  89. package/src/components/Dropdown/Dropdown.tsx +12 -9
  90. package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
  91. package/src/components/Footer/Footer.stories.tsx +8 -6
  92. package/src/components/Footer/FooterLink.tsx +9 -2
  93. package/src/components/Footer/FooterSection.tsx +3 -3
  94. package/src/components/Form/Checkbox.stories.tsx +7 -0
  95. package/src/components/Form/Checkbox.tsx +3 -3
  96. package/src/components/Form/Form.stories.tsx +7 -0
  97. package/src/components/Form/FormGroup.stories.tsx +9 -1
  98. package/src/components/Form/Input.stories.tsx +69 -16
  99. package/src/components/Form/Input.tsx +4 -2
  100. package/src/components/Form/Radio.stories.tsx +9 -1
  101. package/src/components/Form/Radio.tsx +3 -3
  102. package/src/components/Form/Select.stories.tsx +9 -1
  103. package/src/components/Form/Select.tsx +3 -3
  104. package/src/components/Form/Textarea.stories.tsx +10 -2
  105. package/src/components/Form/Textarea.tsx +4 -2
  106. package/src/components/Hero/Hero.stories.tsx +7 -0
  107. package/src/components/List/List.stories.tsx +10 -3
  108. package/src/components/List/List.tsx +3 -3
  109. package/src/components/List/ListGroup.tsx +3 -1
  110. package/src/components/Messages/Messages.stories.tsx +8 -7
  111. package/src/components/Modal/Modal.stories.tsx +17 -6
  112. package/src/components/Modal/Modal.tsx +3 -3
  113. package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
  114. package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
  115. package/src/components/Navigation/Menu/Menu.tsx +9 -3
  116. package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
  117. package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
  118. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
  119. package/src/components/Pagination/Pagination.stories.tsx +188 -111
  120. package/src/components/Pagination/Pagination.tsx +88 -7
  121. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
  122. package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
  123. package/src/components/Popover/Popover.stories.tsx +191 -115
  124. package/src/components/Popover/Popover.tsx +4 -4
  125. package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
  126. package/src/components/Progress/Progress.stories.tsx +79 -49
  127. package/src/components/Progress/Progress.tsx +6 -2
  128. package/src/components/Rating/Rating.stories.tsx +109 -84
  129. package/src/components/Rating/Rating.tsx +5 -2
  130. package/src/components/River/River.stories.tsx +194 -114
  131. package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
  132. package/src/components/Slider/Slider.stories.tsx +7 -0
  133. package/src/components/Slider/Slider.tsx +10 -9
  134. package/src/components/Spinner/Spinner.stories.tsx +15 -11
  135. package/src/components/Spinner/Spinner.tsx +3 -3
  136. package/src/components/Steps/Steps.stories.tsx +132 -98
  137. package/src/components/Tabs/Tabs.stories.tsx +163 -112
  138. package/src/components/Tabs/Tabs.tsx +3 -3
  139. package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
  140. package/src/components/Todo/Todo.stories.tsx +38 -12
  141. package/src/components/Toggle/Toggle.stories.tsx +61 -28
  142. package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
  143. package/src/components/Tooltip/Tooltip.tsx +3 -3
  144. package/src/components/Upload/Upload.stories.tsx +122 -84
  145. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
  146. package/src/components/index.ts +6 -2
  147. package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
  148. package/src/lib/composables/useAtomixGlass.ts +2 -3
  149. package/src/lib/composables/useChartPerformance.ts +102 -78
  150. package/src/lib/composables/useChartScale.ts +10 -0
  151. package/src/lib/composables/useHero.ts +9 -2
  152. package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
  153. package/src/lib/composables/useNavbar.ts +0 -10
  154. package/src/lib/composables/useSideMenu.ts +1 -0
  155. package/src/lib/composables/useVideoPlayer.ts +3 -2
  156. package/src/lib/config/loader.ts +57 -14
  157. package/src/lib/constants/components.ts +10 -0
  158. package/src/lib/hooks/index.ts +0 -1
  159. package/src/lib/hooks/useComponentCustomization.ts +11 -15
  160. package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
  161. package/src/lib/patterns/index.ts +2 -2
  162. package/src/lib/patterns/slots.tsx +2 -2
  163. package/src/lib/theme/README.md +174 -0
  164. package/src/lib/theme/adapters/index.ts +31 -0
  165. package/src/lib/theme/adapters/themeAdapter.ts +287 -0
  166. package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
  167. package/src/lib/theme/config/configLoader.ts +254 -0
  168. package/src/lib/theme/config/loader.ts +37 -48
  169. package/src/lib/theme/config/types.ts +2 -2
  170. package/src/lib/theme/config/validator.ts +15 -91
  171. package/src/lib/theme/{constants.ts → constants/constants.ts} +0 -18
  172. package/src/lib/theme/constants/index.ts +8 -0
  173. package/src/lib/theme/core/ThemeRegistry.ts +19 -6
  174. package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
  175. package/src/lib/theme/core/composeTheme.ts +155 -0
  176. package/src/lib/theme/core/createTheme.ts +94 -0
  177. package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +10 -6
  178. package/src/lib/theme/core/index.ts +5 -19
  179. package/src/lib/theme/devtools/Comparator.tsx +346 -22
  180. package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
  181. package/src/lib/theme/devtools/Inspector.tsx +335 -51
  182. package/src/lib/theme/devtools/LiveEditor.tsx +489 -112
  183. package/src/lib/theme/devtools/Preview.tsx +471 -221
  184. package/src/lib/theme/{core → devtools}/ThemeValidator.ts +6 -3
  185. package/src/lib/theme/devtools/index.ts +14 -4
  186. package/src/lib/theme/devtools/useHistory.ts +130 -0
  187. package/src/lib/theme/errors/index.ts +12 -0
  188. package/src/lib/theme/generators/cssFile.ts +79 -0
  189. package/src/lib/theme/generators/generateCSS.ts +89 -0
  190. package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +4 -14
  191. package/src/lib/theme/generators/index.ts +19 -0
  192. package/src/lib/theme/i18n/rtl.ts +7 -7
  193. package/src/lib/theme/index.ts +120 -15
  194. package/src/lib/theme/runtime/ThemeApplicator.ts +53 -95
  195. package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
  196. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +4 -4
  197. package/src/lib/theme/runtime/ThemeProvider.tsx +456 -179
  198. package/src/lib/theme/runtime/index.ts +1 -2
  199. package/src/lib/theme/runtime/useTheme.ts +1 -2
  200. package/src/lib/theme/test/testTheme.ts +385 -0
  201. package/src/lib/theme/tokens/index.ts +12 -0
  202. package/src/lib/theme/tokens/tokens.ts +721 -0
  203. package/src/lib/theme/types.ts +6 -42
  204. package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
  205. package/src/lib/theme/utils/index.ts +11 -0
  206. package/src/lib/theme/utils/injectCSS.ts +90 -0
  207. package/src/lib/theme/utils/themeHelpers.ts +78 -0
  208. package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +1 -1
  209. package/src/lib/theme-tools.ts +8 -9
  210. package/src/lib/types/components.ts +93 -34
  211. package/src/lib/types/partProps.ts +0 -16
  212. package/src/lib/utils/componentUtils.ts +1 -1
  213. package/src/lib/utils/fontPreloader.ts +148 -0
  214. package/src/lib/utils/index.ts +11 -0
  215. package/src/lib/utils/memoryMonitor.ts +189 -0
  216. package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
  217. package/src/styles/01-settings/_settings.fonts.scss +2 -5
  218. package/src/styles/02-tools/_tools.button.scss +66 -79
  219. package/src/styles/06-components/_components.atomix-glass.scss +13 -3
  220. package/src/styles/06-components/_components.navbar.scss +0 -6
  221. package/src/styles/06-components/_components.pagination.scss +88 -0
  222. package/scripts/build-themes.js +0 -208
  223. package/scripts/sync-theme-config.js +0 -309
  224. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
  225. package/src/lib/theme/composeTheme.ts +0 -370
  226. package/src/lib/theme/core/ThemeCache.ts +0 -283
  227. package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
  228. package/src/lib/theme/core/ThemeEngine.ts +0 -657
  229. package/src/lib/theme/createThemeFromConfig.ts +0 -132
  230. package/src/lib/theme/devtools/CLI.ts +0 -364
  231. package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
  232. package/src/lib/theme/runtime/ThemeManager.ts +0 -442
  233. package/src/styles/03-generic/_generated-root.css +0 -5
  234. package/src/themes/README.md +0 -442
  235. package/src/themes/themes.config.js +0 -35
  236. /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
  237. /package/src/lib/theme/{errors.ts → errors/errors.ts} +0 -0
@@ -1,38 +1,62 @@
1
1
  import React, { useState } from 'react';
2
- import { Meta, StoryFn } from '@storybook/react';
3
- import { fn } from '@storybook/test';
2
+ import type { Meta, StoryObj } from '@storybook/react';
4
3
  import { Pagination } from './Pagination';
5
- import { PaginationProps } from '../../lib/types/components';
4
+ import { SIZES } from '../../lib/constants/components';
6
5
 
7
- export default {
6
+ const meta = {
8
7
  title: 'Components/Pagination',
9
8
  component: Pagination,
9
+ parameters: {
10
+ layout: 'centered',
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'The Pagination component provides navigation controls for moving through multiple pages of content. It displays page numbers, ellipsis for large page ranges, and optional first/last and previous/next buttons. Pagination supports keyboard navigation and is fully accessible.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
10
19
  argTypes: {
11
20
  currentPage: {
12
21
  control: 'number',
13
22
  description: 'Current active page',
23
+ defaultValue: 1,
14
24
  },
15
25
  totalPages: {
16
26
  control: 'number',
17
27
  description: 'Total number of pages',
28
+ defaultValue: 10,
18
29
  },
19
-
20
30
  siblingCount: {
21
31
  control: 'number',
22
32
  description: 'Number of page links to show before and after current page',
33
+ defaultValue: 1,
23
34
  },
24
35
  showFirstLastButtons: {
25
36
  control: 'boolean',
26
37
  description: 'Whether to show first/last page buttons',
38
+ defaultValue: true,
27
39
  },
28
40
  showPrevNextButtons: {
29
41
  control: 'boolean',
30
42
  description: 'Whether to show previous/next page buttons',
43
+ defaultValue: true,
44
+ },
45
+ showSearch: {
46
+ control: 'boolean',
47
+ description: 'Whether to show search input for jumping to a specific page',
48
+ defaultValue: false,
49
+ },
50
+ searchPlaceholder: {
51
+ control: 'text',
52
+ description: 'Placeholder text for the search input',
53
+ defaultValue: 'Go to page',
31
54
  },
32
55
  size: {
33
- control: 'select',
34
- options: ['sm', 'md', 'lg'],
56
+ control: { type: 'select' },
57
+ options: SIZES,
35
58
  description: 'Size variant for pagination',
59
+ defaultValue: 'md',
36
60
  },
37
61
  ariaLabel: {
38
62
  control: 'text',
@@ -47,19 +71,14 @@ export default {
47
71
  description: 'Enable glass morphism effect',
48
72
  },
49
73
  },
50
- parameters: {
51
- docs: {
52
- description: {
53
- component:
54
- 'A Pagination component for navigating through pages of content with enhanced accessibility, configurable sizes, and icons for navigation buttons.',
55
- },
56
- },
57
- },
58
- } as Meta<typeof Pagination>;
74
+ } satisfies Meta<typeof Pagination>;
75
+
76
+ export default meta;
77
+ type Story = StoryObj<typeof meta>;
59
78
 
60
- // Template with controlled state
61
- const ControlledTemplate: StoryFn<PaginationProps> = args => {
62
- const [currentPage, setCurrentPage] = useState(args.currentPage);
79
+ // Helper component for controlled pagination
80
+ const ControlledPagination = (args: React.ComponentProps<typeof Pagination>) => {
81
+ const [currentPage, setCurrentPage] = useState(args.currentPage || 1);
63
82
 
64
83
  const handlePageChange = (page: number) => {
65
84
  setCurrentPage(page);
@@ -69,129 +88,145 @@ const ControlledTemplate: StoryFn<PaginationProps> = args => {
69
88
  return <Pagination {...args} currentPage={currentPage} onPageChange={handlePageChange} />;
70
89
  };
71
90
 
72
- export const Default = ControlledTemplate.bind({});
73
- Default.args = {
74
- currentPage: 1,
75
- totalPages: 10,
76
- siblingCount: 1,
77
- showFirstLastButtons: true,
78
- showPrevNextButtons: true,
79
- size: 'md',
80
- ariaLabel: 'Pagination',
81
- };
82
- Default.parameters = {
83
- docs: {
84
- description: {
85
- story: 'Default pagination with first/last and previous/next navigation buttons using icons.',
91
+ export const Default: Story = {
92
+ render: args => <ControlledPagination {...args} />,
93
+ args: {
94
+ currentPage: 1,
95
+ totalPages: 10,
96
+ siblingCount: 1,
97
+ showFirstLastButtons: true,
98
+ showPrevNextButtons: true,
99
+ size: 'md',
100
+ ariaLabel: 'Pagination',
101
+ },
102
+ parameters: {
103
+ docs: {
104
+ description: {
105
+ story: 'Default pagination with first/last and previous/next navigation buttons using icons.',
106
+ },
86
107
  },
87
108
  },
88
109
  };
89
110
 
90
- export const WithMorePages = ControlledTemplate.bind({});
91
- WithMorePages.args = {
92
- currentPage: 25,
93
- totalPages: 50,
94
- siblingCount: 2,
95
- size: 'md',
96
- };
97
- WithMorePages.parameters = {
98
- docs: {
99
- description: {
100
- story: 'Pagination with many pages, showing the ellipsis (dots) for page ranges.',
111
+ export const WithMorePages: Story = {
112
+ render: args => <ControlledPagination {...args} />,
113
+ args: {
114
+ currentPage: 25,
115
+ totalPages: 50,
116
+ siblingCount: 2,
117
+ size: 'md',
118
+ },
119
+ parameters: {
120
+ docs: {
121
+ description: {
122
+ story: 'Pagination with many pages, showing the ellipsis (dots) for page ranges.',
123
+ },
101
124
  },
102
125
  },
103
126
  };
104
127
 
105
- export const SmallSize = ControlledTemplate.bind({});
106
- SmallSize.args = {
107
- currentPage: 4,
108
- totalPages: 10,
109
- siblingCount: 1,
110
- size: 'sm',
111
- };
112
- SmallSize.parameters = {
113
- docs: {
114
- description: {
115
- story: 'Small-sized pagination component with smaller icons and buttons.',
128
+ export const SmallSize: Story = {
129
+ render: args => <ControlledPagination {...args} />,
130
+ args: {
131
+ currentPage: 4,
132
+ totalPages: 10,
133
+ siblingCount: 1,
134
+ size: 'sm',
135
+ },
136
+ parameters: {
137
+ docs: {
138
+ description: {
139
+ story: 'Small-sized pagination component with smaller icons and buttons.',
140
+ },
116
141
  },
117
142
  },
118
143
  };
119
144
 
120
- export const LargeSize = ControlledTemplate.bind({});
121
- LargeSize.args = {
122
- currentPage: 4,
123
- totalPages: 10,
124
- siblingCount: 1,
125
- size: 'lg',
126
- };
127
- LargeSize.parameters = {
128
- docs: {
129
- description: {
130
- story: 'Large-sized pagination component with larger icons and buttons.',
145
+ export const LargeSize: Story = {
146
+ render: args => <ControlledPagination {...args} />,
147
+ args: {
148
+ currentPage: 4,
149
+ totalPages: 10,
150
+ siblingCount: 1,
151
+ size: 'lg',
152
+ },
153
+ parameters: {
154
+ docs: {
155
+ description: {
156
+ story: 'Large-sized pagination component with larger icons and buttons.',
157
+ },
131
158
  },
132
159
  },
133
160
  };
134
161
 
135
- export const FewPages = ControlledTemplate.bind({});
136
- FewPages.args = {
137
- currentPage: 2,
138
- totalPages: 3,
139
- siblingCount: 1,
140
- };
141
- FewPages.parameters = {
142
- docs: {
143
- description: {
144
- story: 'Pagination with only a few pages, showing all page numbers without ellipsis.',
162
+ export const FewPages: Story = {
163
+ render: args => <ControlledPagination {...args} />,
164
+ args: {
165
+ currentPage: 2,
166
+ totalPages: 3,
167
+ siblingCount: 1,
168
+ },
169
+ parameters: {
170
+ docs: {
171
+ description: {
172
+ story: 'Pagination with only a few pages, showing all page numbers without ellipsis.',
173
+ },
145
174
  },
146
175
  },
147
176
  };
148
177
 
149
- export const NoFirstLastButtons = ControlledTemplate.bind({});
150
- NoFirstLastButtons.args = {
151
- currentPage: 5,
152
- totalPages: 15,
153
- showFirstLastButtons: false,
154
- showPrevNextButtons: true,
155
- };
156
- NoFirstLastButtons.parameters = {
157
- docs: {
158
- description: {
159
- story: 'Pagination with only previous/next navigation buttons (no skip to first/last).',
178
+ export const NoFirstLastButtons: Story = {
179
+ render: args => <ControlledPagination {...args} />,
180
+ args: {
181
+ currentPage: 5,
182
+ totalPages: 15,
183
+ showFirstLastButtons: false,
184
+ showPrevNextButtons: true,
185
+ },
186
+ parameters: {
187
+ docs: {
188
+ description: {
189
+ story: 'Pagination with only previous/next navigation buttons (no skip to first/last).',
190
+ },
160
191
  },
161
192
  },
162
193
  };
163
194
 
164
- export const OnlyPageNumbers = ControlledTemplate.bind({});
165
- OnlyPageNumbers.args = {
166
- currentPage: 5,
167
- totalPages: 15,
168
- showFirstLastButtons: false,
169
- showPrevNextButtons: false,
170
- };
171
- OnlyPageNumbers.parameters = {
172
- docs: {
173
- description: {
174
- story: 'Pagination with only page numbers, no navigation buttons.',
195
+ export const OnlyPageNumbers: Story = {
196
+ render: args => <ControlledPagination {...args} />,
197
+ args: {
198
+ currentPage: 5,
199
+ totalPages: 15,
200
+ showFirstLastButtons: false,
201
+ showPrevNextButtons: false,
202
+ },
203
+ parameters: {
204
+ docs: {
205
+ description: {
206
+ story: 'Pagination with only page numbers, no navigation buttons.',
207
+ },
175
208
  },
176
209
  },
177
210
  };
178
211
 
179
- export const CustomStyling = ControlledTemplate.bind({});
180
- CustomStyling.args = {
181
- currentPage: 5,
182
- totalPages: 15,
183
- className: 'custom-pagination-class',
184
- showFirstLastButtons: false,
185
- };
186
- CustomStyling.parameters = {
187
- docs: {
188
- description: {
189
- story: 'Pagination with custom CSS class for additional styling.',
212
+ export const CustomStyling: Story = {
213
+ render: args => <ControlledPagination {...args} />,
214
+ args: {
215
+ currentPage: 5,
216
+ totalPages: 15,
217
+ className: 'custom-pagination-class',
218
+ showFirstLastButtons: false,
219
+ },
220
+ parameters: {
221
+ docs: {
222
+ description: {
223
+ story: 'Pagination with custom CSS class for additional styling.',
224
+ },
190
225
  },
191
226
  },
192
227
  };
193
228
 
194
- export const Glass = {
229
+ export const Glass: Story = {
195
230
  args: {
196
231
  currentPage: 5,
197
232
  totalPages: 15,
@@ -233,7 +268,7 @@ export const Glass = {
233
268
  },
234
269
  };
235
270
 
236
- export const GlassCustom = {
271
+ export const GlassCustom: Story = {
237
272
  args: {
238
273
  currentPage: 5,
239
274
  totalPages: 15,
@@ -294,3 +329,45 @@ export const GlassCustom = {
294
329
  },
295
330
  },
296
331
  };
332
+
333
+ export const WithSearch: Story = {
334
+ render: args => <ControlledPagination {...args} />,
335
+ args: {
336
+ currentPage: 5,
337
+ totalPages: 50,
338
+ siblingCount: 2,
339
+ showFirstLastButtons: true,
340
+ showPrevNextButtons: true,
341
+ showSearch: true,
342
+ searchPlaceholder: 'Go to page',
343
+ size: 'md',
344
+ },
345
+ parameters: {
346
+ docs: {
347
+ description: {
348
+ story: 'Pagination with search functionality to quickly jump to a specific page. Users can type a page number and submit to navigate directly.',
349
+ },
350
+ },
351
+ },
352
+ };
353
+
354
+ export const WithSearchLargeDataset: Story = {
355
+ render: args => <ControlledPagination {...args} />,
356
+ args: {
357
+ currentPage: 250,
358
+ totalPages: 1000,
359
+ siblingCount: 2,
360
+ showFirstLastButtons: true,
361
+ showPrevNextButtons: true,
362
+ showSearch: true,
363
+ searchPlaceholder: 'Enter page number',
364
+ size: 'md',
365
+ },
366
+ parameters: {
367
+ docs: {
368
+ description: {
369
+ story: 'Pagination with search functionality for large datasets. The search feature is especially useful when dealing with many pages.',
370
+ },
371
+ },
372
+ },
373
+ };
@@ -1,12 +1,10 @@
1
- import React from 'react';
1
+ import React, { memo, useState, FormEvent } from 'react';
2
2
  import { PaginationProps } from '../../lib/types/components';
3
3
  import { usePagination, DOTS } from '../../lib/composables/usePagination';
4
4
  import { PAGINATION_DEFAULTS } from '../../lib/constants/components';
5
5
  import { Icon, IconProps } from '../Icon/Icon';
6
6
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
7
7
 
8
- // @TODO: Add Search functionality for pagination
9
-
10
8
  /**
11
9
  * Navigation button types for pagination
12
10
  */
@@ -26,7 +24,7 @@ interface PaginationNavButtonProps {
26
24
  /**
27
25
  * PaginationNavButton component for rendering first, previous, next, and last buttons
28
26
  */
29
- export const PaginationNavButton: React.FC<PaginationNavButtonProps> = ({
27
+ export const PaginationNavButton: React.FC<PaginationNavButtonProps> = memo(({
30
28
  type,
31
29
  onClick,
32
30
  disabled,
@@ -47,18 +45,20 @@ export const PaginationNavButton: React.FC<PaginationNavButtonProps> = ({
47
45
  <Icon name={iconName} size="sm" aria-hidden="true" />
48
46
  </button>
49
47
  </li>
50
- );
48
+ ));
51
49
 
52
50
  /**
53
51
  * Pagination component
54
52
  */
55
- export const Pagination: React.FC<PaginationProps> = ({
53
+ export const Pagination: React.FC<PaginationProps> = memo(({
56
54
  currentPage = PAGINATION_DEFAULTS.currentPage,
57
55
  totalPages = PAGINATION_DEFAULTS.totalPages,
58
56
  onPageChange,
59
57
  siblingCount = PAGINATION_DEFAULTS.siblingCount,
60
58
  showFirstLastButtons = PAGINATION_DEFAULTS.showFirstLastButtons,
61
59
  showPrevNextButtons = PAGINATION_DEFAULTS.showPrevNextButtons,
60
+ showSearch = false,
61
+ searchPlaceholder = 'Go to page',
62
62
  size = PAGINATION_DEFAULTS.size,
63
63
  className = '',
64
64
  style,
@@ -72,11 +72,48 @@ export const Pagination: React.FC<PaginationProps> = ({
72
72
  onPageChange,
73
73
  });
74
74
 
75
+ const [searchValue, setSearchValue] = useState<string>('');
76
+ const [searchError, setSearchError] = useState<string>('');
77
+
75
78
  // Don't render pagination with a single page or no pages
76
79
  if (currentPage === 0 || paginationRange.length < 2) {
77
80
  return null;
78
81
  }
79
82
 
83
+ const handleSearchSubmit = (e: FormEvent<HTMLFormElement>) => {
84
+ e.preventDefault();
85
+ setSearchError('');
86
+
87
+ const pageNumber = parseInt(searchValue, 10);
88
+
89
+ if (isNaN(pageNumber)) {
90
+ setSearchError('Please enter a valid page number');
91
+ return;
92
+ }
93
+
94
+ if (pageNumber < 1 || pageNumber > totalPages) {
95
+ setSearchError(`Page must be between 1 and ${totalPages}`);
96
+ return;
97
+ }
98
+
99
+ if (pageNumber === currentPage) {
100
+ setSearchError('You are already on this page');
101
+ return;
102
+ }
103
+
104
+ goToPage(pageNumber);
105
+ setSearchValue('');
106
+ };
107
+
108
+ const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
109
+ const value = e.target.value;
110
+ // Only allow numbers
111
+ if (value === '' || /^\d+$/.test(value)) {
112
+ setSearchValue(value);
113
+ setSearchError('');
114
+ }
115
+ };
116
+
80
117
  const paginationContent = (
81
118
  <nav
82
119
  className={`c-pagination c-pagination--${size} ${className}`}
@@ -158,6 +195,49 @@ export const Pagination: React.FC<PaginationProps> = ({
158
195
  />
159
196
  )}
160
197
  </ul>
198
+
199
+ {showSearch && (
200
+ <form
201
+ className="c-pagination__search"
202
+ onSubmit={handleSearchSubmit}
203
+ aria-label="Jump to page"
204
+ >
205
+ <div className="c-pagination__search-wrapper">
206
+ <label htmlFor={`pagination-search-${currentPage}`} className="c-pagination__search-label">
207
+ <span className="c-pagination__search-label-text">Go to page:</span>
208
+ <input
209
+ id={`pagination-search-${currentPage}`}
210
+ type="text"
211
+ inputMode="numeric"
212
+ pattern="[0-9]*"
213
+ className={`c-pagination__search-input ${searchError ? 'is-error' : ''}`}
214
+ placeholder={searchPlaceholder}
215
+ value={searchValue}
216
+ onChange={handleSearchChange}
217
+ aria-label="Page number"
218
+ aria-invalid={searchError ? 'true' : 'false'}
219
+ aria-describedby={searchError ? `pagination-error-${currentPage}` : undefined}
220
+ />
221
+ </label>
222
+ <button
223
+ type="submit"
224
+ className="c-pagination__search-button"
225
+ aria-label="Go to page"
226
+ >
227
+ <Icon name="ArrowRight" size="sm" aria-hidden="true" />
228
+ </button>
229
+ </div>
230
+ {searchError && (
231
+ <div
232
+ id={`pagination-error-${currentPage}`}
233
+ className="c-pagination__search-error"
234
+ role="alert"
235
+ >
236
+ {searchError}
237
+ </div>
238
+ )}
239
+ </form>
240
+ )}
161
241
  </nav>
162
242
  );
163
243
 
@@ -178,10 +258,11 @@ export const Pagination: React.FC<PaginationProps> = ({
178
258
  }
179
259
 
180
260
  return paginationContent;
181
- };
261
+ });
182
262
 
183
263
  export type { PaginationProps };
184
264
 
185
265
  Pagination.displayName = 'Pagination';
266
+ PaginationNavButton.displayName = 'PaginationNavButton';
186
267
 
187
268
  export default Pagination;
@@ -1,11 +1,11 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
2
  import React from 'react';
3
3
  import { ImageType } from '../../lib/types/components';
4
4
  import { Badge } from '../Badge/Badge';
5
5
  import { Button } from '../Button/Button';
6
6
  import { PhotoViewer } from './PhotoViewer';
7
7
 
8
- const meta: Meta<typeof PhotoViewer> = {
8
+ const meta = {
9
9
  title: 'Components/PhotoViewer',
10
10
  component: PhotoViewer,
11
11
  parameters: {
@@ -13,29 +13,34 @@ const meta: Meta<typeof PhotoViewer> = {
13
13
  docs: {
14
14
  description: {
15
15
  component:
16
- 'A modern, fully-featured photo viewer component with zoom, pan, navigation, and metadata display capabilities.',
16
+ 'The PhotoViewer component provides a modern, fully-featured image viewing experience with zoom, pan, navigation, and metadata display. It supports image galleries, keyboard navigation, touch gestures, and fullscreen mode. Ideal for photo galleries, media libraries, or any application requiring detailed image viewing capabilities.',
17
17
  },
18
18
  },
19
19
  },
20
+ tags: ['autodocs'],
20
21
  argTypes: {
21
22
  thumbnailPosition: {
22
23
  control: 'select',
23
24
  options: ['bottom', 'top', 'left', 'right', 'none'],
25
+ description: 'Position of the thumbnail navigation',
24
26
  },
25
27
  enableKeyboardNavigation: {
26
28
  control: 'boolean',
29
+ description: 'Whether to enable keyboard navigation',
27
30
  },
28
31
  enableGestures: {
29
32
  control: 'boolean',
33
+ description: 'Whether to enable touch gestures',
30
34
  },
31
35
  enableFullscreen: {
32
36
  control: 'boolean',
37
+ description: 'Whether to enable fullscreen mode',
33
38
  },
34
39
  },
35
- };
40
+ } satisfies Meta<typeof PhotoViewer>;
36
41
 
37
42
  export default meta;
38
- type Story = StoryObj<typeof PhotoViewer>;
43
+ type Story = StoryObj<typeof meta>;
39
44
 
40
45
  // Sample images with rich metadata
41
46
  const sampleImages: ImageType[] = [
@@ -5,7 +5,7 @@ import React, { useRef, useEffect, useState } from 'react';
5
5
  */
6
6
  export interface PhotoViewerImageProps {
7
7
  /** Ref to the image element */
8
- imageRef: React.RefObject<HTMLImageElement | null>;
8
+ imageRef: React.RefObject<HTMLImageElement>;
9
9
  /** Ref to the container element */
10
10
  containerRef?: React.RefObject<HTMLDivElement | null>;
11
11
  /** Image source URL */
@@ -134,7 +134,7 @@ export const PhotoViewerImage: React.FC<PhotoViewerImageProps> = ({
134
134
 
135
135
  return (
136
136
  <div
137
- ref={effectiveContainerRef}
137
+ ref={effectiveContainerRef as React.LegacyRef<HTMLDivElement>}
138
138
  className={`c-photo-viewer__image-container ${isTransitioning ? 'is-transitioning' : ''}`}
139
139
  style={{
140
140
  cursor: isDragging ? 'grabbing' : zoomLevel > 1 ? 'grab' : 'default',