@shohojdhara/atomix 0.3.14 → 0.4.0
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/CHANGELOG.md +20 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +44 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +50 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +21044 -2618
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +44 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +50 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +152 -78
- package/dist/index.esm.js +346 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +359 -353
- 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 +23 -8
- package/scripts/atomix-cli.js +170 -73
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +358 -850
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +6 -5
- package/src/components/AtomixGlass/shader-utils.ts +133 -52
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -36
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +195 -0
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +122 -352
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +30 -11
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +454 -1126
- package/src/components/Button/Button.test.tsx +123 -0
- package/src/components/Button/Button.tsx +88 -60
- package/src/components/Button/ButtonGroup.stories.tsx +376 -215
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +316 -568
- package/src/components/Card/Card.stories.tsx +292 -81
- 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 +153 -16
- 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 +152 -66
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +114 -7
- package/src/components/DataTable/DataTable.stories.tsx +349 -144
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +396 -327
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +122 -78
- package/src/components/Form/Form.stories.tsx +110 -19
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- 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 +146 -17
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +372 -38
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +183 -43
- package/src/components/Modal/Modal.tsx +130 -127
- 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 +354 -97
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +160 -7
- package/src/components/River/River.stories.tsx +3 -2
- package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +104 -8
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +173 -42
- package/src/components/Tabs/Tabs.stories.tsx +141 -12
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +137 -36
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +241 -150
- 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/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +219 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +126 -97
- package/src/lib/composables/useChartExport.ts +3 -8
- package/src/lib/composables/useDataTable.ts +72 -43
- 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/components.ts +9 -32
- 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 +107 -105
- 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 +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +19 -0
- package/src/lib/utils/dataTableExport.ts +2 -15
- 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 +2 -2
- package/src/styles/01-settings/_index.scss +1 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- 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 +4 -4
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +38 -12
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.accordion.scss +56 -14
- 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 +25 -17
- 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/_index.scss +2 -0
- 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 +2 -0
- 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 +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +67 -46
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useCallback,
|
|
3
|
-
useEffect,
|
|
4
|
-
useMemo,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
2
|
import type {
|
|
9
3
|
AtomixGlassProps,
|
|
10
4
|
DisplacementMode,
|
|
@@ -41,10 +35,7 @@ const backgroundDetectionCache = new WeakMap<HTMLElement, BackgroundDetectionCac
|
|
|
41
35
|
* Compare two OverLightConfig values for equality
|
|
42
36
|
* Handles primitives (boolean, 'auto') and objects with deep comparison
|
|
43
37
|
*/
|
|
44
|
-
const compareOverLightConfig = (
|
|
45
|
-
config1: OverLightConfig,
|
|
46
|
-
config2: OverLightConfig
|
|
47
|
-
): boolean => {
|
|
38
|
+
const compareOverLightConfig = (config1: OverLightConfig, config2: OverLightConfig): boolean => {
|
|
48
39
|
// Primitive comparison for boolean and 'auto'
|
|
49
40
|
if (typeof config1 !== 'object' || config1 === null) {
|
|
50
41
|
return config1 === config2;
|
|
@@ -235,18 +226,12 @@ export function useAtomixGlass({
|
|
|
235
226
|
const effectiveCornerRadius = useMemo(() => {
|
|
236
227
|
if (cornerRadius !== undefined) {
|
|
237
228
|
const result = Math.max(0, cornerRadius);
|
|
238
|
-
// if (process.env.NODE_ENV !== 'production' && debugCornerRadius) {
|
|
239
|
-
// console.log('[AtomixGlass] Using manual cornerRadius prop:', result);
|
|
240
|
-
// }
|
|
241
229
|
return result;
|
|
242
230
|
}
|
|
243
231
|
|
|
244
232
|
const result = Math.max(0, dynamicCornerRadius);
|
|
245
|
-
// if (process.env.NODE_ENV !== 'production' && debugCornerRadius) {
|
|
246
|
-
// console.log('[AtomixGlass] Using dynamic cornerRadius:', result);
|
|
247
|
-
// }
|
|
248
233
|
return result;
|
|
249
|
-
}, [cornerRadius, dynamicCornerRadius
|
|
234
|
+
}, [cornerRadius, dynamicCornerRadius]);
|
|
250
235
|
|
|
251
236
|
const effectiveReducedMotion = useMemo(
|
|
252
237
|
() => reducedMotion || userPrefersReducedMotion,
|
|
@@ -278,7 +263,6 @@ export function useAtomixGlass({
|
|
|
278
263
|
const extractRadius = () => {
|
|
279
264
|
try {
|
|
280
265
|
let extractedRadius: number | null = null;
|
|
281
|
-
let extractionSource = 'default';
|
|
282
266
|
|
|
283
267
|
if (contentRef.current) {
|
|
284
268
|
const firstChild = contentRef.current.firstElementChild as HTMLElement;
|
|
@@ -286,7 +270,6 @@ export function useAtomixGlass({
|
|
|
286
270
|
const domRadius = extractBorderRadiusFromDOMElement(firstChild);
|
|
287
271
|
if (domRadius !== null && domRadius > 0) {
|
|
288
272
|
extractedRadius = domRadius;
|
|
289
|
-
extractionSource = 'DOM element';
|
|
290
273
|
}
|
|
291
274
|
}
|
|
292
275
|
}
|
|
@@ -295,28 +278,17 @@ export function useAtomixGlass({
|
|
|
295
278
|
const childRadius = extractBorderRadiusFromChildren(children);
|
|
296
279
|
if (childRadius > 0 && childRadius !== CONSTANTS.DEFAULT_CORNER_RADIUS) {
|
|
297
280
|
extractedRadius = childRadius;
|
|
298
|
-
extractionSource = 'React children';
|
|
299
281
|
}
|
|
300
282
|
}
|
|
301
283
|
|
|
302
284
|
if (extractedRadius !== null && extractedRadius > 0) {
|
|
303
285
|
setDynamicCornerRadius(extractedRadius);
|
|
304
|
-
|
|
305
|
-
// if (process.env.NODE_ENV !== 'production' && debugCornerRadius) {
|
|
306
|
-
// console.log('[AtomixGlass] Corner radius extracted:', {
|
|
307
|
-
// value: extractedRadius,
|
|
308
|
-
// source: extractionSource,
|
|
309
|
-
// timestamp: new Date().toISOString(),
|
|
310
|
-
// });
|
|
311
|
-
// }
|
|
312
|
-
} else if ((typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') && debugCornerRadius) {
|
|
313
|
-
// console.log(
|
|
314
|
-
// '[AtomixGlass] No corner radius found, using default:',
|
|
315
|
-
// CONSTANTS.DEFAULT_CORNER_RADIUS
|
|
316
|
-
// );
|
|
317
286
|
}
|
|
318
287
|
} catch (error) {
|
|
319
|
-
if (
|
|
288
|
+
if (
|
|
289
|
+
(typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
|
|
290
|
+
debugCornerRadius
|
|
291
|
+
) {
|
|
320
292
|
console.error('[AtomixGlass] Error extracting corner radius:', error);
|
|
321
293
|
}
|
|
322
294
|
}
|
|
@@ -330,7 +302,8 @@ export function useAtomixGlass({
|
|
|
330
302
|
// Media query handlers and background detection
|
|
331
303
|
useEffect(() => {
|
|
332
304
|
// Only run auto-detection for 'auto' mode or object config (which uses auto-detection)
|
|
333
|
-
const shouldDetect =
|
|
305
|
+
const shouldDetect =
|
|
306
|
+
overLight === 'auto' || (typeof overLight === 'object' && overLight !== null);
|
|
334
307
|
|
|
335
308
|
if (shouldDetect && glassRef.current) {
|
|
336
309
|
const element = glassRef.current;
|
|
@@ -379,7 +352,13 @@ export function useAtomixGlass({
|
|
|
379
352
|
const bgImage = computedStyle.backgroundImage;
|
|
380
353
|
|
|
381
354
|
// Check for solid color backgrounds
|
|
382
|
-
if (
|
|
355
|
+
if (
|
|
356
|
+
bgColor &&
|
|
357
|
+
bgColor !== 'rgba(0, 0, 0, 0)' &&
|
|
358
|
+
bgColor !== 'transparent' &&
|
|
359
|
+
bgColor !== 'initial' &&
|
|
360
|
+
bgColor !== 'none'
|
|
361
|
+
) {
|
|
383
362
|
const rgb = bgColor.match(/\d+/g);
|
|
384
363
|
if (rgb && rgb.length >= 3) {
|
|
385
364
|
const r = Number(rgb[0]);
|
|
@@ -387,9 +366,20 @@ export function useAtomixGlass({
|
|
|
387
366
|
const b = Number(rgb[2]);
|
|
388
367
|
|
|
389
368
|
// Validate RGB values are valid numbers
|
|
390
|
-
if (
|
|
391
|
-
|
|
392
|
-
|
|
369
|
+
if (
|
|
370
|
+
!isNaN(r) &&
|
|
371
|
+
!isNaN(g) &&
|
|
372
|
+
!isNaN(b) &&
|
|
373
|
+
isFinite(r) &&
|
|
374
|
+
isFinite(g) &&
|
|
375
|
+
isFinite(b) &&
|
|
376
|
+
r >= 0 &&
|
|
377
|
+
r <= 255 &&
|
|
378
|
+
g >= 0 &&
|
|
379
|
+
g <= 255 &&
|
|
380
|
+
b >= 0 &&
|
|
381
|
+
b <= 255
|
|
382
|
+
) {
|
|
393
383
|
// Only consider if it's not pure black or very dark
|
|
394
384
|
if (r > 10 || g > 10 || b > 10) {
|
|
395
385
|
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
@@ -436,11 +426,12 @@ export function useAtomixGlass({
|
|
|
436
426
|
if (typeof overLight === 'object' && overLight !== null) {
|
|
437
427
|
const objConfig = overLight as OverLightObjectConfig;
|
|
438
428
|
if (objConfig.threshold !== undefined) {
|
|
439
|
-
const configThreshold =
|
|
429
|
+
const configThreshold =
|
|
430
|
+
typeof objConfig.threshold === 'number' &&
|
|
440
431
|
!isNaN(objConfig.threshold) &&
|
|
441
432
|
isFinite(objConfig.threshold)
|
|
442
|
-
|
|
443
|
-
|
|
433
|
+
? objConfig.threshold
|
|
434
|
+
: 0.7;
|
|
444
435
|
threshold = Math.min(0.9, Math.max(0.1, configThreshold));
|
|
445
436
|
}
|
|
446
437
|
}
|
|
@@ -448,37 +439,31 @@ export function useAtomixGlass({
|
|
|
448
439
|
const isOverLightDetected = avgLuminance > threshold;
|
|
449
440
|
|
|
450
441
|
// Cache the result in shared cache
|
|
451
|
-
setCachedBackgroundDetection(
|
|
442
|
+
setCachedBackgroundDetection(
|
|
443
|
+
element.parentElement,
|
|
444
|
+
overLight,
|
|
445
|
+
isOverLightDetected,
|
|
446
|
+
threshold
|
|
447
|
+
);
|
|
452
448
|
|
|
453
449
|
setDetectedOverLight(isOverLightDetected);
|
|
454
|
-
|
|
455
|
-
// Debug logging
|
|
456
|
-
// if (process.env.NODE_ENV !== 'production' && debugOverLight) {
|
|
457
|
-
// console.log('[AtomixGlass] OverLight Detection:', {
|
|
458
|
-
// avgLuminance: avgLuminance.toFixed(3),
|
|
459
|
-
// threshold: threshold.toFixed(3),
|
|
460
|
-
// detected: isOverLightDetected,
|
|
461
|
-
// validSamples,
|
|
462
|
-
// totalLuminance: totalLuminance.toFixed(3),
|
|
463
|
-
// configType: typeof overLight === 'object' ? 'object' : typeof overLight,
|
|
464
|
-
// timestamp: new Date().toISOString(),
|
|
465
|
-
// });
|
|
466
|
-
// }
|
|
467
450
|
} else {
|
|
468
451
|
// Invalid luminance calculation, default to false
|
|
469
452
|
const result = false;
|
|
470
|
-
const threshold =
|
|
471
|
-
|
|
472
|
-
|
|
453
|
+
const threshold =
|
|
454
|
+
typeof overLight === 'object' && overLight !== null
|
|
455
|
+
? (overLight as OverLightObjectConfig).threshold || 0.7
|
|
456
|
+
: 0.7;
|
|
473
457
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
474
458
|
setDetectedOverLight(result);
|
|
475
459
|
}
|
|
476
460
|
} else {
|
|
477
461
|
// Default to false if no valid background found
|
|
478
462
|
const result = false;
|
|
479
|
-
const threshold =
|
|
480
|
-
|
|
481
|
-
|
|
463
|
+
const threshold =
|
|
464
|
+
typeof overLight === 'object' && overLight !== null
|
|
465
|
+
? (overLight as OverLightObjectConfig).threshold || 0.7
|
|
466
|
+
: 0.7;
|
|
482
467
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
483
468
|
setDetectedOverLight(result);
|
|
484
469
|
}
|
|
@@ -489,9 +474,10 @@ export function useAtomixGlass({
|
|
|
489
474
|
}
|
|
490
475
|
const result = false;
|
|
491
476
|
if (element && element.parentElement) {
|
|
492
|
-
const threshold =
|
|
493
|
-
|
|
494
|
-
|
|
477
|
+
const threshold =
|
|
478
|
+
typeof overLight === 'object' && overLight !== null
|
|
479
|
+
? (overLight as OverLightObjectConfig).threshold || 0.7
|
|
480
|
+
: 0.7;
|
|
495
481
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
496
482
|
}
|
|
497
483
|
setDetectedOverLight(result);
|
|
@@ -501,17 +487,7 @@ export function useAtomixGlass({
|
|
|
501
487
|
return () => clearTimeout(timeoutId);
|
|
502
488
|
} else if (typeof overLight === 'boolean') {
|
|
503
489
|
// For boolean values, disable auto-detection
|
|
504
|
-
// Cache is automatically managed by WeakMap (no manual clearing needed)
|
|
505
490
|
setDetectedOverLight(false);
|
|
506
|
-
|
|
507
|
-
// Debug logging for boolean mode
|
|
508
|
-
// if (process.env.NODE_ENV !== 'production' && debugOverLight) {
|
|
509
|
-
// console.log('[AtomixGlass] OverLight Mode: boolean', {
|
|
510
|
-
// value: overLight,
|
|
511
|
-
// autoDetection: false,
|
|
512
|
-
// timestamp: new Date().toISOString(),
|
|
513
|
-
// });
|
|
514
|
-
// }
|
|
515
491
|
}
|
|
516
492
|
|
|
517
493
|
if (typeof window.matchMedia !== 'function') {
|
|
@@ -607,9 +583,12 @@ export function useAtomixGlass({
|
|
|
607
583
|
setInternalMouseOffset(newOffset);
|
|
608
584
|
setInternalGlobalMousePosition(globalPos);
|
|
609
585
|
|
|
610
|
-
if (
|
|
586
|
+
if (
|
|
587
|
+
(typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
|
|
588
|
+
enablePerformanceMonitoring
|
|
589
|
+
) {
|
|
611
590
|
const endTime = performance.now();
|
|
612
|
-
const duration = endTime - startTime;
|
|
591
|
+
// const duration = endTime - startTime;
|
|
613
592
|
// if (duration > 5) {
|
|
614
593
|
// console.warn(`AtomixGlass: Mouse tracking took ${duration.toFixed(2)}ms`);
|
|
615
594
|
// }
|
|
@@ -684,6 +663,16 @@ export function useAtomixGlass({
|
|
|
684
663
|
|
|
685
664
|
// Transform calculations
|
|
686
665
|
const calculateDirectionalScale = useCallback(() => {
|
|
666
|
+
// Disable directional scaling if overLight is active (to prevent zooming/distorting the premium glass effect)
|
|
667
|
+
const isOverLightActive =
|
|
668
|
+
overLight === true ||
|
|
669
|
+
(overLight === 'auto' && detectedOverLight) ||
|
|
670
|
+
(typeof overLight === 'object' && overLight !== null && detectedOverLight);
|
|
671
|
+
|
|
672
|
+
if (isOverLightActive) {
|
|
673
|
+
return 'scale(1)';
|
|
674
|
+
}
|
|
675
|
+
|
|
687
676
|
if (
|
|
688
677
|
!globalMousePosition.x ||
|
|
689
678
|
!globalMousePosition.y ||
|
|
@@ -727,7 +716,7 @@ export function useAtomixGlass({
|
|
|
727
716
|
Math.abs(normalizedX) * stretchIntensity * 0.15;
|
|
728
717
|
|
|
729
718
|
return `scaleX(${Math.max(0.8, scaleX)}) scaleY(${Math.max(0.8, scaleY)})`;
|
|
730
|
-
}, [globalMousePosition, elasticity, glassSize, glassRef]);
|
|
719
|
+
}, [globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight]);
|
|
731
720
|
|
|
732
721
|
const calculateFadeInFactor = useCallback(() => {
|
|
733
722
|
if (
|
|
@@ -752,7 +741,9 @@ export function useAtomixGlass({
|
|
|
752
741
|
);
|
|
753
742
|
const edgeDistance = calculateDistance({ x: edgeDistanceX, y: edgeDistanceY }, { x: 0, y: 0 });
|
|
754
743
|
|
|
755
|
-
return edgeDistance > CONSTANTS.ACTIVATION_ZONE
|
|
744
|
+
return edgeDistance > CONSTANTS.ACTIVATION_ZONE
|
|
745
|
+
? 0
|
|
746
|
+
: 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
|
|
756
747
|
}, [globalMousePosition, glassSize, glassRef]);
|
|
757
748
|
|
|
758
749
|
const calculateElasticTranslation = useCallback(() => {
|
|
@@ -797,7 +788,9 @@ export function useAtomixGlass({
|
|
|
797
788
|
element !== null && element instanceof HTMLElement && element.isConnected;
|
|
798
789
|
|
|
799
790
|
const validateSize = (size: GlassSize): boolean =>
|
|
800
|
-
validateGlassSize(size) &&
|
|
791
|
+
validateGlassSize(size) &&
|
|
792
|
+
size.width <= CONSTANTS.MAX_SIZE &&
|
|
793
|
+
size.height <= CONSTANTS.MAX_SIZE;
|
|
801
794
|
|
|
802
795
|
let rafId: number | null = null;
|
|
803
796
|
let lastSize = { width: 0, height: 0 };
|
|
@@ -931,40 +924,65 @@ export function useAtomixGlass({
|
|
|
931
924
|
const activeIntensity = isActive ? 1.6 : 1;
|
|
932
925
|
|
|
933
926
|
// More robust overlight configuration with better defaults and clamping
|
|
934
|
-
const baseOpacity = isOverLight
|
|
927
|
+
const baseOpacity = isOverLight
|
|
928
|
+
? Math.min(0.6, Math.max(0.2, 0.5 * hoverIntensity * activeIntensity))
|
|
929
|
+
: 0;
|
|
935
930
|
|
|
936
931
|
const baseConfig = {
|
|
937
932
|
isOverLight,
|
|
938
933
|
threshold: 0.7,
|
|
939
934
|
opacity: baseOpacity,
|
|
940
|
-
contrast: Math.min(1.
|
|
941
|
-
brightness: Math.min(1.
|
|
942
|
-
saturationBoost:
|
|
943
|
-
shadowIntensity: Math.min(1.
|
|
944
|
-
borderOpacity: Math.min(1.0, Math.max(0.3, 0.7 + mouseInfluence * 0.
|
|
935
|
+
contrast: Math.min(1.6, Math.max(1.0, 1.4 + mouseInfluence * 0.1)),
|
|
936
|
+
brightness: Math.min(1.1, Math.max(0.8, 0.9 + mouseInfluence * 0.05)),
|
|
937
|
+
saturationBoost: 1.3, // Fixed value — dynamic saturation amplifies perceived displacement
|
|
938
|
+
shadowIntensity: Math.min(1.2, Math.max(0.5, 0.9 + mouseInfluence * 0.2)),
|
|
939
|
+
borderOpacity: Math.min(1.0, Math.max(0.3, 0.7 + mouseInfluence * 0.1)),
|
|
945
940
|
};
|
|
946
941
|
|
|
947
942
|
if (typeof overLight === 'object' && overLight !== null) {
|
|
948
943
|
const objConfig = overLight as OverLightObjectConfig;
|
|
949
944
|
|
|
950
945
|
// Validate and apply object config values with proper clamping
|
|
951
|
-
const validatedThreshold = validateConfigValue(
|
|
946
|
+
const validatedThreshold = validateConfigValue(
|
|
947
|
+
objConfig.threshold,
|
|
948
|
+
0.1,
|
|
949
|
+
1.0,
|
|
950
|
+
baseConfig.threshold
|
|
951
|
+
);
|
|
952
952
|
const validatedOpacity = validateConfigValue(objConfig.opacity, 0.1, 1.0, baseConfig.opacity);
|
|
953
|
-
const validatedContrast = validateConfigValue(
|
|
954
|
-
|
|
955
|
-
|
|
953
|
+
const validatedContrast = validateConfigValue(
|
|
954
|
+
objConfig.contrast,
|
|
955
|
+
0.5,
|
|
956
|
+
2.5,
|
|
957
|
+
baseConfig.contrast
|
|
958
|
+
);
|
|
959
|
+
const validatedBrightness = validateConfigValue(
|
|
960
|
+
objConfig.brightness,
|
|
961
|
+
0.5,
|
|
962
|
+
2.0,
|
|
963
|
+
baseConfig.brightness
|
|
964
|
+
);
|
|
965
|
+
const validatedSaturationBoost = validateConfigValue(
|
|
966
|
+
objConfig.saturationBoost,
|
|
967
|
+
0.5,
|
|
968
|
+
3.0,
|
|
969
|
+
baseConfig.saturationBoost
|
|
970
|
+
);
|
|
956
971
|
|
|
957
972
|
const finalConfig = {
|
|
958
973
|
...baseConfig,
|
|
959
974
|
threshold: validatedThreshold,
|
|
960
975
|
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
961
|
-
contrast: validatedContrast + mouseInfluence * 0.
|
|
962
|
-
brightness: validatedBrightness + mouseInfluence * 0.
|
|
963
|
-
saturationBoost: validatedSaturationBoost
|
|
976
|
+
contrast: Math.min(1.6, validatedContrast + mouseInfluence * 0.1),
|
|
977
|
+
brightness: Math.min(1.1, validatedBrightness + mouseInfluence * 0.05),
|
|
978
|
+
saturationBoost: validatedSaturationBoost, // Use validated value directly, no mouse influence
|
|
964
979
|
};
|
|
965
980
|
|
|
966
981
|
// Debug logging
|
|
967
|
-
if (
|
|
982
|
+
if (
|
|
983
|
+
(typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
|
|
984
|
+
debugOverLight
|
|
985
|
+
) {
|
|
968
986
|
console.log('[AtomixGlass] OverLight Config:', {
|
|
969
987
|
isOverLight,
|
|
970
988
|
config: {
|
|
@@ -996,7 +1014,10 @@ export function useAtomixGlass({
|
|
|
996
1014
|
}
|
|
997
1015
|
|
|
998
1016
|
// Debug logging for non-object configs
|
|
999
|
-
if (
|
|
1017
|
+
if (
|
|
1018
|
+
(typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
|
|
1019
|
+
debugOverLight
|
|
1020
|
+
) {
|
|
1000
1021
|
console.log('[AtomixGlass] OverLight Config:', {
|
|
1001
1022
|
isOverLight,
|
|
1002
1023
|
configType: typeof overLight === 'boolean' ? (overLight ? 'true' : 'false') : overLight,
|
|
@@ -1019,7 +1040,15 @@ export function useAtomixGlass({
|
|
|
1019
1040
|
}
|
|
1020
1041
|
|
|
1021
1042
|
return baseConfig;
|
|
1022
|
-
}, [
|
|
1043
|
+
}, [
|
|
1044
|
+
overLight,
|
|
1045
|
+
getEffectiveOverLight,
|
|
1046
|
+
mouseOffset,
|
|
1047
|
+
isHovered,
|
|
1048
|
+
isActive,
|
|
1049
|
+
validateConfigValue,
|
|
1050
|
+
debugOverLight,
|
|
1051
|
+
]);
|
|
1023
1052
|
|
|
1024
1053
|
// Event handlers
|
|
1025
1054
|
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { sanitizeCSVCell } from '../utils/csv';
|
|
2
3
|
|
|
3
4
|
export interface ExportOptions {
|
|
4
5
|
/**
|
|
@@ -180,13 +181,7 @@ export function useChartExport() {
|
|
|
180
181
|
|
|
181
182
|
// Convert to CSV string with sanitization
|
|
182
183
|
const csvContent = rows
|
|
183
|
-
.map(row => row.map(cell => {
|
|
184
|
-
// Sanitize cell content to prevent CSV injection
|
|
185
|
-
const sanitized = String(cell).replace(/[\r\n\t]/g, ' ').replace(/"/g, '""');
|
|
186
|
-
// Prevent formula injection by prefixing dangerous characters
|
|
187
|
-
const dangerous = /^[=+\-@]/;
|
|
188
|
-
return `"${dangerous.test(sanitized) ? `'${sanitized}` : sanitized}"`;
|
|
189
|
-
}).join(','))
|
|
184
|
+
.map(row => row.map(cell => `"${sanitizeCSVCell(cell)}"`).join(','))
|
|
190
185
|
.join('\n');
|
|
191
186
|
|
|
192
187
|
// Download
|
|
@@ -330,4 +325,4 @@ export function useChartExport() {
|
|
|
330
325
|
exportChart,
|
|
331
326
|
shareChart,
|
|
332
327
|
};
|
|
333
|
-
}
|
|
328
|
+
}
|
|
@@ -274,7 +274,9 @@ export function useDataTable({
|
|
|
274
274
|
const visibleColumns = useMemo(() => {
|
|
275
275
|
return columnOrder
|
|
276
276
|
.map(key => columns.find(col => col.key === key))
|
|
277
|
-
.filter(
|
|
277
|
+
.filter(
|
|
278
|
+
(col): col is DataTableColumn => col !== undefined && columnVisibility[col.key] !== false
|
|
279
|
+
);
|
|
278
280
|
}, [columns, columnOrder, columnVisibility]);
|
|
279
281
|
|
|
280
282
|
// Handle sorting
|
|
@@ -299,13 +301,10 @@ export function useDataTable({
|
|
|
299
301
|
);
|
|
300
302
|
|
|
301
303
|
// Handle page change
|
|
302
|
-
const handlePageChange = useCallback(
|
|
303
|
-
(page
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
},
|
|
307
|
-
[]
|
|
308
|
-
);
|
|
304
|
+
const handlePageChange = useCallback((page: number) => {
|
|
305
|
+
if (page < 1) return;
|
|
306
|
+
setCurrentPage(page);
|
|
307
|
+
}, []);
|
|
309
308
|
|
|
310
309
|
// Handle search
|
|
311
310
|
const handleSearch = useCallback((query: string) => {
|
|
@@ -328,47 +327,73 @@ export function useDataTable({
|
|
|
328
327
|
setCurrentPage(1);
|
|
329
328
|
}, []);
|
|
330
329
|
|
|
330
|
+
// Pre-process column filters to avoid redundant lookups and transformations
|
|
331
|
+
const activeColumnFilters = useMemo(() => {
|
|
332
|
+
if (!columnFilters)
|
|
333
|
+
return [] as Array<{
|
|
334
|
+
key: string;
|
|
335
|
+
value: string;
|
|
336
|
+
lowercaseValue: string;
|
|
337
|
+
column: DataTableColumn;
|
|
338
|
+
}>;
|
|
339
|
+
|
|
340
|
+
return Object.entries(columnFilterValues)
|
|
341
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
342
|
+
.map(([columnKey, value]) => {
|
|
343
|
+
const column = columns.find(col => col.key === columnKey);
|
|
344
|
+
if (!column || !column.filterable) return null;
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
key: columnKey,
|
|
348
|
+
value,
|
|
349
|
+
lowercaseValue:
|
|
350
|
+
typeof value === 'string' ? value.toLowerCase() : String(value).toLowerCase(),
|
|
351
|
+
column,
|
|
352
|
+
};
|
|
353
|
+
})
|
|
354
|
+
.filter((f): f is NonNullable<typeof f> => f !== null);
|
|
355
|
+
}, [columnFilters, columnFilterValues, columns]);
|
|
356
|
+
|
|
331
357
|
// Filter data based on search query and column filters
|
|
332
358
|
const filteredData = useMemo(() => {
|
|
333
|
-
|
|
359
|
+
if (!searchQuery && activeColumnFilters.length === 0) {
|
|
360
|
+
return data;
|
|
361
|
+
}
|
|
334
362
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
363
|
+
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : '';
|
|
364
|
+
|
|
365
|
+
return data.filter(row => {
|
|
366
|
+
// Apply global search
|
|
367
|
+
if (searchQuery) {
|
|
368
|
+
const matchesGlobal = visibleColumns.some(column => {
|
|
340
369
|
const value = row[column.key];
|
|
341
370
|
if (value == null) return false;
|
|
342
371
|
return String(value).toLowerCase().includes(lowercaseQuery);
|
|
343
372
|
});
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
// Apply column-specific filters
|
|
348
|
-
if (columnFilters) {
|
|
349
|
-
result = result.filter(row => {
|
|
350
|
-
return Object.entries(columnFilterValues).every(([columnKey, filterValue]) => {
|
|
351
|
-
if (!filterValue) return true;
|
|
352
|
-
|
|
353
|
-
const column = columns.find(col => col.key === columnKey);
|
|
354
|
-
if (!column || !column.filterable) return true;
|
|
373
|
+
if (!matchesGlobal) return false;
|
|
374
|
+
}
|
|
355
375
|
|
|
356
|
-
|
|
357
|
-
|
|
376
|
+
// Apply column-specific filters
|
|
377
|
+
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
378
|
+
const filter = activeColumnFilters[i];
|
|
379
|
+
if (!filter) continue;
|
|
380
|
+
const { key, value, lowercaseValue, column } = filter;
|
|
381
|
+
const cellValue = row[key];
|
|
358
382
|
|
|
359
|
-
|
|
360
|
-
if (column.filterFunction) {
|
|
361
|
-
return column.filterFunction(cellValue, filterValue);
|
|
362
|
-
}
|
|
383
|
+
if (cellValue == null) return false;
|
|
363
384
|
|
|
385
|
+
// Use custom filter function if provided
|
|
386
|
+
if (column.filterFunction) {
|
|
387
|
+
if (!column.filterFunction(cellValue, value)) return false;
|
|
388
|
+
} else {
|
|
364
389
|
// Default text filter
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
390
|
+
if (!String(cellValue).toLowerCase().includes(lowercaseValue)) return false;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
369
393
|
|
|
370
|
-
|
|
371
|
-
|
|
394
|
+
return true;
|
|
395
|
+
});
|
|
396
|
+
}, [data, visibleColumns, searchQuery, activeColumnFilters]);
|
|
372
397
|
|
|
373
398
|
// Sort data
|
|
374
399
|
const sortedData = useMemo(() => {
|
|
@@ -434,7 +459,9 @@ export function useDataTable({
|
|
|
434
459
|
}
|
|
435
460
|
|
|
436
461
|
if (onSelectionChange) {
|
|
437
|
-
const selectedRowsData = sortedData.filter(row =>
|
|
462
|
+
const selectedRowsData = sortedData.filter(row =>
|
|
463
|
+
newSelectedIds.includes(getRowId(row, rowKey))
|
|
464
|
+
);
|
|
438
465
|
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
439
466
|
}
|
|
440
467
|
},
|
|
@@ -446,16 +473,16 @@ export function useDataTable({
|
|
|
446
473
|
(selected: boolean) => {
|
|
447
474
|
if (selectionMode !== 'multiple') return;
|
|
448
475
|
|
|
449
|
-
const newSelectedIds = selected
|
|
450
|
-
? paginatedData.map(row => getRowId(row, rowKey))
|
|
451
|
-
: [];
|
|
476
|
+
const newSelectedIds = selected ? paginatedData.map(row => getRowId(row, rowKey)) : [];
|
|
452
477
|
|
|
453
478
|
if (!controlledSelectedRowIds) {
|
|
454
479
|
setInternalSelectedRowIds(newSelectedIds);
|
|
455
480
|
}
|
|
456
481
|
|
|
457
482
|
if (onSelectionChange) {
|
|
458
|
-
const selectedRowsData = sortedData.filter(row =>
|
|
483
|
+
const selectedRowsData = sortedData.filter(row =>
|
|
484
|
+
newSelectedIds.includes(getRowId(row, rowKey))
|
|
485
|
+
);
|
|
459
486
|
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
460
487
|
}
|
|
461
488
|
},
|
|
@@ -471,7 +498,9 @@ export function useDataTable({
|
|
|
471
498
|
// Check if some rows are selected (indeterminate)
|
|
472
499
|
const isIndeterminate = useMemo(() => {
|
|
473
500
|
if (selectionMode !== 'multiple' || paginatedData.length === 0) return false;
|
|
474
|
-
const selectedCount = paginatedData.filter(row =>
|
|
501
|
+
const selectedCount = paginatedData.filter(row =>
|
|
502
|
+
selectedRowIds.includes(getRowId(row, rowKey))
|
|
503
|
+
).length;
|
|
475
504
|
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
476
505
|
}, [selectionMode, paginatedData, selectedRowIds, rowKey]);
|
|
477
506
|
|