@shohojdhara/atomix 0.2.9 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/atomix.css +309 -105
  3. package/dist/atomix.min.css +3 -5
  4. package/dist/index.d.ts +807 -51
  5. package/dist/index.esm.js +16367 -16405
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +16277 -16330
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.min.js +1 -1
  10. package/dist/index.min.js.map +1 -1
  11. package/dist/themes/applemix.css +309 -105
  12. package/dist/themes/applemix.min.css +5 -7
  13. package/dist/themes/boomdevs.css +202 -10
  14. package/dist/themes/boomdevs.min.css +3 -5
  15. package/dist/themes/esrar.css +309 -105
  16. package/dist/themes/esrar.min.css +4 -6
  17. package/dist/themes/flashtrade.css +310 -105
  18. package/dist/themes/flashtrade.min.css +5 -7
  19. package/dist/themes/mashroom.css +300 -96
  20. package/dist/themes/mashroom.min.css +4 -6
  21. package/dist/themes/shaj-default.css +300 -96
  22. package/dist/themes/shaj-default.min.css +4 -6
  23. package/package.json +1 -1
  24. package/src/components/AtomixGlass/AtomixGlass.test.tsx +21 -32
  25. package/src/components/AtomixGlass/AtomixGlass.tsx +55 -42
  26. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +205 -57
  27. package/src/components/AtomixGlass/GlassFilter.tsx +22 -8
  28. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +221 -0
  29. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -3
  30. package/src/components/AtomixGlass/shader-utils.ts +8 -0
  31. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +319 -100
  32. package/src/components/AtomixGlass/stories/Examples.stories.tsx +601 -105
  33. package/src/components/AtomixGlass/stories/Modes.stories.tsx +30 -12
  34. package/src/components/AtomixGlass/stories/Playground.stories.tsx +173 -38
  35. package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +18 -18
  36. package/src/components/AtomixGlass/stories/shared-components.tsx +27 -5
  37. package/src/components/Breadcrumb/Breadcrumb.tsx +8 -3
  38. package/src/components/Button/Button.tsx +62 -17
  39. package/src/components/Callout/Callout.test.tsx +8 -14
  40. package/src/components/Card/Card.tsx +103 -1
  41. package/src/components/Card/index.ts +3 -2
  42. package/src/components/Footer/Footer.stories.tsx +1 -2
  43. package/src/components/Footer/Footer.tsx +0 -5
  44. package/src/components/Footer/FooterLink.tsx +3 -2
  45. package/src/components/Footer/FooterSection.tsx +0 -7
  46. package/src/components/Icon/index.ts +1 -1
  47. package/src/components/Modal/Modal.stories.tsx +29 -38
  48. package/src/components/Modal/Modal.tsx +4 -4
  49. package/src/components/Navigation/Nav/NavItem.tsx +8 -3
  50. package/src/components/Navigation/SideMenu/SideMenu.tsx +49 -41
  51. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +63 -19
  52. package/src/components/Popover/Popover.tsx +1 -1
  53. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +977 -400
  54. package/src/components/VideoPlayer/VideoPlayer.tsx +1 -6
  55. package/src/lib/composables/shared-mouse-tracker.ts +133 -0
  56. package/src/lib/composables/useAtomixGlass.ts +303 -115
  57. package/src/lib/theme/ThemeManager.integration.test.ts +124 -0
  58. package/src/lib/theme/ThemeManager.stories.tsx +13 -13
  59. package/src/lib/theme/ThemeManager.test.ts +4 -0
  60. package/src/lib/theme/ThemeManager.ts +203 -59
  61. package/src/lib/theme/ThemeProvider.tsx +183 -33
  62. package/src/lib/theme/composeTheme.ts +375 -0
  63. package/src/lib/theme/createTheme.test.ts +475 -0
  64. package/src/lib/theme/createTheme.ts +510 -0
  65. package/src/lib/theme/generateCSSVariables.ts +713 -0
  66. package/src/lib/theme/index.ts +67 -0
  67. package/src/lib/theme/themeUtils.ts +333 -0
  68. package/src/lib/theme/types.ts +337 -8
  69. package/src/lib/theme/useTheme.test.tsx +2 -1
  70. package/src/lib/theme/useTheme.ts +6 -22
  71. package/src/lib/types/components.ts +152 -57
  72. package/src/styles/01-settings/_index.scss +2 -2
  73. package/src/styles/01-settings/_settings.badge.scss +2 -2
  74. package/src/styles/01-settings/_settings.border-radius.scss +1 -1
  75. package/src/styles/01-settings/{_settings.maps.scss → _settings.design-tokens.scss} +163 -49
  76. package/src/styles/01-settings/_settings.modal.scss +1 -1
  77. package/src/styles/01-settings/_settings.spacing.scss +14 -13
  78. package/src/styles/03-generic/_generic.root.scss +131 -50
  79. package/src/styles/05-objects/_objects.block.scss +1 -1
  80. package/src/styles/06-components/_components.atomix-glass.scss +20 -22
  81. package/src/styles/06-components/_components.badge.scss +2 -2
  82. package/src/styles/06-components/_components.button.scss +1 -1
  83. package/src/styles/06-components/_components.callout.scss +1 -1
  84. package/src/styles/06-components/_components.card.scss +74 -2
  85. package/src/styles/06-components/_components.chart.scss +1 -1
  86. package/src/styles/06-components/_components.dropdown.scss +6 -0
  87. package/src/styles/06-components/_components.footer.scss +1 -1
  88. package/src/styles/06-components/_components.list-group.scss +1 -1
  89. package/src/styles/06-components/_components.list.scss +1 -1
  90. package/src/styles/06-components/_components.menu.scss +1 -1
  91. package/src/styles/06-components/_components.messages.scss +1 -1
  92. package/src/styles/06-components/_components.modal.scss +7 -2
  93. package/src/styles/06-components/_components.navbar.scss +1 -1
  94. package/src/styles/06-components/_components.popover.scss +10 -0
  95. package/src/styles/06-components/_components.product-review.scss +1 -1
  96. package/src/styles/06-components/_components.progress.scss +1 -1
  97. package/src/styles/06-components/_components.rating.scss +1 -1
  98. package/src/styles/06-components/_components.spinner.scss +1 -1
  99. package/src/styles/99-utilities/_utilities.background.scss +1 -1
  100. package/src/styles/99-utilities/_utilities.border.scss +1 -1
  101. package/src/styles/99-utilities/_utilities.link.scss +1 -1
  102. package/src/styles/99-utilities/_utilities.text.scss +1 -1
