@shohojdhara/atomix 0.3.5 → 0.3.7

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 (182) hide show
  1. package/README.md +101 -199
  2. package/atomix.config.ts +241 -0
  3. package/dist/atomix.css +260 -179
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +250 -179
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.js +69 -166
  8. package/dist/charts.js.map +1 -1
  9. package/dist/core.js +184 -263
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.js +55 -131
  12. package/dist/forms.js.map +1 -1
  13. package/dist/heavy.js +184 -263
  14. package/dist/heavy.js.map +1 -1
  15. package/dist/index.d.ts +1831 -1657
  16. package/dist/index.esm.js +4497 -4318
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +4510 -4328
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.min.js +1 -1
  21. package/dist/index.min.js.map +1 -1
  22. package/dist/theme.d.ts +1431 -1472
  23. package/dist/theme.js +4175 -4138
  24. package/dist/theme.js.map +1 -1
  25. package/package.json +6 -20
  26. package/src/components/Accordion/Accordion.stories.tsx +50 -17
  27. package/src/components/AtomixGlass/AtomixGlass.tsx +128 -322
  28. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +12 -5
  29. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
  31. package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
  32. package/src/components/Avatar/Avatar.stories.tsx +7 -0
  33. package/src/components/Badge/Badge.stories.tsx +91 -13
  34. package/src/components/Block/Block.stories.tsx +7 -23
  35. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
  36. package/src/components/Button/Button.stories.tsx +141 -22
  37. package/src/components/Button/Button.tsx +85 -167
  38. package/src/components/Button/ButtonGroup.stories.tsx +315 -0
  39. package/src/components/Button/ButtonGroup.tsx +67 -0
  40. package/src/components/Button/index.ts +2 -0
  41. package/src/components/Callout/Callout.stories.tsx +8 -6
  42. package/src/components/Card/Card.stories.tsx +82 -28
  43. package/src/components/Chart/AnimatedChart.tsx +0 -1
  44. package/src/components/Chart/AreaChart.tsx +0 -1
  45. package/src/components/Chart/BarChart.tsx +0 -1
  46. package/src/components/Chart/BubbleChart.tsx +0 -1
  47. package/src/components/Chart/CandlestickChart.tsx +0 -1
  48. package/src/components/Chart/Chart.stories.tsx +5 -7
  49. package/src/components/Chart/Chart.tsx +0 -16
  50. package/src/components/Chart/ChartRenderer.tsx +1 -1
  51. package/src/components/Chart/DonutChart.tsx +0 -1
  52. package/src/components/Chart/FunnelChart.tsx +0 -1
  53. package/src/components/Chart/GaugeChart.tsx +0 -1
  54. package/src/components/Chart/HeatmapChart.tsx +0 -1
  55. package/src/components/Chart/LineChart.tsx +0 -1
  56. package/src/components/Chart/MultiAxisChart.tsx +0 -1
  57. package/src/components/Chart/PieChart.tsx +0 -1
  58. package/src/components/Chart/RadarChart.tsx +0 -1
  59. package/src/components/Chart/ScatterChart.tsx +0 -1
  60. package/src/components/Chart/WaterfallChart.tsx +0 -1
  61. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
  62. package/src/components/DataTable/DataTable.stories.tsx +23 -16
  63. package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
  64. package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
  65. package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
  66. package/src/components/Footer/Footer.stories.tsx +8 -6
  67. package/src/components/Footer/FooterLink.tsx +9 -2
  68. package/src/components/Form/Checkbox.stories.tsx +7 -0
  69. package/src/components/Form/Form.stories.tsx +7 -0
  70. package/src/components/Form/FormGroup.stories.tsx +9 -1
  71. package/src/components/Form/Input.stories.tsx +69 -16
  72. package/src/components/Form/Radio.stories.tsx +9 -1
  73. package/src/components/Form/Select.stories.tsx +9 -1
  74. package/src/components/Form/Textarea.stories.tsx +10 -2
  75. package/src/components/Hero/Hero.stories.tsx +7 -0
  76. package/src/components/List/List.stories.tsx +7 -0
  77. package/src/components/Messages/Messages.stories.tsx +8 -7
  78. package/src/components/Modal/Modal.stories.tsx +17 -6
  79. package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
  80. package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
  81. package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
  82. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
  83. package/src/components/Pagination/Pagination.stories.tsx +188 -111
  84. package/src/components/Pagination/Pagination.tsx +83 -3
  85. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
  86. package/src/components/Popover/Popover.stories.tsx +191 -115
  87. package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
  88. package/src/components/Progress/Progress.stories.tsx +79 -49
  89. package/src/components/Rating/Rating.stories.tsx +109 -84
  90. package/src/components/River/River.stories.tsx +194 -114
  91. package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
  92. package/src/components/Slider/Slider.stories.tsx +7 -0
  93. package/src/components/Spinner/Spinner.stories.tsx +15 -11
  94. package/src/components/Steps/Steps.stories.tsx +132 -98
  95. package/src/components/Tabs/Tabs.stories.tsx +163 -112
  96. package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
  97. package/src/components/Todo/Todo.stories.tsx +38 -12
  98. package/src/components/Toggle/Toggle.stories.tsx +61 -28
  99. package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
  100. package/src/components/Upload/Upload.stories.tsx +122 -84
  101. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
  102. package/src/components/index.ts +1 -0
  103. package/src/lib/composables/useAtomixGlass.ts +9 -10
  104. package/src/lib/composables/useNavbar.ts +0 -10
  105. package/src/lib/config/loader.ts +4 -4
  106. package/src/lib/constants/components.ts +17 -0
  107. package/src/lib/hooks/useComponentCustomization.ts +1 -1
  108. package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
  109. package/src/lib/hooks/useThemeTokens.ts +105 -0
  110. package/src/lib/theme/README.md +174 -0
  111. package/src/lib/theme/adapters/index.ts +31 -0
  112. package/src/lib/theme/adapters/themeAdapter.ts +287 -0
  113. package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
  114. package/src/lib/theme/config/configLoader.ts +95 -0
  115. package/src/lib/theme/config/loader.ts +37 -54
  116. package/src/lib/theme/config/types.ts +2 -2
  117. package/src/lib/theme/config/validator.ts +15 -91
  118. package/src/lib/theme/{constants.ts → constants/constants.ts} +1 -19
  119. package/src/lib/theme/constants/index.ts +8 -0
  120. package/src/lib/theme/core/ThemeRegistry.ts +75 -266
  121. package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
  122. package/src/lib/theme/core/composeTheme.ts +105 -0
  123. package/src/lib/theme/core/createTheme.ts +108 -0
  124. package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +12 -8
  125. package/src/lib/theme/core/index.ts +19 -19
  126. package/src/lib/theme/devtools/Comparator.tsx +346 -22
  127. package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
  128. package/src/lib/theme/devtools/Inspector.tsx +335 -51
  129. package/src/lib/theme/devtools/LiveEditor.tsx +478 -107
  130. package/src/lib/theme/devtools/Preview.tsx +471 -221
  131. package/src/lib/theme/{core → devtools}/ThemeValidator.ts +1 -1
  132. package/src/lib/theme/devtools/index.ts +14 -4
  133. package/src/lib/theme/devtools/useHistory.ts +130 -0
  134. package/src/lib/theme/{errors.ts → errors/errors.ts} +1 -1
  135. package/src/lib/theme/errors/index.ts +12 -0
  136. package/src/lib/theme/generators/cssFile.ts +79 -0
  137. package/src/lib/theme/generators/generateCSS.ts +89 -0
  138. package/src/lib/theme/generators/generateCSSNested.ts +130 -0
  139. package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +3 -13
  140. package/src/lib/theme/generators/index.ts +25 -0
  141. package/src/lib/theme/i18n/rtl.ts +5 -6
  142. package/src/lib/theme/index.ts +149 -19
  143. package/src/lib/theme/runtime/ThemeApplicator.ts +53 -112
  144. package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
  145. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +5 -5
  146. package/src/lib/theme/runtime/ThemeProvider.tsx +266 -282
  147. package/src/lib/theme/runtime/index.ts +2 -2
  148. package/src/lib/theme/runtime/useTheme.ts +1 -2
  149. package/src/lib/theme/runtime/useThemeTokens.ts +131 -0
  150. package/src/lib/theme/test/testTheme.ts +385 -0
  151. package/src/lib/theme/tokens/index.ts +12 -0
  152. package/src/lib/theme/tokens/tokens.ts +721 -0
  153. package/src/lib/theme/types.ts +6 -42
  154. package/src/lib/theme/utils/componentTheming.ts +132 -0
  155. package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
  156. package/src/lib/theme/utils/index.ts +11 -0
  157. package/src/lib/theme/utils/injectCSS.ts +90 -0
  158. package/src/lib/theme/utils/naming.ts +100 -0
  159. package/src/lib/theme/utils/themeHelpers.ts +78 -0
  160. package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +7 -7
  161. package/src/lib/theme-tools.ts +7 -8
  162. package/src/lib/types/components.ts +40 -130
  163. package/src/lib/utils/componentUtils.ts +2 -2
  164. package/src/lib/utils/memoryMonitor.ts +3 -3
  165. package/src/lib/utils/themeNaming.ts +135 -0
  166. package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
  167. package/src/styles/02-tools/_tools.button.scss +66 -79
  168. package/src/styles/06-components/_components.atomix-glass.scss +13 -3
  169. package/src/styles/06-components/_components.pagination.scss +88 -0
  170. package/scripts/sync-theme-config.js +0 -309
  171. package/src/lib/theme/composeTheme.ts +0 -370
  172. package/src/lib/theme/core/ThemeCache.ts +0 -283
  173. package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
  174. package/src/lib/theme/core/ThemeEngine.ts +0 -665
  175. package/src/lib/theme/createThemeFromConfig.ts +0 -132
  176. package/src/lib/theme/devtools/CLI.ts +0 -364
  177. package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
  178. package/src/lib/theme/runtime/ThemeManager.ts +0 -446
  179. package/src/styles/03-generic/_generated-root.css +0 -26
  180. package/src/themes/README.md +0 -442
  181. package/src/themes/themes.config.js +0 -68
  182. /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
