@shohojdhara/atomix 0.5.1 → 0.5.4
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/atomix.config.ts +45 -33
- package/build-tools/webpack-loader.js +5 -4
- package/dist/atomix.css +138 -17
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/webpack-loader.js +5 -4
- package/dist/charts.d.ts +23 -23
- package/dist/charts.js +40 -37
- package/dist/charts.js.map +1 -1
- package/dist/config.d.ts +699 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +2 -2
- package/dist/core.js +111 -50
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +3 -6
- package/dist/forms.js +2 -2
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +173 -111
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1881 -790
- package/dist/index.esm.js +2713 -816
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2693 -780
- 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 +59 -60
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +1390 -276
- package/dist/theme.js +2133 -625
- package/dist/theme.js.map +1 -1
- package/package.json +14 -9
- package/scripts/atomix-cli.js +15 -1
- package/scripts/cli/__tests__/complexity-utils.test.js +24 -0
- package/scripts/cli/__tests__/detector.test.js +50 -0
- package/scripts/cli/__tests__/template-engine.test.js +23 -0
- package/scripts/cli/__tests__/test-setup.js +3 -0
- package/scripts/cli/commands/doctor.js +15 -3
- package/scripts/cli/commands/generate.js +113 -51
- package/scripts/cli/internal/ai-engine.js +30 -10
- package/scripts/cli/internal/complexity-utils.js +60 -0
- package/scripts/cli/internal/component-validator.js +49 -16
- package/scripts/cli/internal/config-loader.js +30 -20
- package/scripts/cli/internal/generator.js +89 -36
- package/scripts/cli/internal/hook-generator.js +5 -2
- package/scripts/cli/internal/itcss-generator.js +16 -12
- package/scripts/cli/templates/next-templates.js +81 -30
- package/scripts/cli/templates/storybook-templates.js +12 -2
- package/scripts/cli/utils/detector.js +45 -7
- package/scripts/cli/utils/diagnostics.js +78 -0
- package/scripts/cli/utils/telemetry.js +13 -0
- package/src/components/Accordion/Accordion.stories.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +219 -0
- package/src/components/AtomixGlass/glass-utils.ts +1 -1
- package/src/components/Button/Button.tsx +114 -57
- package/src/components/Callout/Callout.tsx +4 -4
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/DonutChart.tsx +11 -8
- package/src/components/EdgePanel/EdgePanel.tsx +119 -115
- package/src/components/Form/Select.tsx +4 -4
- package/src/components/List/List.tsx +4 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +6 -6
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +1 -1
- package/src/components/ProductReview/ProductReview.tsx +4 -2
- package/src/components/Rating/Rating.tsx +4 -2
- package/src/components/SectionIntro/SectionIntro.tsx +4 -2
- package/src/components/Steps/Steps.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +5 -5
- package/src/components/Testimonial/Testimonial.tsx +4 -2
- package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
- package/src/layouts/CssGrid/CssGrid.stories.tsx +464 -0
- package/src/layouts/CssGrid/CssGrid.tsx +215 -0
- package/src/layouts/CssGrid/index.ts +8 -0
- package/src/layouts/CssGrid/scripts/CssGrid.js +284 -0
- package/src/layouts/CssGrid/scripts/index.js +43 -0
- package/src/layouts/Grid/scripts/Container.js +139 -0
- package/src/layouts/Grid/scripts/Grid.js +184 -0
- package/src/layouts/Grid/scripts/GridCol.js +273 -0
- package/src/layouts/Grid/scripts/Row.js +154 -0
- package/src/layouts/Grid/scripts/index.js +48 -0
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +71 -59
- package/src/lib/composables/atomix-glass/useGlassSize.ts +1 -1
- package/src/lib/composables/useAccordion.ts +5 -5
- package/src/lib/composables/useAtomixGlass.ts +3 -3
- package/src/lib/composables/useBarChart.ts +2 -2
- package/src/lib/composables/useChart.ts +3 -2
- package/src/lib/composables/useChartToolbar.ts +48 -66
- package/src/lib/composables/useDataTable.ts +1 -1
- package/src/lib/composables/useDatePicker.ts +2 -2
- package/src/lib/composables/useEdgePanel.ts +45 -54
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -5
- package/src/lib/composables/usePhotoViewer.ts +2 -3
- package/src/lib/composables/usePieChart.ts +1 -1
- package/src/lib/composables/usePopover.ts +151 -139
- package/src/lib/composables/useSideMenu.ts +28 -41
- package/src/lib/composables/useSlider.ts +2 -6
- package/src/lib/composables/useTooltip.ts +2 -2
- package/src/lib/config/index.ts +38 -323
- package/src/lib/config/loader.ts +419 -0
- package/src/lib/config/public-api.ts +43 -0
- package/src/lib/config/types.ts +389 -0
- package/src/lib/config/validator.ts +305 -0
- package/src/lib/theme/adapters/index.ts +1 -1
- package/src/lib/theme/adapters/themeAdapter.ts +358 -229
- package/src/lib/theme/components/ThemeToggle.tsx +276 -0
- package/src/lib/theme/config/configLoader.ts +351 -0
- package/src/lib/theme/config/loader.ts +221 -0
- package/src/lib/theme/core/createTheme.ts +126 -50
- package/src/lib/theme/core/createThemeObject.ts +7 -4
- package/src/lib/theme/devtools/Comparator.tsx +1 -1
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +1 -1
- package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
- package/src/lib/theme/index.ts +322 -38
- package/src/lib/theme/runtime/ThemeProvider.tsx +45 -11
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +44 -393
- package/src/lib/theme/runtime/useTheme.ts +1 -0
- package/src/lib/theme/tokens/tokens.ts +101 -1
- package/src/lib/theme/types.ts +91 -0
- package/src/lib/theme/utils/performanceMonitor.ts +315 -0
- package/src/lib/theme/utils/responsive.ts +280 -0
- package/src/lib/theme/utils/themeUtils.ts +531 -117
- package/src/styles/01-settings/_index.scss +1 -0
- package/src/styles/01-settings/_settings.atomix-glass.scss +174 -0
- package/src/styles/01-settings/_settings.masonry-grid.scss +42 -6
- package/src/styles/02-tools/_tools.glass.scss +6 -0
- package/src/styles/05-objects/_objects.masonry-grid.scss +162 -24
- package/src/styles/06-components/_components.atomix-glass.scss +4 -4
- package/src/lib/composables/useBreadcrumb.ts +0 -81
- package/src/lib/composables/useChartInteractions.ts +0 -123
- package/src/lib/composables/useChartPerformance.ts +0 -347
- package/src/lib/composables/useDropdown.ts +0 -338
- package/src/lib/composables/useModal.ts +0 -110
- package/src/lib/hooks/usePerformanceMonitor.ts +0 -148
- package/src/lib/utils/displacement-generator.ts +0 -92
- package/src/lib/utils/memoryMonitor.ts +0 -191
- package/src/styles/01-settings/_settings.testtypecheck.scss +0 -53
- package/src/styles/01-settings/_settings.typedbutton.scss +0 -53
- package/src/styles/06-components/_components.testbutton.scss +0 -212
- package/src/styles/06-components/_components.testtypecheck.scss +0 -212
- package/src/styles/06-components/_components.typedbutton.scss +0 -212
package/dist/heavy.d.ts
CHANGED
|
@@ -578,7 +578,7 @@ declare global {
|
|
|
578
578
|
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
579
579
|
* Ref is forwarded to the root `<div>` element.
|
|
580
580
|
*/
|
|
581
|
-
declare const AtomixGlass: React$1.
|
|
581
|
+
declare const AtomixGlass: React$1.NamedExoticComponent<AtomixGlassProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
582
582
|
|
|
583
583
|
/**
|
|
584
584
|
* Advanced Video Player Component
|
package/dist/heavy.js
CHANGED
|
@@ -3575,11 +3575,13 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
|
|
|
3575
3575
|
detectBorderRadius();
|
|
3576
3576
|
// Create ResizeObserver to watch for style changes
|
|
3577
3577
|
let resizeObserver = null;
|
|
3578
|
-
|
|
3578
|
+
"undefined" != typeof ResizeObserver && containerRef.current && (resizeObserver = new ResizeObserver(detectBorderRadius),
|
|
3579
3579
|
resizeObserver.observe(containerRef.current)),
|
|
3580
3580
|
// Also listen for window resize (in case styles change)
|
|
3581
|
-
window.addEventListener("resize", detectBorderRadius)
|
|
3582
|
-
|
|
3581
|
+
window.addEventListener("resize", detectBorderRadius);
|
|
3582
|
+
const currentContainer = containerRef.current;
|
|
3583
|
+
return () => {
|
|
3584
|
+
window.removeEventListener("resize", detectBorderRadius), resizeObserver && currentContainer && (resizeObserver.unobserve(currentContainer),
|
|
3583
3585
|
resizeObserver.disconnect());
|
|
3584
3586
|
};
|
|
3585
3587
|
}), []);
|
|
@@ -3914,7 +3916,7 @@ VideoPlayer.displayName = "VideoPlayer";
|
|
|
3914
3916
|
*/
|
|
3915
3917
|
const MasonryGrid = forwardRef((({children: children, className: className = "", xs: xs = 1, sm: sm, md: md, lg: lg, xl: xl, xxl: xxl, gap: gap = 16, animate: animate = !0, imagesLoaded: imagesLoaded = !0, onLayoutComplete: onLayoutComplete, onImageLoad: onImageLoad, ...props}, ref) => {
|
|
3916
3918
|
// === REFS & STATE ===
|
|
3917
|
-
const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [
|
|
3919
|
+
const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [, setLayoutComplete] = useState(!1), [loadingImages, setLoadingImages] = useState(!1), containerRef = useRef(null), columnHeights = useRef([]), imagesLoadedCount = useRef(0), totalImagesCount = useRef(0), imageElements = useRef(new Map);
|
|
3918
3920
|
useEffect((() => {
|
|
3919
3921
|
setLoadingImages(!!imagesLoaded);
|
|
3920
3922
|
}), [ columns, imagesLoaded ]),
|
|
@@ -3943,34 +3945,45 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
3943
3945
|
});
|
|
3944
3946
|
})), setItems(newItems);
|
|
3945
3947
|
}), [ children ]);
|
|
3946
|
-
// ===
|
|
3947
|
-
const
|
|
3948
|
-
if (!
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3948
|
+
// === MANAGE ITEM LAYOUT ===
|
|
3949
|
+
const calculateLayout = useCallback((() => {
|
|
3950
|
+
if (!containerRef.current || 0 === items.length) return;
|
|
3951
|
+
const colWidth = (containerRef.current.offsetWidth - gap * (columns - 1)) / columns;
|
|
3952
|
+
columnHeights.current = Array(columns).fill(0);
|
|
3953
|
+
const newPositions = [];
|
|
3954
|
+
items.forEach(((item, index) => {
|
|
3955
|
+
if (item.ref.current) {
|
|
3956
|
+
// Find the shortest column
|
|
3957
|
+
const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
|
|
3958
|
+
columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
|
|
3959
|
+
left: left,
|
|
3960
|
+
top: top,
|
|
3961
|
+
width: colWidth,
|
|
3962
|
+
height: height
|
|
3963
|
+
};
|
|
3954
3964
|
}
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
setLoadingImages(!1), // This ensures the loading class is removed *immediately* after images load
|
|
3964
|
-
// Force a double requestAnimationFrame for final layout calculation after all images are loaded (guarantees DOM paint)
|
|
3965
|
-
requestAnimationFrame((() => {
|
|
3966
|
-
requestAnimationFrame((() => {
|
|
3967
|
-
calculateLayout(),
|
|
3968
|
-
// As a failsafe, if still present for some render lag, force another setLoadingImages(false)
|
|
3969
|
-
setLoadingImages(!1);
|
|
3970
|
-
}));
|
|
3971
|
-
})), onLayoutComplete?.());
|
|
3965
|
+
})), setPositions(newPositions);
|
|
3966
|
+
}), [ items, columns, gap ]), handleImageLoad = useCallback((img => {
|
|
3967
|
+
if (imageElements.current.get(img)) return;
|
|
3968
|
+
// Add loaded class for animation
|
|
3969
|
+
if (imageElements.current.set(img, !0), imagesLoadedCount.current += 1, containerRef.current && imagesLoaded) {
|
|
3970
|
+
const itemElement = img.closest(".o-masonry-grid > div");
|
|
3971
|
+
itemElement && (itemElement.offsetHeight, itemElement.classList.add("o-masonry-grid__item-loaded"),
|
|
3972
|
+
itemElement.classList.remove("o-masonry-grid__item-loading"));
|
|
3972
3973
|
}
|
|
3973
|
-
|
|
3974
|
+
// Schedule layout recalculation after next paint to prevent overlap
|
|
3975
|
+
const scheduleLayoutUpdate = () => {
|
|
3976
|
+
const frameId = requestAnimationFrame((() => {
|
|
3977
|
+
onImageLoad?.(imagesLoadedCount.current, totalImagesCount.current), calculateLayout();
|
|
3978
|
+
}));
|
|
3979
|
+
return () => cancelAnimationFrame(frameId);
|
|
3980
|
+
}, cleanup = scheduleLayoutUpdate();
|
|
3981
|
+
// Clean up previous scheduled updates
|
|
3982
|
+
// If all images have loaded, update loading state and complete layout
|
|
3983
|
+
imagesLoadedCount.current >= totalImagesCount.current && totalImagesCount.current > 0 && (setLayoutComplete(!0),
|
|
3984
|
+
setLoadingImages(!1), setTimeout((() => cleanup()), 0), // Clean up after current execution
|
|
3985
|
+
scheduleLayoutUpdate(), onLayoutComplete?.());
|
|
3986
|
+
}), [ onImageLoad, onLayoutComplete, imagesLoaded, calculateLayout ]), trackImages = useCallback((() => {
|
|
3974
3987
|
if (!imagesLoaded || !containerRef.current) return;
|
|
3975
3988
|
imageElements.current.clear(), imagesLoadedCount.current = 0;
|
|
3976
3989
|
const images = containerRef.current.querySelectorAll("img");
|
|
@@ -3989,30 +4002,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
3989
4002
|
img.removeEventListener("error", masonryImg._masonryLoadHandler), delete masonryImg._masonryLoadHandler);
|
|
3990
4003
|
}));
|
|
3991
4004
|
});
|
|
3992
|
-
}), [ imagesLoaded, handleImageLoad, onLayoutComplete ])
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
columnHeights.current = Array(columns).fill(0);
|
|
3996
|
-
const newPositions = [];
|
|
3997
|
-
items.forEach(((item, index) => {
|
|
3998
|
-
if (item.ref.current) {
|
|
3999
|
-
// Find the shortest column
|
|
4000
|
-
const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
|
|
4001
|
-
columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
|
|
4002
|
-
left: left,
|
|
4003
|
-
top: top,
|
|
4004
|
-
width: colWidth,
|
|
4005
|
-
height: height
|
|
4006
|
-
};
|
|
4007
|
-
}
|
|
4008
|
-
})), setPositions(newPositions);
|
|
4009
|
-
}), [ items, columns, gap ]);
|
|
4010
|
-
// === OBSERVE CONTAINER RESIZE ===
|
|
4005
|
+
}), [ imagesLoaded, handleImageLoad, onLayoutComplete ]);
|
|
4006
|
+
// === TRACK & MANAGE IMAGES ===
|
|
4007
|
+
// === OBSERVE CONTAINER RESIZE ===
|
|
4011
4008
|
useEffect((() => {
|
|
4012
4009
|
if (!containerRef.current) return;
|
|
4013
|
-
let animationFrame = null;
|
|
4014
|
-
const observer = new ResizeObserver((
|
|
4015
|
-
|
|
4010
|
+
let animationFrame = null, lastWidth = 0;
|
|
4011
|
+
const observer = new ResizeObserver((entries => {
|
|
4012
|
+
const entry = entries[0];
|
|
4013
|
+
if (!entry) return;
|
|
4014
|
+
const currentWidth = entry.contentRect.width;
|
|
4015
|
+
// Only recalculate if width actually changed (prevents excessive calculations)
|
|
4016
|
+
Math.abs(currentWidth - lastWidth) > 1 && (animationFrame && cancelAnimationFrame(animationFrame),
|
|
4017
|
+
animationFrame = requestAnimationFrame((() => {
|
|
4018
|
+
calculateLayout(), lastWidth = currentWidth;
|
|
4019
|
+
})));
|
|
4016
4020
|
}));
|
|
4017
4021
|
return observer.observe(containerRef.current), () => {
|
|
4018
4022
|
observer.disconnect(), animationFrame && cancelAnimationFrame(animationFrame);
|
|
@@ -4023,24 +4027,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
4023
4027
|
setLayoutComplete(!0), void setLoadingImages(!1))
|
|
4024
4028
|
// Only reset layoutComplete when items or columns change
|
|
4025
4029
|
), [ items, columns, calculateLayout, imagesLoaded, trackImages ]),
|
|
4026
|
-
// ===
|
|
4030
|
+
// === ADD RESIZEOBSERVERS TO GRID ITEMS FOR DYNAMIC CONTENT MEASUREMENT ===
|
|
4027
4031
|
React.useEffect((() => {
|
|
4028
|
-
// Clean up old observers if items ever change
|
|
4029
4032
|
const observers = [];
|
|
4033
|
+
let animationFrame = null;
|
|
4034
|
+
// Debounced layout calculation for item resize events
|
|
4035
|
+
const debouncedCalculateLayout = () => {
|
|
4036
|
+
animationFrame && cancelAnimationFrame(animationFrame), animationFrame = requestAnimationFrame(calculateLayout);
|
|
4037
|
+
};
|
|
4030
4038
|
return items.forEach((item => {
|
|
4031
4039
|
if (item.ref.current) {
|
|
4032
|
-
const obs = new ResizeObserver(
|
|
4033
|
-
// Double rAF: ensures layout only runs after DOM/paint/async renders
|
|
4034
|
-
requestAnimationFrame((() => {
|
|
4035
|
-
requestAnimationFrame((() => {
|
|
4036
|
-
calculateLayout();
|
|
4037
|
-
}));
|
|
4038
|
-
}));
|
|
4039
|
-
}));
|
|
4040
|
+
const obs = new ResizeObserver(debouncedCalculateLayout);
|
|
4040
4041
|
obs.observe(item.ref.current), observers.push(obs);
|
|
4041
4042
|
}
|
|
4042
4043
|
})), () => {
|
|
4043
|
-
observers.forEach((obs => obs.disconnect()));
|
|
4044
|
+
observers.forEach((obs => obs.disconnect())), animationFrame && cancelAnimationFrame(animationFrame);
|
|
4044
4045
|
};
|
|
4045
4046
|
}), [ items, calculateLayout ]);
|
|
4046
4047
|
// Ensure loadingImages state resets when items/columns/imagesLoaded change
|
|
@@ -4351,9 +4352,48 @@ class ThemeNaming {
|
|
|
4351
4352
|
}
|
|
4352
4353
|
}
|
|
4353
4354
|
|
|
4355
|
+
/**
|
|
4356
|
+
* Render a slot with the given props
|
|
4357
|
+
*
|
|
4358
|
+
* Priority order:
|
|
4359
|
+
* 1. render function
|
|
4360
|
+
* 2. component
|
|
4361
|
+
* 3. children
|
|
4362
|
+
* 4. fallback
|
|
4363
|
+
*
|
|
4364
|
+
* @example
|
|
4365
|
+
* renderSlot(
|
|
4366
|
+
* { render: (props) => <CustomButton {...props} /> },
|
|
4367
|
+
* { onClick: handleClick, children: 'Click me' }
|
|
4368
|
+
* )
|
|
4369
|
+
*/
|
|
4370
|
+
function renderSlot(slot, props, fallback) {
|
|
4371
|
+
// No slot provided, use fallback
|
|
4372
|
+
if (!slot) return fallback;
|
|
4373
|
+
// Slot is a plain React node
|
|
4374
|
+
if ( React.isValidElement(slot) || "string" == typeof slot || "number" == typeof slot) return slot;
|
|
4375
|
+
// Slot is an object with rendering options
|
|
4376
|
+
if ("object" == typeof slot && null !== slot) {
|
|
4377
|
+
const slotObj = slot;
|
|
4378
|
+
// Priority 1: render function
|
|
4379
|
+
if (slotObj.render && "function" == typeof slotObj.render) return slotObj.render(props);
|
|
4380
|
+
// Priority 2: component
|
|
4381
|
+
if (slotObj.component) {
|
|
4382
|
+
const Component = slotObj.component;
|
|
4383
|
+
return jsx(Component, {
|
|
4384
|
+
...props
|
|
4385
|
+
});
|
|
4386
|
+
}
|
|
4387
|
+
// Priority 3: children
|
|
4388
|
+
if (void 0 !== slotObj.children) return slotObj.children;
|
|
4389
|
+
}
|
|
4390
|
+
// Fallback
|
|
4391
|
+
return fallback;
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4354
4394
|
ThemeNaming.prefix = "atomix";
|
|
4355
4395
|
|
|
4356
|
-
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, ...props}, ref) => {
|
|
4396
|
+
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, slots: slots, ...props}, ref) => {
|
|
4357
4397
|
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
4358
4398
|
name: iconName,
|
|
4359
4399
|
size: iconSize
|
|
@@ -4369,17 +4409,28 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4369
4409
|
children: [ loading && jsx("span", {
|
|
4370
4410
|
className: ThemeNaming.bemClass("btn", "spinner"),
|
|
4371
4411
|
"aria-hidden": "true",
|
|
4372
|
-
children:
|
|
4412
|
+
children: renderSlot(slots?.spinner, {
|
|
4413
|
+
className: ThemeNaming.bemClass("btn", "spinner"),
|
|
4373
4414
|
size: spinnerSize,
|
|
4374
4415
|
variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
|
|
4375
|
-
}
|
|
4416
|
+
}, jsx(Spinner, {
|
|
4417
|
+
size: spinnerSize,
|
|
4418
|
+
variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
|
|
4419
|
+
}))
|
|
4376
4420
|
}), iconElement && !loading && jsx("span", {
|
|
4377
4421
|
className: ThemeNaming.bemClass("btn", "icon"),
|
|
4378
4422
|
"aria-hidden": "true",
|
|
4379
|
-
children:
|
|
4423
|
+
children: renderSlot(slots?.icon, {
|
|
4424
|
+
className: ThemeNaming.bemClass("btn", "icon"),
|
|
4425
|
+
children: iconElement,
|
|
4426
|
+
size: iconSize
|
|
4427
|
+
}, iconElement)
|
|
4380
4428
|
}), !iconOnly && buttonText && jsx("span", {
|
|
4381
4429
|
className: ThemeNaming.bemClass("btn", "label"),
|
|
4382
|
-
children:
|
|
4430
|
+
children: renderSlot(slots?.label, {
|
|
4431
|
+
className: ThemeNaming.bemClass("btn", "label"),
|
|
4432
|
+
children: buttonText
|
|
4433
|
+
}, buttonText)
|
|
4383
4434
|
}) ]
|
|
4384
4435
|
}), buttonProps = {
|
|
4385
4436
|
className: buttonClass,
|
|
@@ -4396,48 +4447,59 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4396
4447
|
tabIndex: void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : 0,
|
|
4397
4448
|
style: style,
|
|
4398
4449
|
...props
|
|
4399
|
-
}
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4450
|
+
}, buttonChildren = renderSlot(slots?.root, {
|
|
4451
|
+
className: buttonClass,
|
|
4452
|
+
children: buttonContent,
|
|
4453
|
+
disabled: isDisabled,
|
|
4454
|
+
loading: loading,
|
|
4455
|
+
onClick: handleClickEvent,
|
|
4456
|
+
type: type,
|
|
4457
|
+
"aria-label": safeAriaLabel,
|
|
4458
|
+
"aria-disabled": isDisabled,
|
|
4459
|
+
"aria-busy": loading
|
|
4460
|
+
}, (() => {
|
|
4461
|
+
// Render as anchor if href is provided
|
|
4462
|
+
if (shouldRenderAsLink) {
|
|
4463
|
+
// Use custom linkComponent if provided (e.g., Next.js Link)
|
|
4464
|
+
if (linkComponent) {
|
|
4465
|
+
const LinkComp = linkComponent, linkProps = {
|
|
4466
|
+
...buttonProps,
|
|
4467
|
+
ref: ref,
|
|
4468
|
+
// linkComponent usually forwards ref to anchor
|
|
4469
|
+
href: isDisabled ? void 0 : href,
|
|
4470
|
+
to: isDisabled ? void 0 : href,
|
|
4471
|
+
target: target,
|
|
4472
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4473
|
+
};
|
|
4474
|
+
return jsx(LinkComp, {
|
|
4475
|
+
...linkProps,
|
|
4476
|
+
children: buttonContent
|
|
4477
|
+
});
|
|
4478
|
+
}
|
|
4479
|
+
// Fallback to regular anchor tag
|
|
4480
|
+
return jsx("a", {
|
|
4481
|
+
...buttonProps,
|
|
4482
|
+
ref: ref,
|
|
4483
|
+
href: isDisabled ? void 0 : href,
|
|
4484
|
+
target: target,
|
|
4485
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4486
|
+
children: buttonContent
|
|
4487
|
+
});
|
|
4488
|
+
}
|
|
4489
|
+
// Default button rendering
|
|
4490
|
+
return jsx(Component, {
|
|
4410
4491
|
...buttonProps,
|
|
4411
4492
|
ref: ref,
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
to: isDisabled ? void 0 : href,
|
|
4415
|
-
target: target,
|
|
4416
|
-
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4417
|
-
};
|
|
4418
|
-
content = jsx(LinkComp, {
|
|
4419
|
-
...linkProps,
|
|
4493
|
+
type: "button" === Component ? type : void 0,
|
|
4494
|
+
disabled: isDisabled,
|
|
4420
4495
|
children: buttonContent
|
|
4421
4496
|
});
|
|
4422
|
-
}
|
|
4423
|
-
//
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
target: target,
|
|
4429
|
-
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4430
|
-
children: buttonContent
|
|
4431
|
-
}); else
|
|
4432
|
-
// Default button rendering
|
|
4433
|
-
content = jsx(Component, {
|
|
4434
|
-
...buttonProps,
|
|
4435
|
-
ref: ref,
|
|
4436
|
-
type: "button" === Component ? type : void 0,
|
|
4437
|
-
disabled: isDisabled,
|
|
4438
|
-
children: buttonContent
|
|
4439
|
-
});
|
|
4440
|
-
if (glass) {
|
|
4497
|
+
})());
|
|
4498
|
+
// Determine if we should render as a link
|
|
4499
|
+
// If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
|
|
4500
|
+
// The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
|
|
4501
|
+
// This is a safe fallback for disabled links.
|
|
4502
|
+
if (glass) {
|
|
4441
4503
|
// Default glass props
|
|
4442
4504
|
const defaultGlassProps = {
|
|
4443
4505
|
displacementScale: 20,
|
|
@@ -4450,10 +4512,10 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4450
4512
|
};
|
|
4451
4513
|
return jsx(AtomixGlass, {
|
|
4452
4514
|
...glassProps,
|
|
4453
|
-
children:
|
|
4515
|
+
children: buttonChildren
|
|
4454
4516
|
});
|
|
4455
4517
|
}
|
|
4456
|
-
return
|
|
4518
|
+
return buttonChildren;
|
|
4457
4519
|
})));
|
|
4458
4520
|
|
|
4459
4521
|
Button.displayName = "Button";
|
|
@@ -4992,7 +5054,7 @@ useEffect((() => {
|
|
|
4992
5054
|
}
|
|
4993
5055
|
};
|
|
4994
5056
|
}));
|
|
4995
|
-
}), [
|
|
5057
|
+
}), [ currentIndex, calculateBounds, constrainPosition ]), setImagePosition = useCallback((position => {
|
|
4996
5058
|
setImageStates((prev => {
|
|
4997
5059
|
const currentState = prev[currentIndex] || {
|
|
4998
5060
|
zoomLevel: 1,
|
|
@@ -5042,7 +5104,7 @@ useEffect((() => {
|
|
|
5042
5104
|
}
|
|
5043
5105
|
};
|
|
5044
5106
|
}));
|
|
5045
|
-
}), [
|
|
5107
|
+
}), [ currentIndex, calculateBounds, constrainPosition ]), handleWheel = useCallback((event => {
|
|
5046
5108
|
var _context;
|
|
5047
5109
|
if (!isMounted || !event || !event.currentTarget) return;
|
|
5048
5110
|
// Additional safety check for the target element
|
|
@@ -5399,7 +5461,7 @@ useEffect((() => {
|
|
|
5399
5461
|
}
|
|
5400
5462
|
return prev;
|
|
5401
5463
|
}));
|
|
5402
|
-
}), [
|
|
5464
|
+
}), [ enableGestures, isDragging, startDragPosition, currentIndex, constrainPosition, calculateBounds ]), handleTouchEnd = useCallback((() => {
|
|
5403
5465
|
setIsDragging(!1), lastDistanceRef.current = null, lastMidpointRef.current = null;
|
|
5404
5466
|
}), []), currentState = imageStates[currentIndex] || {
|
|
5405
5467
|
zoomLevel: 1,
|