@@ -1,11 +1,32 @@
1
- import React, { useState, useEffect, useRef, forwardRef } from 'react';
1
+ import React, { useState, useEffect, useRef, forwardRef, createContext, useContext } from 'react';
2
2
  import { SideMenuProps } from '../../../lib/types/components';
3
3
  import { useSideMenu } from '../../../lib/composables/useSideMenu';
4
4
  import { Icon } from '../../Icon';
5
5
  import { AtomixGlass } from '../../AtomixGlass/AtomixGlass';
6
+ import useForkRef from '../../../lib/utils/useForkRef';
6
7
  import SideMenuList from './SideMenuList';
7
8
  import SideMenuItem from './SideMenuItem';
8
9
 
10
+ // Context for passing LinkComponent to SideMenuItem children
11
+ const SideMenuContext = createContext<{
12
+ LinkComponent?: React.ComponentType<{
13
+ href?: string;
14
+ to?: string;
15
+ children: React.ReactNode;
16
+ className?: string;
17
+ onClick?: (event: React.MouseEvent) => void;
18
+ target?: string;
19
+ rel?: string;
20
+ 'aria-disabled'?: boolean;
21
+ 'aria-current'?: string;
22
+ tabIndex?: number;
23
+ ref?: React.Ref<HTMLAnchorElement>;
24
+ }>;
25
+ }>({});
26
+
27
+ // Hook to use SideMenu context
28
+ export const useSideMenuContext = () => useContext(SideMenuContext);
29
+
9
30
  /**
10
31
  * SideMenu component provides a collapsible navigation menu with title and menu items.
11
32
  * Automatically collapses on mobile devices and can be toggled via a header button.
@@ -38,6 +59,7 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
38
59
  toggleIcon,
39
60
  id,
40
61
  glass,
62
+ LinkComponent,
41
63
  },
42
64
  ref
43
65
  ) => {
@@ -49,7 +71,6 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
49
71
  generateSideMenuClass,
50
72
  generateWrapperClass,
51
73
  handleToggle,
52
- handleDesktopCollapse,
53
74
  } = useSideMenu({
54
75
  isOpen,
55
76
  onToggle,
@@ -59,6 +80,7 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
59
80
  disabled,
60
81
  });
61
82
 
83
+ // Mobile breakpoint matches md breakpoint (768px)
62
84
  const MOBILE_BREAKPOINT = 768;
63
85
 
64
86
  // Track mobile state
@@ -116,23 +138,23 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
116
138
  });
117
139
  }, [menuItems?.length]);
118
140
 
141
+ // Helper function to update nested wrapper height
142
+ const updateNestedHeight = (index: number, isOpen: boolean) => {
143
+ const wrapper = nestedWrapperRefs.current[index];
144
+ const inner = nestedInnerRefs.current[index];
145
+ if (wrapper && inner) {
146
+ wrapper.style.height = isOpen ? `${inner.scrollHeight}px` : '0px';
147
+ }
148
+ };
149
+
119
150
  // Set initial heights for nested wrappers on mount and when menuItems change
120
151
  useEffect(() => {
121
152
  if (!menuItems?.length) return;
122
153
 
123
154
  const timeoutId = setTimeout(() => {
124
155
  menuItems.forEach((_, index) => {
125
- const wrapper = nestedWrapperRefs.current[index];
126
- const inner = nestedInnerRefs.current[index];
127
156
  const isOpen = nestedItemStates[index] ?? true;
128
-
129
- if (wrapper && inner) {
130
- if (isOpen) {
131
- wrapper.style.height = `${inner.scrollHeight}px`;
132
- } else {
133
- wrapper.style.height = '0px';
134
- }
135
- }
157
+ updateNestedHeight(index, isOpen);
136
158
  });
137
159
  }, 0);
138
160
 
@@ -149,22 +171,12 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
149
171
 
150
172
  Object.keys(nestedItemStates).forEach(key => {
151
173
  const index = Number(key);
152
- const wrapper = nestedWrapperRefs.current[index];
153
- const inner = nestedInnerRefs.current[index];
154
- const isOpen = nestedItemStates[index];
155
-
156
- if (wrapper && inner) {
157
- const frameId = requestAnimationFrame(() => {
158
- if (wrapper && inner) {
159
- if (isOpen) {
160
- wrapper.style.height = `${inner.scrollHeight}px`;
161
- } else {
162
- wrapper.style.height = '0px';
163
- }
164
- }
165
- });
166
- frameIds.push(frameId);
167
- }
174
+ const isOpen = nestedItemStates[index] ?? true;
175
+
176
+ const frameId = requestAnimationFrame(() => {
177
+ updateNestedHeight(index, isOpen);
178
+ });
179
+ frameIds.push(frameId);
168
180
  });
169
181
 
170
182
  return () => {
@@ -172,15 +184,8 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
172
184
  };
173
185
  }, [nestedItemStates, menuItems?.length]);
174
186
 
175
- // Combine refs
176
- const combinedRef = (node: HTMLDivElement | null) => {
177
- (sideMenuRef as React.MutableRefObject<HTMLDivElement | null>).current = node;
178
- if (typeof ref === 'function') {
179
- ref(node);
180
- } else if (ref) {
181
- (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
182
- }
183
- };
187
+ // Combine refs using utility
188
+ const combinedRef = useForkRef(sideMenuRef, ref);
184
189
 
185
190
  const sideMenuClass = generateSideMenuClass({
186
191
  className,
@@ -230,8 +235,9 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
230
235
  id={id ? `${id}-content` : undefined}
231
236
  aria-hidden={shouldShowToggler ? !isOpenState : false}
232
237
  >
233
- <div ref={innerRef} className="c-side-menu__inner">
234
- {children && children}
238
+ <SideMenuContext.Provider value={{ LinkComponent }}>
239
+ <div ref={innerRef} className="c-side-menu__inner">
240
+ {children}
235
241
  {menuItems?.map((item, index) => {
236
242
  const isNestedItemOpen = nestedItemStates[index] ?? true;
237
243
  const hasItems = item.items && item.items.length > 0;
@@ -302,6 +308,7 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
302
308
  active={subItem.active}
303
309
  disabled={subItem.disabled}
304
310
  icon={subItem.icon}
311
+ LinkComponent={LinkComponent}
305
312
  >
306
313
  {subItem.title}
307
314
  </SideMenuItem>
@@ -313,7 +320,8 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
313
320
  </div>
314
321
  );
315
322
  })}
316
- </div>
323
+ </div>
324
+ </SideMenuContext.Provider>
317
325
  </div>
318
326
  </>
319
327
  );
@@ -330,7 +338,7 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
330
338
  <AtomixGlass {...glassProps}>
331
339
  <div
332
340
  ref={combinedRef}
333
- className={sideMenuClass + ' c-side-menu--glass'}
341
+ className={`${sideMenuClass} c-side-menu--glass`}
334
342
  id={id}
335
343
  style={style}
336
344
  >
@@ -1,6 +1,7 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import { SideMenuItemProps } from '../../../lib/types/components';
3
3
  import { useSideMenuItem } from '../../../lib/composables/useSideMenu';
4
+ import { useSideMenuContext } from './SideMenu';
4
5
 
5
6
  /**
6
7
  * SideMenuItem component represents a single navigation item in a side menu.
@@ -39,10 +40,14 @@ export const SideMenuItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Si
39
40
  className = '',
40
41
  target,
41
42
  rel,
42
- LinkComponent,
43
+ LinkComponent: LinkComponentProp,
43
44
  },
44
45
  ref
45
46
  ) => {
47
+ const { LinkComponent: LinkComponentFromContext } = useSideMenuContext();
48
+ // Use LinkComponent from props first, then fall back to context
49
+ const LinkComponent = LinkComponentProp ?? LinkComponentFromContext;
50
+
46
51
  const { generateSideMenuItemClass, handleClick } = useSideMenuItem({
47
52
  active,
48
53
  disabled,
@@ -51,26 +56,65 @@ export const SideMenuItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Si
51
56
 
52
57
  const itemClass = generateSideMenuItemClass();
53
58
 
54
- const linkProps = {
55
- ref: ref as React.Ref<HTMLAnchorElement>,
56
- href: disabled ? undefined : href,
57
- className: itemClass,
58
- onClick: handleClick(onClick),
59
- 'aria-disabled': disabled,
60
- 'aria-current': (active ? 'page' : undefined) as React.AriaAttributes['aria-current'],
61
- target: target,
62
- rel: rel,
63
- tabIndex: disabled ? -1 : 0,
64
- };
65
-
66
59
  // Render as link if href is provided
67
60
  if (href) {
68
- return LinkComponent ? (
69
- <LinkComponent {...linkProps}>
70
- {icon && <span className="c-side-menu__link-icon">{icon}</span>}
71
- <span className="c-side-menu__link-text">{children}</span>
72
- </LinkComponent>
73
- ) : (
61
+ // When using a custom LinkComponent (e.g., Next.js Link, React Router Link)
62
+ if (LinkComponent) {
63
+ const Component = LinkComponent;
64
+
65
+ // Build link props - support both 'href' (Next.js) and 'to' (React Router)
66
+ // The Link component will use whichever prop it needs
67
+ const linkProps: {
68
+ ref?: React.Ref<HTMLAnchorElement>;
69
+ className?: string;
70
+ onClick?: (event: React.MouseEvent) => void;
71
+ 'aria-disabled'?: boolean;
72
+ 'aria-current'?: string;
73
+ target?: string;
74
+ rel?: string;
75
+ tabIndex?: number;
76
+ href?: string;
77
+ to?: string;
78
+ } = {
79
+ ref: ref as React.Ref<HTMLAnchorElement>,
80
+ className: itemClass,
81
+ onClick: disabled
82
+ ? (e: React.MouseEvent) => {
83
+ e.preventDefault();
84
+ }
85
+ : onClick,
86
+ 'aria-disabled': disabled,
87
+ 'aria-current': active ? 'page' : undefined,
88
+ target: target,
89
+ rel: rel,
90
+ tabIndex: disabled ? -1 : 0,
91
+ // Support both Next.js (href) and React Router (to) Link components
92
+ // Pass both props - the Link component will use whichever it needs
93
+ ...(disabled ? {} : { href, to: href }),
94
+ };
95
+
96
+ return (
97
+ <Component {...linkProps}>
98
+ {icon && <span className="c-side-menu__link-icon">{icon}</span>}
99
+ <span className="c-side-menu__link-text">{children}</span>
100
+ </Component>
101
+ );
102
+ }
103
+
104
+ // Regular anchor tag
105
+ const linkProps = {
106
+ ref: ref as React.Ref<HTMLAnchorElement>,
107
+ href: disabled ? undefined : href,
108
+ className: itemClass,
109
+ onClick: handleClick(onClick),
110
+ 'aria-disabled': disabled,
111
+ 'aria-current': (active ? 'page' : undefined) as React.AriaAttributes['aria-current'],
112
+ target: target,
113
+ rel: rel,
114
+ tabIndex: disabled ? -1 : 0,
115
+ };
116
+
117
+ return (
74
118
  <a {...linkProps}>
75
119
  {icon && <span className="c-side-menu__link-icon">{icon}</span>}
76
120
  <span className="c-side-menu__link-text">{children}</span>
@@ -94,7 +94,7 @@ export const Popover: React.FC<PopoverProps> = ({
94
94
  glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
95
95
 
96
96
  return (
97
- <AtomixGlass {...glassProps}>
97
+ <AtomixGlass {...glassProps} style={style}>
98
98
  <div className="c-popover__content">
99
99
  <div className="c-popover__content-inner">{content}</div>
100
100
  </div>