@@ -1,16 +1,27 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { useState } from 'react';
3
+ import type { AtomixGlassProps } from '../../lib/types/components';
3
4
  import Modal from './Modal';
4
5
 
5
- const meta: Meta<typeof Modal> = {
6
+ // Helper type for glass props in stories (without children requirement)
7
+ type GlassProps = boolean | Omit<AtomixGlassProps, 'children'>;
8
+
9
+ const meta = {
6
10
  title: 'Components/Modal',
7
11
  component: Modal,
8
12
  parameters: {
9
13
  layout: 'centered',
14
+ docs: {
15
+ description: {
16
+ component:
17
+ 'The Modal component displays content in a focused overlay dialog. It provides a way to present important information or actions that require user attention. Modals support various sizes, can include headers and footers, and support glass morphism effects.',
18
+ },
19
+ },
10
20
  },
21
+ tags: ['autodocs'],
11
22
  argTypes: {
12
23
  size: {
13
- control: 'select',
24
+ control: { type: 'select' },
14
25
  options: ['sm', 'md', 'lg', 'xl'],
15
26
  description: 'Size of the modal',
16
27
  defaultValue: 'md',
@@ -35,10 +46,10 @@ const meta: Meta<typeof Modal> = {
35
46
  description: 'Enable glass morphism effect',
36
47
  },
37
48
  },
38
- };
49
+ } satisfies Meta<typeof Modal>;
39
50
 
40
51
  export default meta;
41
- type Story = StoryObj<typeof Modal>;
52
+ type Story = StoryObj<typeof meta>;
42
53
 
43
54
  /**
44
55
  * Basic modal example with a button to trigger opening.
@@ -377,7 +388,7 @@ export const GlassModalCustom: Story = {
377
388
  aberrationIntensity: 2,
378
389
  cornerRadius: 20,
379
390
  mode: 'polar',
380
- } as any
391
+ } as GlassProps
381
392
  }
382
393
  footer={
383
394
  <>
@@ -6,7 +6,14 @@ const meta = {
6
6
  component: Menu,
7
7
  parameters: {
8
8
  layout: 'centered',
9
+ docs: {
10
+ description: {
11
+ component:
12
+ 'The Menu component provides a vertical list of menu items, typically used in dropdowns, sidebars, or context menus. It supports dividers, icons, and can be nested. Menus are ideal for organizing navigation options, actions, or any hierarchical list of choices.',
13
+ },
14
+ },
9
15
  },
16
+ tags: ['autodocs'],
10
17
  argTypes: {
11
18
  disabled: {
12
19
  control: 'boolean',
@@ -9,7 +9,14 @@ const meta = {
9
9
  component: Nav,
10
10
  parameters: {
11
11
  layout: 'centered',
12
+ docs: {
13
+ description: {
14
+ component:
15
+ 'The Nav component provides a horizontal navigation bar for organizing links and menu items. It supports various alignment options, can include dropdowns, and provides a clean interface for site navigation. Nav components are essential for primary site navigation and work seamlessly with NavItem and NavDropdown components.',
16
+ },
17
+ },
12
18
  },
19
+ tags: ['autodocs'],
13
20
  argTypes: {
14
21
  alignment: {
15
22
  control: { type: 'select' },
@@ -71,6 +71,7 @@ The Navbar component provides a responsive navigation header with brand, navigat
71
71
  },
72
72
  },
73
73
  },
74
+ tags: ['autodocs'],
74
75
  argTypes: {
75
76
  position: {
76
77
  control: { type: 'select' },
@@ -138,7 +138,7 @@ The SideMenu component provides a collapsible navigation menu with title and men
138
138
  } satisfies Meta<typeof SideMenu>;
139
139
 
140
140
  export default meta;
141
- type Story = StoryObj<typeof SideMenu>;
141
+ type Story = StoryObj<typeof meta>;
142
142
 
143
143
  // Default SideMenu
144
144
  export const Default: Story = {
@@ -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, { memo } 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
  */
@@ -59,6 +57,8 @@ export const Pagination: React.FC<PaginationProps> = memo(({
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> = memo(({
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> = memo(({
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
 
@@ -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[] = [