@shohojdhara/atomix 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6795,7 +6795,7 @@ declare const ATOMIX_GLASS: {
6795
6795
  CORNER_RADIUS: number;
6796
6796
  PADDING: string;
6797
6797
  MODE: "standard";
6798
- OVER_LIGHT: "auto";
6798
+ OVER_LIGHT: false;
6799
6799
  ENABLE_OVER_LIGHT_LAYERS: boolean;
6800
6800
  };
6801
6801
  CONSTANTS: {
@@ -9491,9 +9491,38 @@ interface WaterfallChartProps extends Omit<ChartProps$1, 'type' | 'datasets'> {
9491
9491
  }
9492
9492
  declare const WaterfallChart: react.MemoExoticComponent<react.ForwardRefExoticComponent<WaterfallChartProps & react.RefAttributes<HTMLDivElement>>>;
9493
9493
 
9494
+ type ColorMode = 'light' | 'dark';
9494
9495
  interface ColorModeToggleProps {
9496
+ /** Additional CSS class names */
9495
9497
  className?: string;
9498
+ /** Inline styles */
9496
9499
  style?: react__default.CSSProperties;
9500
+ /** Controlled mode value */
9501
+ value?: ColorMode;
9502
+ /** Default mode (uncontrolled) */
9503
+ defaultValue?: ColorMode;
9504
+ /** Callback when mode changes */
9505
+ onChange?: (mode: ColorMode) => void;
9506
+ /** Custom light mode icon */
9507
+ lightIcon?: react__default.ReactNode;
9508
+ /** Custom dark mode icon */
9509
+ darkIcon?: react__default.ReactNode;
9510
+ /** Size variant */
9511
+ size?: 'sm' | 'md' | 'lg';
9512
+ /** Disable the toggle */
9513
+ disabled?: boolean;
9514
+ /** localStorage key for persistence */
9515
+ storageKey?: string;
9516
+ /** data attribute name for body element */
9517
+ dataAttribute?: string;
9518
+ /** Disable localStorage persistence */
9519
+ disableStorage?: boolean;
9520
+ /** Disable system preference detection */
9521
+ disableSystemPreference?: boolean;
9522
+ /** Custom aria-label */
9523
+ 'aria-label'?: string;
9524
+ /** Show tooltip */
9525
+ showTooltip?: boolean;
9497
9526
  }
9498
9527
  declare const ColorModeToggle: react__default.FC<ColorModeToggleProps>;
9499
9528
 
package/dist/index.esm.js CHANGED
@@ -1536,7 +1536,7 @@ const ATOMIX_GLASS = {
1536
1536
  CORNER_RADIUS: 16, // Default border-radius matching design system
1537
1537
  PADDING: '0 0',
1538
1538
  MODE: 'standard',
1539
- OVER_LIGHT: 'auto',
1539
+ OVER_LIGHT: false,
1540
1540
  ENABLE_OVER_LIGHT_LAYERS: true,
1541
1541
  },
1542
1542
  CONSTANTS: {
@@ -2829,7 +2829,6 @@ const AtomixGlassContainer = forwardRef(({ children, className = '', style, disp
2829
2829
  padding: `var(--atomix-glass-container-padding)`,
2830
2830
  borderRadius: `var(--atomix-glass-container-radius)`,
2831
2831
  boxShadow: `var(--atomix-glass-container-box-shadow)`,
2832
- transition: effectiveReducedMotion ? 'none' : 'all 0.2s ease-out',
2833
2832
  }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, children: [jsxs("div", { className: ATOMIX_GLASS.FILTER_CLASS, children: [jsx(GlassFilter, { mode: mode, id: filterId, displacementScale: typeof displacementScale === 'number' && !isNaN(displacementScale)
2834
2833
  ? displacementScale
2835
2834
  : 0, aberrationIntensity: typeof aberrationIntensity === 'number' && !isNaN(aberrationIntensity)
@@ -3899,7 +3898,6 @@ function AtomixGlass({ children, displacementScale = ATOMIX_GLASS.DEFAULTS.DISPL
3899
3898
  width: adjustedSize.width,
3900
3899
  borderRadius: `${effectiveCornerRadius}px`,
3901
3900
  transform: baseStyle.transform,
3902
- transition: baseStyle.transition,
3903
3901
  } }), jsx("div", { className: [
3904
3902
  ATOMIX_GLASS.BACKGROUND_LAYER_CLASS,
3905
3903
  ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS,
@@ -3914,7 +3912,6 @@ function AtomixGlass({ children, displacementScale = ATOMIX_GLASS.DEFAULTS.DISPL
3914
3912
  width: adjustedSize.width,
3915
3913
  borderRadius: `${effectiveCornerRadius}px`,
3916
3914
  transform: baseStyle.transform,
3917
- transition: baseStyle.transition,
3918
3915
  } }), shouldRenderOverLightLayers && (jsxs(Fragment, { children: [jsx("div", { className: ATOMIX_GLASS.BASE_LAYER_CLASS }), jsx("div", { className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS }), jsx("div", { className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS, style: {
3919
3916
  opacity: opacityValues.over *
3920
3917
  ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
@@ -8867,58 +8864,103 @@ const WaterfallChart = memo(forwardRef(({ waterfallData = [], config = {}, water
8867
8864
  }));
8868
8865
  WaterfallChart.displayName = 'WaterfallChart';
8869
8866
 
8870
- const ColorModeToggle = ({ className = '', style }) => {
8871
- const [colorMode, setColorMode] = useState('light');
8867
+ const DEFAULT_STORAGE_KEY = 'atomix-color-mode';
8868
+ const DEFAULT_DATA_ATTRIBUTE = 'data-atomix-color-mode';
8869
+ const SIZE_MAP = {
8870
+ sm: 16,
8871
+ md: 24,
8872
+ lg: 32,
8873
+ };
8874
+ const ColorModeToggle = ({ className = '', style, value: controlledValue, defaultValue = 'light', onChange, lightIcon, darkIcon, size = 'md', disabled = false, storageKey = DEFAULT_STORAGE_KEY, dataAttribute = DEFAULT_DATA_ATTRIBUTE, disableStorage = false, disableSystemPreference = false, 'aria-label': ariaLabel, showTooltip = true, }) => {
8875
+ const isControlled = controlledValue !== undefined;
8876
+ const [internalMode, setInternalMode] = useState(defaultValue);
8877
+ const colorMode = isControlled ? controlledValue : internalMode;
8872
8878
  // Initialize color mode from localStorage or system preference
8873
8879
  useEffect(() => {
8880
+ if (isControlled)
8881
+ return;
8882
+ // SSR check
8883
+ if (typeof window === 'undefined')
8884
+ return;
8874
8885
  // Check if color mode is already set in localStorage
8875
- const storedColorMode = localStorage.getItem('atomix-color-mode');
8876
- if (storedColorMode === 'light' || storedColorMode === 'dark') {
8877
- setColorMode(storedColorMode);
8886
+ if (!disableStorage) {
8887
+ try {
8888
+ const storedColorMode = localStorage.getItem(storageKey);
8889
+ if (storedColorMode === 'light' || storedColorMode === 'dark') {
8890
+ setInternalMode(storedColorMode);
8891
+ return;
8892
+ }
8893
+ }
8894
+ catch (error) {
8895
+ console.warn('ColorModeToggle: Failed to read from localStorage', error);
8896
+ }
8878
8897
  }
8879
- else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
8880
- // Use system preference if no stored preference
8881
- setColorMode('dark');
8898
+ // Use system preference if no stored preference
8899
+ if (!disableSystemPreference && window.matchMedia) {
8900
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
8901
+ if (prefersDark) {
8902
+ setInternalMode('dark');
8903
+ }
8882
8904
  }
8883
- }, []);
8905
+ }, [isControlled, disableStorage, disableSystemPreference, storageKey]);
8884
8906
  // Update the document theme attribute when colorMode changes
8885
8907
  useEffect(() => {
8908
+ if (typeof window === 'undefined')
8909
+ return;
8886
8910
  const validColorMode = colorMode === 'dark' ? 'dark' : 'light';
8887
- document.body.setAttribute('data-atomix-color-mode', validColorMode);
8888
- localStorage.setItem('atomix-color-mode', validColorMode);
8889
- }, [colorMode]);
8911
+ document.body.setAttribute(dataAttribute, validColorMode);
8912
+ if (!disableStorage) {
8913
+ try {
8914
+ localStorage.setItem(storageKey, validColorMode);
8915
+ }
8916
+ catch (error) {
8917
+ console.warn('ColorModeToggle: Failed to write to localStorage', error);
8918
+ }
8919
+ }
8920
+ }, [colorMode, dataAttribute, disableStorage, storageKey]);
8890
8921
  // Listen for system color scheme changes
8891
8922
  useEffect(() => {
8923
+ if (isControlled || disableSystemPreference || typeof window === 'undefined')
8924
+ return;
8892
8925
  const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
8893
8926
  const handleSystemThemeChange = (event) => {
8894
8927
  // Only update if user hasn't explicitly set a preference
8895
- if (!localStorage.getItem('atomix-color-mode')) {
8896
- setColorMode(event.matches ? 'dark' : 'light');
8897
- }
8898
- };
8899
- // Add event listener for system theme changes
8900
- if (darkModeMediaQuery.addEventListener) {
8901
- darkModeMediaQuery.addEventListener('change', handleSystemThemeChange);
8902
- }
8903
- else {
8904
- // Fallback for older browsers
8905
- darkModeMediaQuery.addListener(handleSystemThemeChange);
8906
- }
8907
- // Clean up event listener
8908
- return () => {
8909
- if (darkModeMediaQuery.removeEventListener) {
8910
- darkModeMediaQuery.removeEventListener('change', handleSystemThemeChange);
8928
+ if (disableStorage) {
8929
+ setInternalMode(event.matches ? 'dark' : 'light');
8911
8930
  }
8912
8931
  else {
8913
- // Fallback for older browsers
8914
- darkModeMediaQuery.removeListener(handleSystemThemeChange);
8932
+ try {
8933
+ const hasStoredPreference = localStorage.getItem(storageKey);
8934
+ if (!hasStoredPreference) {
8935
+ setInternalMode(event.matches ? 'dark' : 'light');
8936
+ }
8937
+ }
8938
+ catch (error) {
8939
+ console.warn('ColorModeToggle: Failed to check localStorage', error);
8940
+ }
8915
8941
  }
8916
8942
  };
8917
- }, []);
8918
- const toggleColorMode = () => {
8919
- setColorMode(prevMode => (prevMode === 'light' ? 'dark' : 'light'));
8920
- };
8921
- return (jsx("button", { className: `c-color-mode-toggle ${className}`, onClick: toggleColorMode, "aria-label": `Switch to ${colorMode === 'light' ? 'dark' : 'light'} mode`, title: `Switch to ${colorMode === 'light' ? 'dark' : 'light'} mode`, style: style, children: colorMode === 'light' ? (jsx("svg", { viewBox: "0 0 24 24", width: "24", height: "24", fill: "currentColor", children: jsx("path", { d: "M9.37 5.51c-.18.64-.27 1.31-.27 1.99 0 4.08 3.32 7.4 7.4 7.4.68 0 1.35-.09 1.99-.27C17.45 17.19 14.93 19 12 19c-3.86 0-7-3.14-7-7 0-2.93 1.81-5.45 4.37-6.49zM12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z" }) })) : (jsx("svg", { viewBox: "0 0 24 24", width: "24", height: "24", fill: "currentColor", children: jsx("path", { d: "M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41.39.39 1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41.39.39 1.03.39 1.41 0l1.06-1.06z" }) })) }));
8943
+ darkModeMediaQuery.addEventListener('change', handleSystemThemeChange);
8944
+ return () => {
8945
+ darkModeMediaQuery.removeEventListener('change', handleSystemThemeChange);
8946
+ };
8947
+ }, [isControlled, disableSystemPreference, disableStorage, storageKey]);
8948
+ const toggleColorMode = useCallback(() => {
8949
+ if (disabled)
8950
+ return;
8951
+ const newMode = colorMode === 'light' ? 'dark' : 'light';
8952
+ if (!isControlled) {
8953
+ setInternalMode(newMode);
8954
+ }
8955
+ onChange?.(newMode);
8956
+ }, [disabled, colorMode, isControlled, onChange]);
8957
+ const iconSize = SIZE_MAP[size];
8958
+ const nextMode = colorMode === 'light' ? 'dark' : 'light';
8959
+ const label = ariaLabel || `Switch to ${nextMode} mode`;
8960
+ const title = showTooltip ? `Switch to ${nextMode} mode` : undefined;
8961
+ const defaultLightIcon = (jsx("svg", { viewBox: "0 0 24 24", width: iconSize, height: iconSize, fill: "currentColor", "aria-hidden": "true", children: jsx("path", { d: "M9.37 5.51c-.18.64-.27 1.31-.27 1.99 0 4.08 3.32 7.4 7.4 7.4.68 0 1.35-.09 1.99-.27C17.45 17.19 14.93 19 12 19c-3.86 0-7-3.14-7-7 0-2.93 1.81-5.45 4.37-6.49zM12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z" }) }));
8962
+ const defaultDarkIcon = (jsx("svg", { viewBox: "0 0 24 24", width: iconSize, height: iconSize, fill: "currentColor", "aria-hidden": "true", children: jsx("path", { d: "M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41.39.39 1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41.39.39 1.03.39 1.41 0l1.06-1.06z" }) }));
8963
+ return (jsx("button", { type: "button", className: `c-color-mode-toggle c-color-mode-toggle--${size} ${disabled ? 'c-color-mode-toggle--disabled' : ''} ${className}`, onClick: toggleColorMode, disabled: disabled, "aria-label": label, "aria-pressed": colorMode === 'dark', title: title, style: style, children: colorMode === 'light' ? (lightIcon || defaultLightIcon) : (darkIcon || defaultDarkIcon) }));
8922
8964
  };
8923
8965
  ColorModeToggle.displayName = 'ColorModeToggle';
8924
8966