@shohojdhara/atomix 0.3.5 → 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.
- package/README.md +101 -199
- package/atomix.config.ts +241 -0
- package/dist/atomix.css +260 -179
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +250 -179
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +61 -66
- package/dist/charts.js.map +1 -1
- package/dist/core.js +47 -31
- package/dist/core.js.map +1 -1
- package/dist/forms.js +47 -31
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +47 -31
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1841 -1633
- package/dist/index.esm.js +4975 -4113
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +5151 -4290
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +1572 -1442
- package/dist/theme.js +4816 -4080
- package/dist/theme.js.map +1 -1
- package/package.json +6 -20
- package/src/components/Accordion/Accordion.stories.tsx +50 -17
- package/src/components/AtomixGlass/AtomixGlass.tsx +65 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +11 -4
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
- package/src/components/Avatar/Avatar.stories.tsx +7 -0
- package/src/components/Badge/Badge.stories.tsx +91 -13
- package/src/components/Block/Block.stories.tsx +7 -23
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
- package/src/components/Button/Button.stories.tsx +141 -22
- package/src/components/Button/ButtonGroup.stories.tsx +315 -0
- package/src/components/Button/ButtonGroup.tsx +67 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Callout/Callout.stories.tsx +8 -6
- package/src/components/Card/Card.stories.tsx +82 -28
- package/src/components/Chart/AnimatedChart.tsx +0 -1
- package/src/components/Chart/AreaChart.tsx +0 -1
- package/src/components/Chart/BarChart.tsx +0 -1
- package/src/components/Chart/BubbleChart.tsx +0 -1
- package/src/components/Chart/CandlestickChart.tsx +0 -1
- package/src/components/Chart/Chart.stories.tsx +5 -7
- package/src/components/Chart/Chart.tsx +0 -16
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/DonutChart.tsx +0 -1
- package/src/components/Chart/FunnelChart.tsx +0 -1
- package/src/components/Chart/GaugeChart.tsx +0 -1
- package/src/components/Chart/HeatmapChart.tsx +0 -1
- package/src/components/Chart/LineChart.tsx +0 -1
- package/src/components/Chart/MultiAxisChart.tsx +0 -1
- package/src/components/Chart/PieChart.tsx +0 -1
- package/src/components/Chart/RadarChart.tsx +0 -1
- package/src/components/Chart/ScatterChart.tsx +0 -1
- package/src/components/Chart/WaterfallChart.tsx +0 -1
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
- package/src/components/DataTable/DataTable.stories.tsx +23 -16
- package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
- package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
- package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
- package/src/components/Footer/Footer.stories.tsx +8 -6
- package/src/components/Footer/FooterLink.tsx +9 -2
- package/src/components/Form/Checkbox.stories.tsx +7 -0
- package/src/components/Form/Form.stories.tsx +7 -0
- package/src/components/Form/FormGroup.stories.tsx +9 -1
- package/src/components/Form/Input.stories.tsx +69 -16
- package/src/components/Form/Radio.stories.tsx +9 -1
- package/src/components/Form/Select.stories.tsx +9 -1
- package/src/components/Form/Textarea.stories.tsx +10 -2
- package/src/components/Hero/Hero.stories.tsx +7 -0
- package/src/components/List/List.stories.tsx +7 -0
- package/src/components/Messages/Messages.stories.tsx +8 -7
- package/src/components/Modal/Modal.stories.tsx +17 -6
- package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
- package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +188 -111
- package/src/components/Pagination/Pagination.tsx +83 -3
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
- package/src/components/Popover/Popover.stories.tsx +191 -115
- package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
- package/src/components/Progress/Progress.stories.tsx +79 -49
- package/src/components/Rating/Rating.stories.tsx +109 -84
- package/src/components/River/River.stories.tsx +194 -114
- package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
- package/src/components/Slider/Slider.stories.tsx +7 -0
- package/src/components/Spinner/Spinner.stories.tsx +15 -11
- package/src/components/Steps/Steps.stories.tsx +132 -98
- package/src/components/Tabs/Tabs.stories.tsx +163 -112
- package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
- package/src/components/Todo/Todo.stories.tsx +38 -12
- package/src/components/Toggle/Toggle.stories.tsx +61 -28
- package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
- package/src/components/Upload/Upload.stories.tsx +122 -84
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
- package/src/components/index.ts +1 -0
- package/src/lib/composables/useAtomixGlass.ts +2 -3
- package/src/lib/composables/useNavbar.ts +0 -10
- package/src/lib/config/loader.ts +2 -1
- package/src/lib/constants/components.ts +10 -0
- package/src/lib/hooks/useComponentCustomization.ts +1 -1
- package/src/lib/theme/README.md +174 -0
- package/src/lib/theme/adapters/index.ts +31 -0
- package/src/lib/theme/adapters/themeAdapter.ts +287 -0
- package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
- package/src/lib/theme/config/configLoader.ts +254 -0
- package/src/lib/theme/config/loader.ts +37 -48
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +15 -91
- package/src/lib/theme/{constants.ts → constants/constants.ts} +0 -18
- package/src/lib/theme/constants/index.ts +8 -0
- package/src/lib/theme/core/ThemeRegistry.ts +19 -6
- package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
- package/src/lib/theme/core/composeTheme.ts +155 -0
- package/src/lib/theme/core/createTheme.ts +94 -0
- package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +10 -6
- package/src/lib/theme/core/index.ts +5 -19
- package/src/lib/theme/devtools/Comparator.tsx +346 -22
- package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
- package/src/lib/theme/devtools/Inspector.tsx +335 -51
- package/src/lib/theme/devtools/LiveEditor.tsx +478 -107
- package/src/lib/theme/devtools/Preview.tsx +471 -221
- package/src/lib/theme/{core → devtools}/ThemeValidator.ts +1 -1
- package/src/lib/theme/devtools/index.ts +14 -4
- package/src/lib/theme/devtools/useHistory.ts +130 -0
- package/src/lib/theme/errors/index.ts +12 -0
- package/src/lib/theme/generators/cssFile.ts +79 -0
- package/src/lib/theme/generators/generateCSS.ts +89 -0
- package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +3 -13
- package/src/lib/theme/generators/index.ts +19 -0
- package/src/lib/theme/i18n/rtl.ts +5 -6
- package/src/lib/theme/index.ts +120 -15
- package/src/lib/theme/runtime/ThemeApplicator.ts +52 -111
- package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +1 -1
- package/src/lib/theme/runtime/ThemeProvider.tsx +456 -179
- package/src/lib/theme/runtime/index.ts +1 -2
- package/src/lib/theme/runtime/useTheme.ts +1 -2
- package/src/lib/theme/test/testTheme.ts +385 -0
- package/src/lib/theme/tokens/index.ts +12 -0
- package/src/lib/theme/tokens/tokens.ts +721 -0
- package/src/lib/theme/types.ts +6 -42
- package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
- package/src/lib/theme/utils/index.ts +11 -0
- package/src/lib/theme/utils/injectCSS.ts +90 -0
- package/src/lib/theme/utils/themeHelpers.ts +78 -0
- package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +1 -1
- package/src/lib/theme-tools.ts +7 -8
- package/src/lib/types/components.ts +40 -130
- package/src/lib/utils/componentUtils.ts +1 -1
- package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
- package/src/styles/02-tools/_tools.button.scss +66 -79
- package/src/styles/06-components/_components.atomix-glass.scss +13 -3
- package/src/styles/06-components/_components.pagination.scss +88 -0
- package/scripts/sync-theme-config.js +0 -309
- package/src/lib/theme/composeTheme.ts +0 -370
- package/src/lib/theme/core/ThemeCache.ts +0 -283
- package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
- package/src/lib/theme/core/ThemeEngine.ts +0 -665
- package/src/lib/theme/createThemeFromConfig.ts +0 -132
- package/src/lib/theme/devtools/CLI.ts +0 -364
- package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
- package/src/lib/theme/runtime/ThemeManager.ts +0 -446
- package/src/styles/03-generic/_generated-root.css +0 -26
- package/src/themes/README.md +0 -442
- package/src/themes/themes.config.js +0 -68
- /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
- /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,
|
|
3
|
-
import { fn } from '@storybook/test';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
3
|
import { Pagination } from './Pagination';
|
|
5
|
-
import {
|
|
4
|
+
import { SIZES } from '../../lib/constants/components';
|
|
6
5
|
|
|
7
|
-
|
|
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:
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
//
|
|
61
|
-
const
|
|
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 =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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 =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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 =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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 =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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 =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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 =
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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 =
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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 =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
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
|
-
'
|
|
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
|
|
43
|
+
type Story = StoryObj<typeof meta>;
|
|
39
44
|
|
|
40
45
|
// Sample images with rich metadata
|
|
41
46
|
const sampleImages: ImageType[] = [
|