@shohojdhara/atomix 0.3.15 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-tools/index.d.ts +31 -30
- package/build-tools/package.json +4 -21
- package/dist/atomix.css +20234 -2027
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +76 -2
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/index.d.ts +31 -30
- package/dist/build-tools/package.json +4 -21
- package/dist/charts.js +4 -5
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +87 -10
- package/dist/core.js +673 -480
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +15 -3
- package/dist/forms.js +530 -97
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +5 -6
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +644 -277
- package/dist/index.esm.js +1948 -1347
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3333 -2728
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +2 -2
- package/scripts/atomix-cli.js +10 -1
- package/scripts/cli/__tests__/utils.test.js +6 -2
- package/scripts/cli/migration-tools.js +2 -2
- package/scripts/cli/theme-bridge.js +7 -9
- package/scripts/cli/utils.js +2 -1
- package/src/components/Accordion/Accordion.stories.tsx +72 -23
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +219 -96
- package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/glass-utils.ts +4 -3
- package/src/components/AtomixGlass/shader-utils.ts +128 -52
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
- package/src/components/Avatar/Avatar.stories.tsx +45 -62
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +20 -9
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +14 -4
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
- package/src/components/Breadcrumb/Breadcrumb.tsx +173 -65
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
- package/src/components/Button/Button.stories.tsx +13 -22
- package/src/components/Button/Button.test.tsx +97 -81
- package/src/components/Button/Button.tsx +46 -14
- package/src/components/Button/ButtonGroup.stories.tsx +37 -32
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +166 -918
- package/src/components/Callout/Callout.tsx +196 -84
- package/src/components/Callout/CalloutCompound.test.tsx +72 -0
- package/src/components/Card/Card.stories.tsx +67 -36
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +4 -9
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +7 -7
- package/src/components/DataTable/DataTable.stories.tsx +43 -38
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +425 -298
- package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
- package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
- package/src/components/EdgePanel/EdgePanel.tsx +163 -113
- package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
- package/src/components/Footer/Footer.stories.tsx +21 -16
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.test.tsx +49 -49
- package/src/components/Form/Checkbox.tsx +108 -100
- package/src/components/Form/Form.stories.tsx +2 -10
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +6 -12
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +23 -0
- package/src/components/Form/Select.test.tsx +99 -0
- package/src/components/Form/Select.tsx +239 -186
- package/src/components/Form/SelectOption.tsx +88 -0
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +93 -23
- package/src/components/Hero/Hero.test.tsx +142 -0
- package/src/components/Hero/Hero.tsx +343 -58
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.test.tsx +62 -0
- package/src/components/List/List.tsx +32 -25
- package/src/components/List/ListItem.tsx +20 -0
- package/src/components/Modal/Modal.stories.tsx +67 -2
- package/src/components/Modal/Modal.tsx +208 -125
- package/src/components/Modal/ModalCompound.test.tsx +94 -0
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +99 -192
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +35 -44
- package/src/components/River/River.stories.tsx +2 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +3 -1
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +8 -6
- package/src/components/Steps/Steps.tsx +124 -21
- package/src/components/Steps/StepsCompound.test.tsx +81 -0
- package/src/components/Tabs/Tabs.stories.tsx +12 -9
- package/src/components/Tabs/Tabs.tsx +230 -75
- package/src/components/Tabs/TabsCompound.test.tsx +64 -0
- package/src/components/Toggle/Toggle.stories.tsx +27 -13
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +129 -127
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/__tests__/theme-tools.test.ts +32 -6
- package/src/lib/composables/index.ts +0 -4
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +102 -60
- package/src/lib/composables/useChartExport.ts +1 -1
- package/src/lib/composables/useDataTable.ts +29 -17
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +105 -111
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +180 -73
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
- package/src/lib/utils/__tests__/csv.test.ts +1 -1
- package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +3 -1
- package/src/lib/utils/dataTableExport.ts +1 -5
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +3 -3
- package/src/styles/01-settings/_index.scss +0 -1
- package/src/styles/01-settings/_settings.colors.scss +8 -8
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +1 -1
- package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +36 -24
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +3 -1
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +1 -1
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
- package/src/styles/99-utilities/_utilities.text.scss +67 -47
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React, { useEffect, useState, ReactNode } from 'react';
|
|
1
|
+
import React, { useEffect, useState, ReactNode, forwardRef, Children, cloneElement, isValidElement } from 'react';
|
|
2
2
|
import { STEPS } from '../../lib/constants/components';
|
|
3
3
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
4
4
|
import { AtomixGlassProps } from '../../lib/types/components';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Legacy Item Interface
|
|
7
|
+
export interface StepItemData {
|
|
7
8
|
/**
|
|
8
9
|
* The number for the step
|
|
9
10
|
*/
|
|
@@ -20,11 +21,71 @@ export interface StepItem {
|
|
|
20
21
|
content?: React.ReactNode;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
export type { StepItemData as StepItem };
|
|
25
|
+
|
|
26
|
+
// Compound Component Props
|
|
27
|
+
export interface StepsItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
28
|
+
/**
|
|
29
|
+
* The number or icon for the step
|
|
30
|
+
*/
|
|
31
|
+
number?: number | string | ReactNode;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The text label/title for the step
|
|
35
|
+
*/
|
|
36
|
+
title?: ReactNode;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Whether the step is active
|
|
40
|
+
*/
|
|
41
|
+
active?: boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Whether the step is completed
|
|
45
|
+
*/
|
|
46
|
+
completed?: boolean;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Index of the step (injected by parent)
|
|
50
|
+
*/
|
|
51
|
+
index?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const StepsItem = forwardRef<HTMLDivElement, StepsItemProps>(
|
|
55
|
+
({ children, className = '', number, title, active, completed, index, ...props }, ref) => {
|
|
56
|
+
const itemClasses = [
|
|
57
|
+
'c-steps__item',
|
|
58
|
+
active ? STEPS.CLASSES.ACTIVE : '',
|
|
59
|
+
completed ? STEPS.CLASSES.COMPLETED : '',
|
|
60
|
+
className
|
|
61
|
+
].filter(Boolean).join(' ');
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
ref={ref}
|
|
66
|
+
className={itemClasses}
|
|
67
|
+
aria-current={active ? 'step' : undefined}
|
|
68
|
+
data-index={index}
|
|
69
|
+
{...props}
|
|
70
|
+
>
|
|
71
|
+
<div className="c-steps__line"></div>
|
|
72
|
+
<div className="c-steps__content">
|
|
73
|
+
{(number !== undefined && number !== null) && <div className="c-steps__number">{number}</div>}
|
|
74
|
+
{title && <div className="c-steps__text">{title}</div>}
|
|
75
|
+
{children && <div className="c-steps__custom-content">{children}</div>}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
StepsItem.displayName = 'StepsItem';
|
|
83
|
+
|
|
23
84
|
export interface StepsProps {
|
|
24
85
|
/**
|
|
25
|
-
* Array of step items
|
|
86
|
+
* Array of step items (Legacy)
|
|
26
87
|
*/
|
|
27
|
-
items
|
|
88
|
+
items?: StepItemData[];
|
|
28
89
|
|
|
29
90
|
/**
|
|
30
91
|
* Current active step index (0-based)
|
|
@@ -56,12 +117,22 @@ export interface StepsProps {
|
|
|
56
117
|
* Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
|
|
57
118
|
*/
|
|
58
119
|
glass?: AtomixGlassProps | boolean;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Children (Compound)
|
|
123
|
+
*/
|
|
124
|
+
children?: ReactNode;
|
|
59
125
|
}
|
|
60
126
|
|
|
127
|
+
type StepsComponent = React.FC<StepsProps> & {
|
|
128
|
+
Item: typeof StepsItem;
|
|
129
|
+
Step: typeof StepsItem; // Alias for convenience
|
|
130
|
+
};
|
|
131
|
+
|
|
61
132
|
/**
|
|
62
133
|
* Steps component for displaying a sequence of steps
|
|
63
134
|
*/
|
|
64
|
-
|
|
135
|
+
const StepsComp: React.FC<StepsProps> = ({
|
|
65
136
|
items,
|
|
66
137
|
activeIndex = 0,
|
|
67
138
|
vertical = false,
|
|
@@ -69,6 +140,7 @@ export const Steps: React.FC<StepsProps> = ({
|
|
|
69
140
|
className = '',
|
|
70
141
|
style,
|
|
71
142
|
glass,
|
|
143
|
+
children,
|
|
72
144
|
}) => {
|
|
73
145
|
const [currentStep, setCurrentStep] = useState(activeIndex);
|
|
74
146
|
|
|
@@ -79,10 +151,11 @@ export const Steps: React.FC<StepsProps> = ({
|
|
|
79
151
|
}
|
|
80
152
|
}, [activeIndex]);
|
|
81
153
|
|
|
82
|
-
// Method to go to next step
|
|
154
|
+
// Method to go to next step (Internal helper)
|
|
83
155
|
const goToNextStep = () => {
|
|
84
156
|
const nextIndex = currentStep + 1;
|
|
85
|
-
|
|
157
|
+
const maxIndex = items ? items.length : Children.count(children);
|
|
158
|
+
if (nextIndex < maxIndex) {
|
|
86
159
|
setCurrentStep(nextIndex);
|
|
87
160
|
if (onStepChange) {
|
|
88
161
|
onStepChange(nextIndex);
|
|
@@ -101,6 +174,45 @@ export const Steps: React.FC<StepsProps> = ({
|
|
|
101
174
|
}
|
|
102
175
|
};
|
|
103
176
|
|
|
177
|
+
let content: ReactNode;
|
|
178
|
+
|
|
179
|
+
if (items && items.length > 0) {
|
|
180
|
+
// Legacy rendering
|
|
181
|
+
content = items.map((item, index) => (
|
|
182
|
+
<StepsItem
|
|
183
|
+
key={`step-${index}`}
|
|
184
|
+
index={index}
|
|
185
|
+
number={item.number}
|
|
186
|
+
title={item.text}
|
|
187
|
+
active={index <= currentStep}
|
|
188
|
+
completed={index < currentStep}
|
|
189
|
+
>
|
|
190
|
+
{item.content}
|
|
191
|
+
</StepsItem>
|
|
192
|
+
));
|
|
193
|
+
} else {
|
|
194
|
+
// Compound rendering
|
|
195
|
+
content = Children.map(children, (child, index) => {
|
|
196
|
+
if (isValidElement(child)) {
|
|
197
|
+
const childProps = child.props as any;
|
|
198
|
+
// Inject active/completed based on index if not explicitly provided
|
|
199
|
+
const isActive = childProps.active ?? index <= currentStep;
|
|
200
|
+
const isCompleted = childProps.completed ?? index < currentStep;
|
|
201
|
+
|
|
202
|
+
// If number is not provided, default to index + 1
|
|
203
|
+
const number = childProps.number ?? (index + 1);
|
|
204
|
+
|
|
205
|
+
return cloneElement(child, {
|
|
206
|
+
index,
|
|
207
|
+
active: isActive,
|
|
208
|
+
completed: isCompleted,
|
|
209
|
+
number,
|
|
210
|
+
} as any);
|
|
211
|
+
}
|
|
212
|
+
return child;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
104
216
|
const stepsContent = (
|
|
105
217
|
<div
|
|
106
218
|
className={`c-steps ${vertical ? STEPS.CLASSES.VERTICAL : ''} ${className}`}
|
|
@@ -108,20 +220,7 @@ export const Steps: React.FC<StepsProps> = ({
|
|
|
108
220
|
role="navigation"
|
|
109
221
|
aria-label="Steps"
|
|
110
222
|
>
|
|
111
|
-
{
|
|
112
|
-
<div
|
|
113
|
-
key={`step-${index}`}
|
|
114
|
-
className={`c-steps__item ${index <= currentStep ? STEPS.CLASSES.ACTIVE : ''} ${index < currentStep ? STEPS.CLASSES.COMPLETED : ''}`}
|
|
115
|
-
aria-current={index === currentStep ? 'step' : undefined}
|
|
116
|
-
>
|
|
117
|
-
<div className="c-steps__line"></div>
|
|
118
|
-
<div className="c-steps__content">
|
|
119
|
-
<div className="c-steps__number">{item.number}</div>
|
|
120
|
-
<div className="c-steps__text">{item.text}</div>
|
|
121
|
-
{item.content && <div className="c-steps__custom-content">{item.content}</div>}
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
))}
|
|
223
|
+
{content}
|
|
125
224
|
</div>
|
|
126
225
|
);
|
|
127
226
|
|
|
@@ -144,6 +243,10 @@ export const Steps: React.FC<StepsProps> = ({
|
|
|
144
243
|
return stepsContent;
|
|
145
244
|
};
|
|
146
245
|
|
|
246
|
+
export const Steps = StepsComp as StepsComponent;
|
|
247
|
+
|
|
147
248
|
Steps.displayName = 'Steps';
|
|
249
|
+
Steps.Item = StepsItem;
|
|
250
|
+
Steps.Step = StepsItem;
|
|
148
251
|
|
|
149
252
|
export default Steps;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { Steps } from './Steps';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
describe('Steps Component', () => {
|
|
7
|
+
it('renders correctly with legacy items prop', () => {
|
|
8
|
+
const items = [
|
|
9
|
+
{ number: 1, text: 'Step 1' },
|
|
10
|
+
{ number: 2, text: 'Step 2' },
|
|
11
|
+
{ number: 3, text: 'Step 3' },
|
|
12
|
+
];
|
|
13
|
+
render(<Steps items={items} activeIndex={1} />);
|
|
14
|
+
|
|
15
|
+
// Step 1: active (<= 1) and completed (< 1)
|
|
16
|
+
const step1 = screen.getByText('Step 1').closest('.c-steps__item');
|
|
17
|
+
expect(step1).toHaveClass('is-active');
|
|
18
|
+
expect(step1).toHaveClass('is-completed');
|
|
19
|
+
|
|
20
|
+
// Step 2: active (<= 1) and NOT completed (>= 1)
|
|
21
|
+
const step2 = screen.getByText('Step 2').closest('.c-steps__item');
|
|
22
|
+
expect(step2).toHaveClass('is-active');
|
|
23
|
+
expect(step2).not.toHaveClass('is-completed');
|
|
24
|
+
|
|
25
|
+
// Step 3: NOT active (> 1)
|
|
26
|
+
const step3 = screen.getByText('Step 3').closest('.c-steps__item');
|
|
27
|
+
expect(step3).not.toHaveClass('is-active');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders correctly with compound components', () => {
|
|
31
|
+
render(
|
|
32
|
+
<Steps activeIndex={1}>
|
|
33
|
+
<Steps.Item title="Step 1">Content 1</Steps.Item>
|
|
34
|
+
<Steps.Item title="Step 2">Content 2</Steps.Item>
|
|
35
|
+
<Steps.Item title="Step 3">Content 3</Steps.Item>
|
|
36
|
+
</Steps>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Verify titles
|
|
40
|
+
expect(screen.getByText('Step 1')).toBeInTheDocument();
|
|
41
|
+
expect(screen.getByText('Step 2')).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByText('Step 3')).toBeInTheDocument();
|
|
43
|
+
|
|
44
|
+
// Verify content
|
|
45
|
+
expect(screen.getByText('Content 1')).toBeInTheDocument();
|
|
46
|
+
|
|
47
|
+
// Step 1: active and completed (inferred from activeIndex 1)
|
|
48
|
+
const step1 = screen.getByText('Step 1').closest('.c-steps__item');
|
|
49
|
+
expect(step1).toHaveClass('is-active');
|
|
50
|
+
expect(step1).toHaveClass('is-completed');
|
|
51
|
+
|
|
52
|
+
// Step 2: active and NOT completed
|
|
53
|
+
const step2 = screen.getByText('Step 2').closest('.c-steps__item');
|
|
54
|
+
expect(step2).toHaveClass('is-active');
|
|
55
|
+
expect(step2).not.toHaveClass('is-completed');
|
|
56
|
+
|
|
57
|
+
// Step 3: NOT active
|
|
58
|
+
const step3 = screen.getByText('Step 3').closest('.c-steps__item');
|
|
59
|
+
expect(step3).not.toHaveClass('is-active');
|
|
60
|
+
|
|
61
|
+
// Verify automatic numbering
|
|
62
|
+
expect(step1?.querySelector('.c-steps__number')).toHaveTextContent('1');
|
|
63
|
+
expect(step2?.querySelector('.c-steps__number')).toHaveTextContent('2');
|
|
64
|
+
expect(step3?.querySelector('.c-steps__number')).toHaveTextContent('3');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('supports explicit props on Steps.Item', () => {
|
|
68
|
+
render(
|
|
69
|
+
<Steps>
|
|
70
|
+
<Steps.Item title="Custom Step" number="A" active completed>
|
|
71
|
+
Custom Content
|
|
72
|
+
</Steps.Item>
|
|
73
|
+
</Steps>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const step = screen.getByText('Custom Step').closest('.c-steps__item');
|
|
77
|
+
expect(step).toHaveClass('is-active');
|
|
78
|
+
expect(step).toHaveClass('is-completed');
|
|
79
|
+
expect(step?.querySelector('.c-steps__number')).toHaveTextContent('A');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -180,13 +180,15 @@ export const WithDifferentActiveTab: Story = {
|
|
|
180
180
|
|
|
181
181
|
export const WithGlassEffect: Story = {
|
|
182
182
|
render: args => (
|
|
183
|
-
<div
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
<div
|
|
184
|
+
style={{
|
|
185
|
+
maxWidth: '600px',
|
|
186
|
+
margin: '0 auto',
|
|
187
|
+
padding: '30px',
|
|
188
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
189
|
+
minHeight: '300px',
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
190
192
|
<Tabs {...args} />
|
|
191
193
|
</div>
|
|
192
194
|
),
|
|
@@ -224,7 +226,8 @@ export const WithRichContent: Story = {
|
|
|
224
226
|
parameters: {
|
|
225
227
|
docs: {
|
|
226
228
|
description: {
|
|
227
|
-
story:
|
|
229
|
+
story:
|
|
230
|
+
'Demonstrates tabs containing rich HTML content including headings, lists, and tables, showing the flexibility of the tabs component.',
|
|
228
231
|
},
|
|
229
232
|
},
|
|
230
233
|
},
|
|
@@ -392,4 +395,4 @@ export const GlassCustom: Story = {
|
|
|
392
395
|
</div>
|
|
393
396
|
</div>
|
|
394
397
|
),
|
|
395
|
-
};
|
|
398
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, ReactNode, memo } from 'react';
|
|
1
|
+
import React, { useState, ReactNode, memo, createContext, useContext, forwardRef } from 'react';
|
|
2
2
|
import { TAB } from '../../lib/constants/components';
|
|
3
3
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
4
4
|
import { AtomixGlassProps } from '../../lib/types/components';
|
|
@@ -27,9 +27,9 @@ export interface TabsItemProps {
|
|
|
27
27
|
|
|
28
28
|
export interface TabsProps {
|
|
29
29
|
/**
|
|
30
|
-
* Array of tab items
|
|
30
|
+
* Array of tab items (Legacy mode)
|
|
31
31
|
*/
|
|
32
|
-
items
|
|
32
|
+
items?: TabsItemProps[];
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Initial active tab index
|
|
@@ -56,89 +56,244 @@ export interface TabsProps {
|
|
|
56
56
|
* Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
|
|
57
57
|
*/
|
|
58
58
|
glass?: AtomixGlassProps | boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Children (Compound mode)
|
|
62
|
+
*/
|
|
63
|
+
children?: ReactNode;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Context for compound usage
|
|
67
|
+
const TabsContext = createContext<{
|
|
68
|
+
currentTab: number;
|
|
69
|
+
handleTabClick: (index: number) => void;
|
|
70
|
+
}>({
|
|
71
|
+
currentTab: 0,
|
|
72
|
+
handleTabClick: () => {},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Compound components
|
|
76
|
+
export const TabsList = forwardRef<HTMLUListElement, React.HTMLAttributes<HTMLUListElement>>(
|
|
77
|
+
({ children, className = '', ...props }, ref) => {
|
|
78
|
+
return (
|
|
79
|
+
<ul ref={ref} className={`c-tabs__nav ${className}`.trim()} {...props}>
|
|
80
|
+
{React.Children.map(children, (child, index) => {
|
|
81
|
+
if (React.isValidElement(child)) {
|
|
82
|
+
// Inject index into TabsTrigger
|
|
83
|
+
return React.cloneElement(child, { index } as any);
|
|
84
|
+
}
|
|
85
|
+
return child;
|
|
86
|
+
})}
|
|
87
|
+
</ul>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
TabsList.displayName = 'TabsList';
|
|
92
|
+
|
|
93
|
+
export interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
94
|
+
index?: number; // Injected by TabsList or passed explicitly
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(
|
|
98
|
+
({ children, className = '', index, onClick, ...props }, ref) => {
|
|
99
|
+
const { currentTab, handleTabClick } = useContext(TabsContext);
|
|
100
|
+
|
|
101
|
+
// Safety check if used outside context or without index
|
|
102
|
+
if (index === undefined) {
|
|
103
|
+
console.warn('TabsTrigger requires an index prop or must be a direct child of TabsList');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const isActive = index !== undefined && currentTab === index;
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<li className="c-tabs__nav-item">
|
|
110
|
+
<button
|
|
111
|
+
ref={ref}
|
|
112
|
+
className={`c-tabs__nav-btn ${isActive ? TAB.CLASSES.ACTIVE : ''} ${className}`.trim()}
|
|
113
|
+
onClick={(e) => {
|
|
114
|
+
if (index !== undefined) handleTabClick(index);
|
|
115
|
+
onClick?.(e);
|
|
116
|
+
}}
|
|
117
|
+
data-tabindex={index}
|
|
118
|
+
role="tab"
|
|
119
|
+
aria-selected={isActive}
|
|
120
|
+
aria-controls={`tab-panel-${index}`}
|
|
121
|
+
type="button"
|
|
122
|
+
{...props}
|
|
123
|
+
>
|
|
124
|
+
{children}
|
|
125
|
+
</button>
|
|
126
|
+
</li>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
TabsTrigger.displayName = 'TabsTrigger';
|
|
131
|
+
|
|
132
|
+
export const TabsPanels = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
133
|
+
({ children, className = '', ...props }, ref) => {
|
|
134
|
+
return (
|
|
135
|
+
<div ref={ref} className={`c-tabs__panels ${className}`.trim()} {...props}>
|
|
136
|
+
{React.Children.map(children, (child, index) => {
|
|
137
|
+
if (React.isValidElement(child)) {
|
|
138
|
+
return React.cloneElement(child, { index } as any);
|
|
139
|
+
}
|
|
140
|
+
return child;
|
|
141
|
+
})}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
TabsPanels.displayName = 'TabsPanels';
|
|
147
|
+
|
|
148
|
+
export interface TabsPanelProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
149
|
+
index?: number;
|
|
59
150
|
}
|
|
60
151
|
|
|
152
|
+
export const TabsPanel = forwardRef<HTMLDivElement, TabsPanelProps>(
|
|
153
|
+
({ children, className = '', index, style, ...props }, ref) => {
|
|
154
|
+
const { currentTab } = useContext(TabsContext);
|
|
155
|
+
const isActive = index !== undefined && currentTab === index;
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div
|
|
159
|
+
ref={ref}
|
|
160
|
+
className={`c-tabs__panel ${isActive ? TAB.CLASSES.ACTIVE : ''} ${className}`.trim()}
|
|
161
|
+
data-tabindex={index}
|
|
162
|
+
id={`tab-panel-${index}`}
|
|
163
|
+
role="tabpanel"
|
|
164
|
+
aria-labelledby={`tab-nav-${index}`}
|
|
165
|
+
style={{
|
|
166
|
+
height: isActive ? 'auto' : '0px',
|
|
167
|
+
opacity: isActive ? 1 : 0,
|
|
168
|
+
overflow: 'hidden',
|
|
169
|
+
transition: 'height 0.3s ease, opacity 0.3s ease',
|
|
170
|
+
...style,
|
|
171
|
+
}}
|
|
172
|
+
{...props}
|
|
173
|
+
>
|
|
174
|
+
<div className="c-tabs__panel-body">{children}</div>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
TabsPanel.displayName = 'TabsPanel';
|
|
180
|
+
|
|
181
|
+
|
|
61
182
|
/**
|
|
62
183
|
* Tabs component for switching between different content panels
|
|
63
184
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
>
|
|
116
|
-
|
|
185
|
+
type TabsComponent = React.FC<TabsProps> & {
|
|
186
|
+
List: typeof TabsList;
|
|
187
|
+
Trigger: typeof TabsTrigger;
|
|
188
|
+
Panels: typeof TabsPanels;
|
|
189
|
+
Panel: typeof TabsPanel;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export const Tabs: TabsComponent = memo(
|
|
193
|
+
({
|
|
194
|
+
items,
|
|
195
|
+
activeIndex = TAB.DEFAULTS.ACTIVE_INDEX,
|
|
196
|
+
onTabChange,
|
|
197
|
+
className = '',
|
|
198
|
+
style,
|
|
199
|
+
glass,
|
|
200
|
+
children,
|
|
201
|
+
}: TabsProps) => {
|
|
202
|
+
const [currentTab, setCurrentTab] = useState(activeIndex);
|
|
203
|
+
|
|
204
|
+
// Handle tab change
|
|
205
|
+
const handleTabClick = (index: number) => {
|
|
206
|
+
setCurrentTab(index);
|
|
207
|
+
if (onTabChange) {
|
|
208
|
+
onTabChange(index);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Determine content based on mode (legacy items vs compound children)
|
|
213
|
+
let content: ReactNode;
|
|
214
|
+
|
|
215
|
+
// Use items prop if provided
|
|
216
|
+
if (items && items.length > 0) {
|
|
217
|
+
// Legacy mode
|
|
218
|
+
content = (
|
|
219
|
+
<>
|
|
220
|
+
<ul className="c-tabs__nav">
|
|
221
|
+
{items.map((item, index) => (
|
|
222
|
+
<li className="c-tabs__nav-item" key={`tab-nav-${index}`}>
|
|
223
|
+
<button
|
|
224
|
+
className={`c-tabs__nav-btn ${index === currentTab ? TAB.CLASSES.ACTIVE : ''}`}
|
|
225
|
+
onClick={() => handleTabClick(index)}
|
|
226
|
+
data-tabindex={index}
|
|
227
|
+
role="tab"
|
|
228
|
+
aria-selected={index === currentTab}
|
|
229
|
+
aria-controls={`tab-panel-${index}`}
|
|
230
|
+
>
|
|
231
|
+
{item.label}
|
|
232
|
+
</button>
|
|
233
|
+
</li>
|
|
234
|
+
))}
|
|
235
|
+
</ul>
|
|
236
|
+
<div className="c-tabs__panels">
|
|
237
|
+
{items.map((item, index) => (
|
|
238
|
+
<div
|
|
239
|
+
className={`c-tabs__panel ${index === currentTab ? TAB.CLASSES.ACTIVE : ''}`}
|
|
240
|
+
key={`tab-panel-${index}`}
|
|
241
|
+
data-tabindex={index}
|
|
242
|
+
id={`tab-panel-${index}`}
|
|
243
|
+
role="tabpanel"
|
|
244
|
+
aria-labelledby={`tab-nav-${index}`}
|
|
245
|
+
style={{
|
|
246
|
+
height: index === currentTab ? 'auto' : '0px',
|
|
247
|
+
opacity: index === currentTab ? 1 : 0,
|
|
248
|
+
overflow: 'hidden',
|
|
249
|
+
transition: 'height 0.3s ease, opacity 0.3s ease',
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<div className="c-tabs__panel-body">{item.content}</div>
|
|
253
|
+
</div>
|
|
254
|
+
))}
|
|
117
255
|
</div>
|
|
118
|
-
|
|
256
|
+
</>
|
|
257
|
+
);
|
|
258
|
+
} else {
|
|
259
|
+
// Compound mode
|
|
260
|
+
content = (
|
|
261
|
+
<TabsContext.Provider value={{ currentTab, handleTabClick }}>
|
|
262
|
+
{children}
|
|
263
|
+
</TabsContext.Provider>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const wrapper = (
|
|
268
|
+
<div className={`c-tabs js-atomix-tab ${className}`} style={style}>
|
|
269
|
+
{content}
|
|
119
270
|
</div>
|
|
120
|
-
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
if (glass) {
|
|
124
|
-
// Default glass settings for tabs
|
|
125
|
-
const defaultGlassProps = {
|
|
126
|
-
displacementScale: 60,
|
|
127
|
-
blurAmount: 1,
|
|
128
|
-
saturation: 160,
|
|
129
|
-
aberrationIntensity: 0.5,
|
|
130
|
-
cornerRadius: 8,
|
|
131
|
-
mode: 'shader' as const,
|
|
132
|
-
};
|
|
271
|
+
);
|
|
133
272
|
|
|
134
|
-
|
|
273
|
+
if (glass) {
|
|
274
|
+
// Default glass settings for tabs
|
|
275
|
+
const defaultGlassProps = {
|
|
276
|
+
displacementScale: 60,
|
|
277
|
+
blurAmount: 1,
|
|
278
|
+
saturation: 160,
|
|
279
|
+
aberrationIntensity: 0.5,
|
|
280
|
+
cornerRadius: 8,
|
|
281
|
+
mode: 'shader' as const,
|
|
282
|
+
};
|
|
135
283
|
|
|
136
|
-
|
|
137
|
-
}
|
|
284
|
+
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
138
285
|
|
|
139
|
-
|
|
140
|
-
}
|
|
286
|
+
return <AtomixGlass {...glassProps}>{wrapper}</AtomixGlass>;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return wrapper;
|
|
290
|
+
}
|
|
291
|
+
) as unknown as TabsComponent;
|
|
141
292
|
|
|
142
293
|
Tabs.displayName = 'Tabs';
|
|
294
|
+
Tabs.List = TabsList;
|
|
295
|
+
Tabs.Trigger = TabsTrigger;
|
|
296
|
+
Tabs.Panels = TabsPanels;
|
|
297
|
+
Tabs.Panel = TabsPanel;
|
|
143
298
|
|
|
144
299
|
export default Tabs;
|