@shohojdhara/atomix 0.4.1 → 0.4.3
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/dist/atomix.css +9351 -9259
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +12 -19
- package/dist/charts.js +555 -358
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +21 -24
- package/dist/core.js +435 -265
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +11 -18
- package/dist/forms.js +411 -257
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +14 -21
- package/dist/heavy.js +409 -254
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +38 -41
- package/dist/index.esm.js +731 -487
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +733 -492
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/scripts/atomix-cli.js +34 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
- package/src/components/AtomixGlass/README.md +5 -5
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
- package/src/components/Badge/Badge.stories.tsx +1 -1
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Breadcrumb/Breadcrumb.tsx +90 -77
- package/src/components/Breadcrumb/index.ts +2 -2
- package/src/components/Button/Button.stories.tsx +1 -1
- package/src/components/Button/Button.tsx +2 -1
- package/src/components/Button/README.md +2 -2
- package/src/components/Callout/Callout.test.tsx +3 -3
- package/src/components/Callout/Callout.tsx +2 -2
- package/src/components/Callout/README.md +2 -2
- package/src/components/Card/Card.tsx +31 -11
- package/src/components/Chart/Chart.stories.tsx +1 -1
- package/src/components/Chart/Chart.tsx +5 -5
- package/src/components/Chart/TreemapChart.tsx +37 -29
- package/src/components/DatePicker/readme.md +3 -3
- package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +276 -273
- package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +1 -1
- package/src/components/Form/Checkbox.tsx +1 -1
- package/src/components/Form/Input.stories.tsx +1 -1
- package/src/components/Form/Input.tsx +1 -1
- package/src/components/Form/Radio.stories.tsx +1 -1
- package/src/components/Form/Radio.tsx +1 -1
- package/src/components/Form/Select.stories.tsx +1 -1
- package/src/components/Form/Select.tsx +1 -1
- package/src/components/Form/Textarea.stories.tsx +1 -1
- package/src/components/Form/Textarea.tsx +1 -1
- package/src/components/Hero/Hero.stories.tsx +2 -2
- package/src/components/Hero/Hero.tsx +2 -2
- package/src/components/Messages/Messages.stories.tsx +1 -1
- package/src/components/Messages/Messages.tsx +2 -2
- package/src/components/Modal/Modal.stories.tsx +1 -1
- package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
- package/src/components/Navigation/Nav/Nav.tsx +1 -1
- package/src/components/Navigation/Nav/NavItem.tsx +6 -3
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +1 -1
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/Popover/Popover.stories.tsx +1 -1
- package/src/components/Popover/Popover.tsx +1 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Rating/Rating.stories.tsx +1 -1
- package/src/components/Rating/Rating.test.tsx +73 -0
- package/src/components/Rating/Rating.tsx +25 -37
- package/src/components/Spinner/Spinner.tsx +1 -1
- package/src/components/Steps/Steps.stories.tsx +1 -1
- package/src/components/Steps/Steps.tsx +2 -2
- package/src/components/Tabs/Tabs.stories.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Todo/Todo.tsx +0 -1
- package/src/components/Toggle/Toggle.stories.tsx +1 -1
- package/src/components/Toggle/Toggle.tsx +1 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
- package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
- package/src/lib/composables/__tests__/useChart.test.ts +50 -0
- package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
- package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
- package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
- package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
- package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
- package/src/lib/composables/glass-styles.ts +302 -0
- package/src/lib/composables/index.ts +0 -4
- package/src/lib/composables/useAtomixGlass.ts +331 -522
- package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
- package/src/lib/composables/useBarChart.ts +1 -1
- package/src/lib/composables/useBreadcrumb.ts +6 -6
- package/src/lib/composables/useChart.ts +104 -21
- package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
- package/src/lib/composables/useSlider.ts +66 -34
- package/src/lib/theme/devtools/CLI.ts +1 -1
- package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
- package/src/lib/types/components.ts +18 -21
- package/src/lib/utils/__tests__/dom.test.ts +100 -0
- package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
- package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.utility-api.scss +6 -6
- package/src/styles/06-components/_components.accordion.scss +0 -2
- package/src/styles/06-components/_components.chart.scss +0 -1
- package/src/styles/06-components/_components.dropdown.scss +0 -1
- package/src/styles/06-components/_components.edge-panel.scss +0 -2
- package/src/styles/06-components/_components.photoviewer.scss +0 -1
- package/src/styles/06-components/_components.river.scss +0 -1
- package/src/styles/06-components/_components.slider.scss +0 -3
- package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
- package/src/styles/99-utilities/_utilities.text.scss +1 -0
|
@@ -627,7 +627,7 @@ export const GlassCustom: Story = {
|
|
|
627
627
|
displacementScale: 70,
|
|
628
628
|
blurAmount: 1.8,
|
|
629
629
|
saturation: 170,
|
|
630
|
-
|
|
630
|
+
borderRadius: 0,
|
|
631
631
|
} as any
|
|
632
632
|
}
|
|
633
633
|
>
|
|
@@ -693,7 +693,7 @@ export const GlassPremium: Story = {
|
|
|
693
693
|
displacementScale: 180,
|
|
694
694
|
blurAmount: 1,
|
|
695
695
|
saturation: 60,
|
|
696
|
-
|
|
696
|
+
borderRadius: 0,
|
|
697
697
|
} as any
|
|
698
698
|
}
|
|
699
699
|
>
|
|
@@ -786,7 +786,7 @@ export const GlassShowcase: Story = {
|
|
|
786
786
|
displacementScale: 25,
|
|
787
787
|
blurAmount: 1.2,
|
|
788
788
|
saturation: 140,
|
|
789
|
-
|
|
789
|
+
borderRadius: 0,
|
|
790
790
|
} as any
|
|
791
791
|
}
|
|
792
792
|
>
|
|
@@ -815,7 +815,7 @@ export const GlassShowcase: Story = {
|
|
|
815
815
|
displacementScale: 35,
|
|
816
816
|
blurAmount: 1.5,
|
|
817
817
|
saturation: 160,
|
|
818
|
-
|
|
818
|
+
borderRadius: 0,
|
|
819
819
|
} as any
|
|
820
820
|
}
|
|
821
821
|
>
|
|
@@ -844,7 +844,7 @@ export const GlassShowcase: Story = {
|
|
|
844
844
|
displacementScale: 50,
|
|
845
845
|
blurAmount: 2,
|
|
846
846
|
saturation: 180,
|
|
847
|
-
|
|
847
|
+
borderRadius: 0,
|
|
848
848
|
} as any
|
|
849
849
|
}
|
|
850
850
|
>
|
|
@@ -874,7 +874,7 @@ export const GlassShowcase: Story = {
|
|
|
874
874
|
displacementScale: 70,
|
|
875
875
|
blurAmount: 1.8,
|
|
876
876
|
saturation: 170,
|
|
877
|
-
|
|
877
|
+
borderRadius: 0,
|
|
878
878
|
} as any
|
|
879
879
|
}
|
|
880
880
|
>
|
|
@@ -907,7 +907,7 @@ export const GlassShowcase: Story = {
|
|
|
907
907
|
displacementScale: 180,
|
|
908
908
|
blurAmount: 1,
|
|
909
909
|
saturation: 60,
|
|
910
|
-
|
|
910
|
+
borderRadius: 0,
|
|
911
911
|
} as any
|
|
912
912
|
}
|
|
913
913
|
>
|
|
@@ -49,10 +49,10 @@ export const FooterLink = forwardRef<HTMLAnchorElement, FooterLinkProps>(
|
|
|
49
49
|
|
|
50
50
|
if (LinkComponent) {
|
|
51
51
|
const Component = LinkComponent as React.ComponentType<any>;
|
|
52
|
-
// Only pass href if the link is not disabled and href exists
|
|
52
|
+
// Only pass href/to if the link is not disabled and href exists
|
|
53
53
|
const componentProps = {
|
|
54
54
|
ref,
|
|
55
|
-
...(href && !disabled ? { to: href } : {}),
|
|
55
|
+
...(href && !disabled ? { href, to: href } : {}),
|
|
56
56
|
...linkProps,
|
|
57
57
|
};
|
|
58
58
|
|
|
@@ -117,7 +117,7 @@ export const Checkbox = React.memo(
|
|
|
117
117
|
blurAmount: 1,
|
|
118
118
|
saturation: 160,
|
|
119
119
|
aberrationIntensity: 0.3,
|
|
120
|
-
|
|
120
|
+
borderRadius: 6,
|
|
121
121
|
mode: 'shader' as const,
|
|
122
122
|
};
|
|
123
123
|
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
@@ -433,7 +433,7 @@ export const WithCustomGlassEffect: Story = {
|
|
|
433
433
|
blurAmount: -0.1,
|
|
434
434
|
saturation: 130,
|
|
435
435
|
aberrationIntensity: 0,
|
|
436
|
-
|
|
436
|
+
borderRadius: 45,
|
|
437
437
|
mode: 'standard',
|
|
438
438
|
elasticity: 0.2,
|
|
439
439
|
onClick: () => {
|
|
@@ -911,7 +911,7 @@ export const PremiumShowcase: Story = {
|
|
|
911
911
|
blurAmount: 2,
|
|
912
912
|
saturation: 150,
|
|
913
913
|
aberrationIntensity: 0.5,
|
|
914
|
-
|
|
914
|
+
borderRadius: 20,
|
|
915
915
|
overLight: true,
|
|
916
916
|
mode: 'standard',
|
|
917
917
|
},
|
|
@@ -55,7 +55,7 @@ const HeroContent = ({ children, className, style, glass, ...props }: HeroConten
|
|
|
55
55
|
blurAmount: 3,
|
|
56
56
|
saturation: 180,
|
|
57
57
|
aberrationIntensity: 0,
|
|
58
|
-
|
|
58
|
+
borderRadius: 8,
|
|
59
59
|
overLight: false,
|
|
60
60
|
mode: 'standard' as const,
|
|
61
61
|
} : glass;
|
|
@@ -389,7 +389,7 @@ export const Hero: React.FC<HeroProps> & {
|
|
|
389
389
|
blurAmount={3}
|
|
390
390
|
saturation={180}
|
|
391
391
|
aberrationIntensity={0}
|
|
392
|
-
|
|
392
|
+
borderRadius={8}
|
|
393
393
|
overLight={false}
|
|
394
394
|
mode="standard"
|
|
395
395
|
>
|
|
@@ -35,7 +35,7 @@ export const Messages: React.FC<MessagesProps> = ({
|
|
|
35
35
|
// Default glass settings for messages
|
|
36
36
|
const defaultGlassProps = {
|
|
37
37
|
displacementScale: 150,
|
|
38
|
-
|
|
38
|
+
borderRadius: 12,
|
|
39
39
|
elasticity: 0,
|
|
40
40
|
aberrationIntensity: 2,
|
|
41
41
|
};
|
|
@@ -185,7 +185,7 @@ export const Messages: React.FC<MessagesProps> = ({
|
|
|
185
185
|
<AtomixGlass {...glassProps}>
|
|
186
186
|
<div
|
|
187
187
|
className="c-messages__glass-content"
|
|
188
|
-
style={{ borderRadius: glassProps.
|
|
188
|
+
style={{ borderRadius: glassProps.borderRadius }}
|
|
189
189
|
>
|
|
190
190
|
{messagesContent}
|
|
191
191
|
</div>
|
|
@@ -645,7 +645,7 @@ export const GlassCustom: Story = {
|
|
|
645
645
|
glass={{
|
|
646
646
|
displacementScale: 80,
|
|
647
647
|
blurAmount: 2.5,
|
|
648
|
-
|
|
648
|
+
borderRadius: 20,
|
|
649
649
|
mode: 'shader',
|
|
650
650
|
}}
|
|
651
651
|
>
|
|
@@ -799,7 +799,7 @@ export const GlassThemeShowcase: Story = {
|
|
|
799
799
|
glass={{
|
|
800
800
|
displacementScale: 60,
|
|
801
801
|
blurAmount: 2,
|
|
802
|
-
|
|
802
|
+
borderRadius: 16,
|
|
803
803
|
mode: 'shader',
|
|
804
804
|
}}
|
|
805
805
|
>
|
|
@@ -51,7 +51,7 @@ export const Nav = forwardRef<HTMLUListElement, NavProps>(
|
|
|
51
51
|
const defaultGlassProps = {
|
|
52
52
|
displacementScale: 60,
|
|
53
53
|
blurAmount: 1.5,
|
|
54
|
-
|
|
54
|
+
borderRadius: 8,
|
|
55
55
|
mode: 'shader' as const,
|
|
56
56
|
};
|
|
57
57
|
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef, ReactNode, forwardRef } from 'react';
|
|
2
2
|
import { NavItemProps } from '../../../lib/types/components';
|
|
3
3
|
import { useNavItem } from '../../../lib/composables/useNavbar';
|
|
4
|
+
import useForkRef from '../../../lib/utils/useForkRef';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
|
|
@@ -57,7 +58,8 @@ export const NavItem = forwardRef<HTMLLIElement, NavItemProps>(
|
|
|
57
58
|
const [isActive, setIsActive] = useState(false);
|
|
58
59
|
|
|
59
60
|
// Ref for detecting outside clicks
|
|
60
|
-
const itemRef = useRef<
|
|
61
|
+
const itemRef = useRef<any>(null);
|
|
62
|
+
const combinedRef = useForkRef(ref as any, itemRef);
|
|
61
63
|
|
|
62
64
|
// Toggle dropdown
|
|
63
65
|
const handleDropdownToggle = (e: React.MouseEvent) => {
|
|
@@ -134,8 +136,9 @@ export const NavItem = forwardRef<HTMLLIElement, NavItemProps>(
|
|
|
134
136
|
const expanded = typeof ariaExpanded !== 'undefined' ? ariaExpanded : isActive;
|
|
135
137
|
|
|
136
138
|
const linkProps = {
|
|
137
|
-
ref:
|
|
139
|
+
ref: combinedRef,
|
|
138
140
|
href: href || '#',
|
|
141
|
+
to: href || '#',
|
|
139
142
|
className: navLinkClass,
|
|
140
143
|
onClick: dropdown || megaMenu ? handleDropdownToggle : handleClick(onClick),
|
|
141
144
|
'aria-disabled': disabled,
|
|
@@ -146,7 +149,7 @@ export const NavItem = forwardRef<HTMLLIElement, NavItemProps>(
|
|
|
146
149
|
};
|
|
147
150
|
|
|
148
151
|
return (
|
|
149
|
-
<li
|
|
152
|
+
<li className={navItemClass} role="menuitem" aria-haspopup={dropdown || megaMenu}>
|
|
150
153
|
{LinkComponent ? (
|
|
151
154
|
(() => {
|
|
152
155
|
const Component = LinkComponent as React.ComponentType<any>;
|
|
@@ -715,7 +715,7 @@ export const GlassCustom: Story = {
|
|
|
715
715
|
glass={{
|
|
716
716
|
displacementScale: 100,
|
|
717
717
|
blurAmount: 2.5,
|
|
718
|
-
|
|
718
|
+
borderRadius: 0,
|
|
719
719
|
mode: 'shader',
|
|
720
720
|
}}
|
|
721
721
|
>
|
|
@@ -773,7 +773,7 @@ export const GlassCustom: Story = {
|
|
|
773
773
|
docs: {
|
|
774
774
|
description: {
|
|
775
775
|
story:
|
|
776
|
-
'Customized glass effect with increased displacement and blur for a more pronounced visual impact. The sharp corners (
|
|
776
|
+
'Customized glass effect with increased displacement and blur for a more pronounced visual impact. The sharp corners (borderRadius: 0) create a modern, edge-to-edge aesthetic.',
|
|
777
777
|
},
|
|
778
778
|
},
|
|
779
779
|
},
|
|
@@ -942,7 +942,7 @@ export const GlassThemeShowcase: Story = {
|
|
|
942
942
|
glass={{
|
|
943
943
|
displacementScale: 60,
|
|
944
944
|
blurAmount: 2,
|
|
945
|
-
|
|
945
|
+
borderRadius: 0,
|
|
946
946
|
mode: 'shader',
|
|
947
947
|
}}
|
|
948
948
|
>
|
|
@@ -146,7 +146,7 @@ export const Navbar = forwardRef<HTMLElement, NavbarProps>(
|
|
|
146
146
|
const defaultGlassProps = {
|
|
147
147
|
displacementScale: 30,
|
|
148
148
|
blurAmount: 2,
|
|
149
|
-
|
|
149
|
+
borderRadius: 0,
|
|
150
150
|
elasticity: 0,
|
|
151
151
|
mode: 'shader' as const,
|
|
152
152
|
shaderVariant: 'premiumGlass' as const,
|
|
@@ -1140,7 +1140,7 @@ export const GlassCustom: Story = {
|
|
|
1140
1140
|
glass={{
|
|
1141
1141
|
displacementScale: 70,
|
|
1142
1142
|
blurAmount: 2,
|
|
1143
|
-
|
|
1143
|
+
borderRadius: 12,
|
|
1144
1144
|
mode: 'shader',
|
|
1145
1145
|
}}
|
|
1146
1146
|
>
|
|
@@ -1293,7 +1293,7 @@ export const GlassThemeShowcase: Story = {
|
|
|
1293
1293
|
glass={{
|
|
1294
1294
|
displacementScale: 60,
|
|
1295
1295
|
blurAmount: 1.8,
|
|
1296
|
-
|
|
1296
|
+
borderRadius: 16,
|
|
1297
1297
|
mode: 'shader',
|
|
1298
1298
|
}}
|
|
1299
1299
|
>
|
|
@@ -308,7 +308,7 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
|
|
|
308
308
|
const defaultGlassProps = {
|
|
309
309
|
displacementScale: 70,
|
|
310
310
|
blurAmount: 2,
|
|
311
|
-
|
|
311
|
+
borderRadius: 12,
|
|
312
312
|
mode: 'shader' as const,
|
|
313
313
|
};
|
|
314
314
|
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
@@ -46,7 +46,7 @@ export const Progress = memo(
|
|
|
46
46
|
const defaultGlassProps = {
|
|
47
47
|
displacementScale: 30,
|
|
48
48
|
blurAmount: 0.5,
|
|
49
|
-
|
|
49
|
+
borderRadius: 8,
|
|
50
50
|
mode: 'shader' as const,
|
|
51
51
|
};
|
|
52
52
|
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
+
import Rating from './Rating';
|
|
5
|
+
|
|
6
|
+
// Mock AtomixGlass since it's used in Rating
|
|
7
|
+
vi.mock('../AtomixGlass/AtomixGlass', () => ({
|
|
8
|
+
AtomixGlass: ({ children }: any) => <div data-testid="glass-wrapper">{children}</div>,
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
describe('Rating', () => {
|
|
12
|
+
it('renders correctly', () => {
|
|
13
|
+
render(<Rating value={3} />);
|
|
14
|
+
const stars = screen.getAllByRole('button');
|
|
15
|
+
expect(stars).toHaveLength(5);
|
|
16
|
+
// 3 full stars, 2 empty
|
|
17
|
+
expect(stars[0]).toHaveAttribute('aria-checked', 'true');
|
|
18
|
+
expect(stars[1]).toHaveAttribute('aria-checked', 'true');
|
|
19
|
+
expect(stars[2]).toHaveAttribute('aria-checked', 'true');
|
|
20
|
+
expect(stars[3]).toHaveAttribute('aria-checked', 'false');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('calculates half star on hover when allowHalf is true', () => {
|
|
24
|
+
render(<Rating allowHalf />);
|
|
25
|
+
const stars = screen.getAllByRole('button');
|
|
26
|
+
const firstStar = stars[0];
|
|
27
|
+
|
|
28
|
+
// Mock getBoundingClientRect
|
|
29
|
+
vi.spyOn(firstStar, 'getBoundingClientRect').mockReturnValue({
|
|
30
|
+
left: 100,
|
|
31
|
+
width: 20,
|
|
32
|
+
top: 0,
|
|
33
|
+
bottom: 20,
|
|
34
|
+
right: 120,
|
|
35
|
+
height: 20,
|
|
36
|
+
x: 100,
|
|
37
|
+
y: 0,
|
|
38
|
+
toJSON: () => {},
|
|
39
|
+
} as DOMRect);
|
|
40
|
+
|
|
41
|
+
// Hover on left half (105 is < 100 + 10 = 110)
|
|
42
|
+
fireEvent.mouseEnter(firstStar, { clientX: 105 });
|
|
43
|
+
fireEvent.mouseMove(firstStar, { clientX: 105 });
|
|
44
|
+
|
|
45
|
+
// Check if the star has the half class
|
|
46
|
+
// RATING.CLASSES.HALF is 'c-rating__star--half'
|
|
47
|
+
expect(firstStar).toHaveClass('c-rating__star--half');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('calculates full star on hover right half when allowHalf is true', () => {
|
|
51
|
+
render(<Rating allowHalf />);
|
|
52
|
+
const stars = screen.getAllByRole('button');
|
|
53
|
+
const firstStar = stars[0];
|
|
54
|
+
|
|
55
|
+
vi.spyOn(firstStar, 'getBoundingClientRect').mockReturnValue({
|
|
56
|
+
left: 100,
|
|
57
|
+
width: 20,
|
|
58
|
+
top: 0,
|
|
59
|
+
bottom: 20,
|
|
60
|
+
right: 120,
|
|
61
|
+
height: 20,
|
|
62
|
+
x: 100,
|
|
63
|
+
y: 0,
|
|
64
|
+
toJSON: () => {},
|
|
65
|
+
} as DOMRect);
|
|
66
|
+
|
|
67
|
+
// Hover on right half (115 is > 100 + 10 = 110)
|
|
68
|
+
fireEvent.mouseEnter(firstStar, { clientX: 115 });
|
|
69
|
+
fireEvent.mouseMove(firstStar, { clientX: 115 });
|
|
70
|
+
|
|
71
|
+
expect(firstStar).toHaveClass('c-rating__star--full');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -5,6 +5,27 @@ import type { RatingProps } from '../../lib/types/components';
|
|
|
5
5
|
import useForkRef from '../../lib/utils/useForkRef';
|
|
6
6
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
7
7
|
|
|
8
|
+
// Helper function to calculate star value based on mouse position
|
|
9
|
+
const calculateStarValue = (
|
|
10
|
+
e: React.MouseEvent,
|
|
11
|
+
starValue: number,
|
|
12
|
+
allowHalf: boolean
|
|
13
|
+
): number => {
|
|
14
|
+
if (!allowHalf) {
|
|
15
|
+
return starValue;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Get the star element's bounding rectangle
|
|
19
|
+
const starRect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
20
|
+
// Calculate the x position within the star
|
|
21
|
+
const starCenterX = starRect.left + starRect.width / 2;
|
|
22
|
+
// If mouse is on the left half of the star, use half value
|
|
23
|
+
const isHalfStar = e.clientX < starCenterX;
|
|
24
|
+
const adjustedValue = isHalfStar ? starValue - 0.5 : starValue;
|
|
25
|
+
|
|
26
|
+
return Math.max(0.5, adjustedValue); // Ensure minimum of 0.5
|
|
27
|
+
};
|
|
28
|
+
|
|
8
29
|
/**
|
|
9
30
|
* Rating component for displaying and collecting star ratings
|
|
10
31
|
*
|
|
@@ -61,19 +82,7 @@ export const Rating = forwardRef<HTMLDivElement, RatingProps>(
|
|
|
61
82
|
const handleMouseEnter = useCallback(
|
|
62
83
|
(e: React.MouseEvent, starValue: number) => {
|
|
63
84
|
if (readOnly) return;
|
|
64
|
-
|
|
65
|
-
if (allowHalf) {
|
|
66
|
-
// Get the star element's bounding rectangle
|
|
67
|
-
const starRect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
68
|
-
// Calculate the x position within the star
|
|
69
|
-
const starCenterX = starRect.left + starRect.width / 2;
|
|
70
|
-
// If mouse is on the left half of the star, use half value
|
|
71
|
-
const isHalfStar = e.clientX < starCenterX;
|
|
72
|
-
const adjustedValue = isHalfStar ? starValue - 0.5 : starValue;
|
|
73
|
-
setHoverValue(Math.max(0.5, adjustedValue)); // Ensure minimum of 0.5
|
|
74
|
-
} else {
|
|
75
|
-
setHoverValue(starValue);
|
|
76
|
-
}
|
|
85
|
+
setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
77
86
|
},
|
|
78
87
|
[readOnly, allowHalf, setHoverValue]
|
|
79
88
|
);
|
|
@@ -82,15 +91,7 @@ export const Rating = forwardRef<HTMLDivElement, RatingProps>(
|
|
|
82
91
|
const handleMouseMove = useCallback(
|
|
83
92
|
(e: React.MouseEvent, starValue: number) => {
|
|
84
93
|
if (readOnly || !allowHalf) return;
|
|
85
|
-
|
|
86
|
-
// Get the star element's bounding rectangle
|
|
87
|
-
const starRect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
88
|
-
// Calculate the x position within the star
|
|
89
|
-
const starCenterX = starRect.left + starRect.width / 2;
|
|
90
|
-
// If mouse is on the left half of the star, use half value
|
|
91
|
-
const isHalfStar = e.clientX < starCenterX;
|
|
92
|
-
const adjustedValue = isHalfStar ? starValue - 0.5 : starValue;
|
|
93
|
-
setHoverValue(Math.max(0.5, adjustedValue)); // Ensure minimum of 0.5
|
|
94
|
+
setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
94
95
|
},
|
|
95
96
|
[readOnly, allowHalf, setHoverValue]
|
|
96
97
|
);
|
|
@@ -105,20 +106,7 @@ export const Rating = forwardRef<HTMLDivElement, RatingProps>(
|
|
|
105
106
|
const handleClick = useCallback(
|
|
106
107
|
(e: React.MouseEvent, starValue: number) => {
|
|
107
108
|
if (readOnly) return;
|
|
108
|
-
|
|
109
|
-
let newValue = starValue;
|
|
110
|
-
|
|
111
|
-
if (allowHalf) {
|
|
112
|
-
// Get the star element's bounding rectangle
|
|
113
|
-
const starRect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
114
|
-
// Calculate the x position within the star
|
|
115
|
-
const starCenterX = starRect.left + starRect.width / 2;
|
|
116
|
-
// If click is on the left half of the star, use half value
|
|
117
|
-
const isHalfStar = e.clientX < starCenterX;
|
|
118
|
-
newValue = isHalfStar ? starValue - 0.5 : starValue;
|
|
119
|
-
newValue = Math.max(0.5, newValue); // Ensure minimum of 0.5
|
|
120
|
-
}
|
|
121
|
-
|
|
109
|
+
const newValue = calculateStarValue(e, starValue, !!allowHalf);
|
|
122
110
|
onChange?.(newValue);
|
|
123
111
|
},
|
|
124
112
|
[readOnly, onChange, allowHalf]
|
|
@@ -291,7 +279,7 @@ export const Rating = forwardRef<HTMLDivElement, RatingProps>(
|
|
|
291
279
|
blurAmount: 1,
|
|
292
280
|
saturation: 160,
|
|
293
281
|
aberrationIntensity: 0.5,
|
|
294
|
-
|
|
282
|
+
borderRadius: 8,
|
|
295
283
|
mode: 'shader' as const,
|
|
296
284
|
};
|
|
297
285
|
|
|
@@ -38,7 +38,7 @@ export const Spinner: React.FC<SpinnerProps> = memo(
|
|
|
38
38
|
const defaultGlassProps = {
|
|
39
39
|
displacementScale: 20,
|
|
40
40
|
blurAmount: 1,
|
|
41
|
-
|
|
41
|
+
borderRadius: 999,
|
|
42
42
|
mode: 'shader' as const,
|
|
43
43
|
};
|
|
44
44
|
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
@@ -24,7 +24,7 @@ export interface StepItemData {
|
|
|
24
24
|
export type { StepItemData as StepItem };
|
|
25
25
|
|
|
26
26
|
// Compound Component Props
|
|
27
|
-
export interface StepsItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
27
|
+
export interface StepsItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
28
28
|
/**
|
|
29
29
|
* The number or icon for the step
|
|
30
30
|
*/
|
|
@@ -231,7 +231,7 @@ const StepsComp: React.FC<StepsProps> = ({
|
|
|
231
231
|
blurAmount: 1,
|
|
232
232
|
saturation: 160,
|
|
233
233
|
aberrationIntensity: 0.5,
|
|
234
|
-
|
|
234
|
+
borderRadius: 8,
|
|
235
235
|
mode: 'shader' as const,
|
|
236
236
|
};
|
|
237
237
|
|