@donotdev/ui 0.0.12 → 0.0.14

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 (159) hide show
  1. package/dist/components/auth/AuthMenu.d.ts.map +1 -1
  2. package/dist/components/auth/AuthMenu.js +19 -20
  3. package/dist/components/common/FeatureCard.d.ts +3 -1
  4. package/dist/components/common/FeatureCard.d.ts.map +1 -1
  5. package/dist/components/common/FeatureCard.js +3 -3
  6. package/dist/components/common/ProgressBar.js +2 -2
  7. package/dist/components/common/RedirectOverlay.js +1 -1
  8. package/dist/components/common/TechBento.d.ts +14 -2
  9. package/dist/components/common/TechBento.d.ts.map +1 -1
  10. package/dist/components/common/TechBento.js +8 -9
  11. package/dist/components/cookie-consent/CookieConsent.d.ts.map +1 -1
  12. package/dist/components/cookie-consent/CookieConsent.js +6 -7
  13. package/dist/components/layout/GameContainer.d.ts +24 -8
  14. package/dist/components/layout/GameContainer.d.ts.map +1 -1
  15. package/dist/components/layout/GameContainer.js +21 -3
  16. package/dist/components/layout/GameFlow.d.ts.map +1 -1
  17. package/dist/components/layout/GameFlow.js +27 -11
  18. package/dist/components/layout/components/DropdownNavigation.d.ts.map +1 -1
  19. package/dist/components/layout/components/DropdownNavigation.js +3 -12
  20. package/dist/components/layout/components/FloatingLanguageSwitcher.js +1 -1
  21. package/dist/components/layout/components/Notifications.d.ts +1 -3
  22. package/dist/components/layout/components/Notifications.d.ts.map +1 -1
  23. package/dist/components/layout/components/Notifications.js +4 -2
  24. package/dist/components/layout/components/header/AppBranding.d.ts.map +1 -1
  25. package/dist/components/layout/components/header/AppBranding.js +2 -1
  26. package/dist/components/layout/components/header/AppIcon.d.ts.map +1 -1
  27. package/dist/components/layout/components/header/AppIcon.js +5 -2
  28. package/dist/components/layout/components/header/CacheSettings.d.ts.map +1 -1
  29. package/dist/components/layout/components/header/CacheSettings.js +4 -2
  30. package/dist/components/layout/components/header/HeaderNavigation.d.ts +6 -0
  31. package/dist/components/layout/components/header/HeaderNavigation.d.ts.map +1 -1
  32. package/dist/components/layout/components/header/HeaderNavigation.js +12 -2
  33. package/dist/components/license/LicenseWatermark.d.ts.map +1 -1
  34. package/dist/components/license/LicenseWatermark.js +3 -1
  35. package/dist/crud/components/CrudCardLink.d.ts +17 -0
  36. package/dist/crud/components/CrudCardLink.d.ts.map +1 -0
  37. package/dist/crud/components/CrudCardLink.js +17 -0
  38. package/dist/crud/components/EntityCardList.d.ts.map +1 -1
  39. package/dist/crud/components/EntityCardList.js +32 -81
  40. package/dist/crud/components/EntityDisplayRenderer.d.ts +1 -1
  41. package/dist/crud/components/EntityDisplayRenderer.d.ts.map +1 -1
  42. package/dist/crud/components/EntityDisplayRenderer.js +8 -4
  43. package/dist/crud/components/EntityFormRenderer.d.ts +1 -1
  44. package/dist/crud/components/EntityFormRenderer.d.ts.map +1 -1
  45. package/dist/crud/components/EntityFormRenderer.js +29 -18
  46. package/dist/crud/components/EntityList.d.ts +1 -1
  47. package/dist/crud/components/EntityList.d.ts.map +1 -1
  48. package/dist/crud/components/EntityList.js +8 -10
  49. package/dist/crud/components/EntityRecommendations.d.ts +28 -0
  50. package/dist/crud/components/EntityRecommendations.d.ts.map +1 -0
  51. package/dist/crud/components/EntityRecommendations.js +31 -0
  52. package/dist/crud/components/Form.js +1 -1
  53. package/dist/crud/components/index.d.ts +2 -1
  54. package/dist/crud/components/index.d.ts.map +1 -1
  55. package/dist/crud/components/index.js +1 -0
  56. package/dist/index.js +4 -4
  57. package/dist/internal/common/RouteErrorFallback.d.ts.map +1 -1
  58. package/dist/internal/common/RouteErrorFallback.js +3 -3
  59. package/dist/internal/devtools/components/AuthDebugButton.js +1 -1
  60. package/dist/internal/devtools/components/ConfigTab.js +1 -1
  61. package/dist/internal/devtools/components/CookieTab.js +1 -1
  62. package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -1
  63. package/dist/internal/devtools/components/DesignTab.js +5 -4
  64. package/dist/internal/devtools/components/LayoutReset.d.ts.map +1 -1
  65. package/dist/internal/devtools/components/LayoutReset.js +2 -0
  66. package/dist/internal/devtools/components/StoresTab.d.ts.map +1 -1
  67. package/dist/internal/devtools/components/StoresTab.js +5 -2
  68. package/dist/internal/devtools/utils/envVarDiscovery.d.ts +1 -0
  69. package/dist/internal/devtools/utils/envVarDiscovery.d.ts.map +1 -1
  70. package/dist/internal/devtools/utils/envVarDiscovery.js +5 -0
  71. package/dist/internal/devtools/utils/virtualModuleInspector.d.ts.map +1 -1
  72. package/dist/internal/devtools/utils/virtualModuleInspector.js +27 -21
  73. package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
  74. package/dist/internal/initializers/BaseStoresInitializer.js +30 -6
  75. package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
  76. package/dist/internal/layout/components/AutoMetaTags.js +10 -8
  77. package/dist/internal/layout/components/FontPreloadLinks.d.ts +16 -0
  78. package/dist/internal/layout/components/FontPreloadLinks.d.ts.map +1 -0
  79. package/dist/internal/layout/components/FontPreloadLinks.js +32 -0
  80. package/dist/internal/layout/components/PerformanceHints.d.ts +7 -12
  81. package/dist/internal/layout/components/PerformanceHints.d.ts.map +1 -1
  82. package/dist/internal/layout/components/PerformanceHints.js +8 -12
  83. package/dist/internal/layout/components/footer/useLegalLinks.d.ts +6 -5
  84. package/dist/internal/layout/components/footer/useLegalLinks.d.ts.map +1 -1
  85. package/dist/internal/layout/components/footer/useLegalLinks.js +6 -2
  86. package/dist/internal/layout/zones/DnDevFooter.d.ts +6 -0
  87. package/dist/internal/layout/zones/DnDevFooter.d.ts.map +1 -1
  88. package/dist/internal/layout/zones/DnDevFooter.js +10 -4
  89. package/dist/internal/layout/zones/DnDevHeader.d.ts +7 -0
  90. package/dist/internal/layout/zones/DnDevHeader.d.ts.map +1 -1
  91. package/dist/internal/layout/zones/DnDevHeader.js +7 -0
  92. package/dist/internal/layout/zones/DnDevMergedBar.d.ts +7 -0
  93. package/dist/internal/layout/zones/DnDevMergedBar.d.ts.map +1 -1
  94. package/dist/internal/layout/zones/DnDevMergedBar.js +10 -1
  95. package/dist/internal/layout/zones/DnDevSidebar.d.ts +4 -0
  96. package/dist/internal/layout/zones/DnDevSidebar.d.ts.map +1 -1
  97. package/dist/internal/layout/zones/DnDevSidebar.js +13 -1
  98. package/dist/next.d.ts +1 -0
  99. package/dist/next.d.ts.map +1 -1
  100. package/dist/next.js +1 -0
  101. package/dist/routing/404.js +3 -3
  102. package/dist/routing/AuthGuard.d.ts +1 -1
  103. package/dist/routing/AuthGuard.d.ts.map +1 -1
  104. package/dist/routing/AuthGuard.js +3 -1
  105. package/dist/routing/AuthGuardFallback.js +2 -2
  106. package/dist/routing/GoTo.d.ts.map +1 -1
  107. package/dist/routing/GoTo.js +3 -1
  108. package/dist/routing/GoToDialog.d.ts.map +1 -1
  109. package/dist/routing/GoToDialog.js +2 -7
  110. package/dist/routing/GoToInput.d.ts +0 -3
  111. package/dist/routing/GoToInput.d.ts.map +1 -1
  112. package/dist/routing/GoToInput.js +4 -2
  113. package/dist/routing/Link.js +1 -1
  114. package/dist/routing/NavigationItem.d.ts +29 -7
  115. package/dist/routing/NavigationItem.d.ts.map +1 -1
  116. package/dist/routing/NavigationItem.js +22 -6
  117. package/dist/routing/hooks/hooks.next.js +1 -1
  118. package/dist/routing/hooks/hooks.vite.js +1 -1
  119. package/dist/routing/hooks/useRedirectGuard.next.d.ts.map +1 -1
  120. package/dist/routing/hooks/useRedirectGuard.next.js +9 -8
  121. package/dist/routing/hooks/useRedirectGuard.vite.d.ts.map +1 -1
  122. package/dist/routing/hooks/useRedirectGuard.vite.js +9 -8
  123. package/dist/routing/hooks/useSearchParams.next.d.ts +18 -1
  124. package/dist/routing/hooks/useSearchParams.next.d.ts.map +1 -1
  125. package/dist/routing/hooks/useSearchParams.next.js +16 -0
  126. package/dist/routing/hooks/useSearchParams.vite.d.ts +16 -0
  127. package/dist/routing/hooks/useSearchParams.vite.d.ts.map +1 -1
  128. package/dist/routing/hooks/useSearchParams.vite.js +17 -1
  129. package/dist/routing/index.d.ts.map +1 -1
  130. package/dist/routing/index.js +2 -0
  131. package/dist/routing/useNavigation.d.ts +30 -0
  132. package/dist/routing/useNavigation.d.ts.map +1 -1
  133. package/dist/routing/useNavigation.js +40 -3
  134. package/dist/routing/useRouteDiscovery.d.ts +2 -2
  135. package/dist/routing/useRouteDiscovery.d.ts.map +1 -1
  136. package/dist/routing/useRouteDiscovery.js +10 -4
  137. package/dist/styles/index.css +366 -120
  138. package/dist/utils/index.d.ts +1 -0
  139. package/dist/utils/index.d.ts.map +1 -1
  140. package/dist/utils/index.js +1 -0
  141. package/dist/utils/sanitizeSvg.d.ts +13 -0
  142. package/dist/utils/sanitizeSvg.d.ts.map +1 -0
  143. package/dist/utils/sanitizeSvg.js +47 -0
  144. package/dist/utils/useBillingVisibility.d.ts.map +1 -1
  145. package/dist/utils/useBillingVisibility.js +0 -7
  146. package/dist/utils/useCrudSafe.d.ts +0 -2
  147. package/dist/utils/useCrudSafe.d.ts.map +1 -1
  148. package/dist/utils/useFormStoreSafe.d.ts +3 -1
  149. package/dist/utils/useFormStoreSafe.d.ts.map +1 -1
  150. package/dist/utils/useFormStoreSafe.js +4 -5
  151. package/dist/vite-routing/AppRoutes.d.ts +19 -8
  152. package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
  153. package/dist/vite-routing/AppRoutes.js +0 -3
  154. package/package.json +15 -11
  155. package/assets/fonts/fonts.css +0 -206
  156. package/dist/dndev.css +0 -10673
  157. package/dist/routing/Navigate.d.ts +0 -10
  158. package/dist/routing/Navigate.d.ts.map +0 -1
  159. package/dist/routing/Navigate.js +0 -10
@@ -1 +1 @@
1
- {"version":3,"file":"AuthMenu.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthMenu.tsx"],"names":[],"mappings":"AA4EA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAML,OAAO,EACR,MAAM,sBAAsB,CAAC;AAc9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAqE3C;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IAEjD,sBAAsB;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAEnC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAsBD,eAAO,MAAM,QAAQ,GAAI,iFAOtB,aAAa,mDA0Of,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"AuthMenu.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthMenu.tsx"],"names":[],"mappings":"AA4EA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAML,OAAO,EACR,MAAM,sBAAsB,CAAC;AAc9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AA8D3C;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IAEjD,sBAAsB;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAEnC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAsBD,eAAO,MAAM,QAAQ,GAAI,iFAOtB,aAAa,mDA0Of,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -102,18 +102,10 @@ const ConfirmDeleteDialog = lazy(async () => {
102
102
  }
103
103
  });
104
104
  // Graceful degradation for useDeleteAccount hook
105
- let realUseDeleteAccount = null;
106
- // Preload useDeleteAccount (non-blocking)
107
- if (isClient()) {
108
- import('@donotdev/auth')
109
- .then((module) => {
110
- realUseDeleteAccount = module.useDeleteAccount;
111
- })
112
- .catch(() => { });
113
- }
114
- // Fallback hook that matches useDeleteAccount's hook structure
115
- function useDeleteAccountFallback() {
116
- // Always call useState to maintain hook order (matches real hook structure)
105
+ // Resolved at module level (not render level) to avoid Rules of Hooks violation.
106
+ // Once set, useDeleteAccount never changes identity during the app lifecycle.
107
+ let useDeleteAccount = () => {
108
+ // Fallback: always call useState to maintain stable hook order
117
109
  const [showConfirmDialog] = React.useState(false);
118
110
  const [showPasswordDialog] = React.useState(false);
119
111
  const [isDeleting] = React.useState(false);
@@ -127,13 +119,20 @@ function useDeleteAccountFallback() {
127
119
  confirmDelete: async () => { },
128
120
  cancel: () => { },
129
121
  };
130
- }
131
- // Hook wrapper that uses real hook if available, otherwise fallback
132
- function useDeleteAccountHook() {
133
- if (realUseDeleteAccount) {
134
- return realUseDeleteAccount();
135
- }
136
- return useDeleteAccountFallback();
122
+ };
123
+ // Preload useDeleteAccount (non-blocking)
124
+ // The hook reference is swapped before the first render in practice,
125
+ // but if the import resolves after first render, the fallback remains
126
+ // stable for that session to avoid hook order changes mid-lifecycle.
127
+ if (isClient()) {
128
+ import('@donotdev/auth')
129
+ .then((module) => {
130
+ useDeleteAccount = module.useDeleteAccount;
131
+ })
132
+ .catch((e) => {
133
+ if (process.env.NODE_ENV === 'development')
134
+ console.warn('Failed to load @donotdev/auth:', e);
135
+ });
137
136
  }
138
137
  /**
139
138
  * Resolves Lucide icon component from string name or component reference
@@ -167,7 +166,7 @@ export const AuthMenu = ({ loginPath, display = DISPLAY.AUTO, 'no-tooltip': noTo
167
166
  const profilePath = authConfig.profilePath;
168
167
  const configMenuItems = authConfig.authMenuItems || [];
169
168
  // Account deletion flow - managed by useDeleteAccount hook
170
- const deletion = useDeleteAccountHook();
169
+ const deletion = useDeleteAccount();
171
170
  /**
172
171
  * Get user display name with fallbacks
173
172
  */
@@ -13,6 +13,8 @@ export interface FeatureCardProps extends Omit<CardProps, 'content' | 'href' | '
13
13
  content?: CardContent;
14
14
  /** Route path - enables routing via Link */
15
15
  href?: string;
16
+ /** When true, apply clickable styling (cursor, hover) even without href/onClick. Use when card is a dialog trigger. */
17
+ clickable?: boolean;
16
18
  }
17
19
  /**
18
20
  * FeatureCard - Card wrapper with content array and routing
@@ -21,6 +23,6 @@ export interface FeatureCardProps extends Omit<CardProps, 'content' | 'href' | '
21
23
  * Uses Card component internally.
22
24
  * Routing via Link when href provided.
23
25
  */
24
- declare const FeatureCard: ({ icon, title, subtitle, content, href, variant, elevated, onClick, className, footer, style, ...cardProps }: FeatureCardProps) => import("react/jsx-runtime").JSX.Element;
26
+ declare const FeatureCard: ({ icon, title, subtitle, content, href, variant, elevated, onClick, className, footer, style, clickable, ...cardProps }: FeatureCardProps) => import("react/jsx-runtime").JSX.Element;
25
27
  export default FeatureCard;
26
28
  //# sourceMappingURL=FeatureCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureCard.d.ts","sourceRoot":"","sources":["../../../src/components/common/FeatureCard.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIhF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE7C,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,SAAS,EACT,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CACvD;IACC,kDAAkD;IAClD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,QAAA,MAAM,WAAW,GAAI,8GAalB,gBAAgB,4CAmIlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"FeatureCard.d.ts","sourceRoot":"","sources":["../../../src/components/common/FeatureCard.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIhF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE7C,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,SAAS,EACT,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CACvD;IACC,kDAAkD;IAClD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uHAAuH;IACvH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,WAAW,GAAI,yHAclB,gBAAgB,4CA8HlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -21,7 +21,7 @@ import { Link } from '../../routing';
21
21
  * Uses Card component internally.
22
22
  * Routing via Link when href provided.
23
23
  */
24
- const FeatureCard = ({ icon, title, subtitle, content, href, variant, elevated, onClick, className, footer, style, ...cardProps }) => {
24
+ const FeatureCard = ({ icon, title, subtitle, content, href, variant, elevated, onClick, className, footer, style, clickable, ...cardProps }) => {
25
25
  const contentNode = renderCardContent(content);
26
26
  // Fixed height constants for consistent text sizing (2 rows each)
27
27
  const titleRowHeight = `calc(var(--font-size-lg) * var(--line-height) * 2 + var(--gap-md))`;
@@ -56,8 +56,8 @@ const FeatureCard = ({ icon, title, subtitle, content, href, variant, elevated,
56
56
  margin: 0,
57
57
  };
58
58
  // Build title with icon if provided
59
- const titleContent = icon ? (_jsxs(Stack, { direction: "row", align: "center", gap: "medium", style: { width: '100%' }, children: [_jsx(IconBox, { icon: icon }), _jsx(Text, { as: "div", level: "h3", style: titleStyle, children: title })] })) : (_jsx(Text, { as: "div", level: "h3", style: titleStyle, children: title }));
60
- const card = (_jsx(Card, { variant: variant, elevated: elevated, onClick: onClick, className: className, "data-clickable": href || onClick ? 'true' : undefined, style: {
59
+ const titleContent = icon ? (_jsxs(Stack, { direction: "row", align: "center", style: { width: '100%' }, children: [_jsx(IconBox, { icon: icon }), _jsx(Text, { as: "div", level: "h3", style: titleStyle, children: title })] })) : (_jsx(Text, { as: "div", level: "h3", style: titleStyle, children: title }));
60
+ const card = (_jsx(Card, { variant: variant, elevated: elevated, onClick: onClick, className: className, "data-clickable": href || onClick || clickable ? 'true' : undefined, style: {
61
61
  paddingInlineStart: 'var(--gap-md)',
62
62
  paddingInlineEnd: 'var(--gap-md)',
63
63
  gap: 'var(--gap-md)',
@@ -67,8 +67,8 @@ const ProgressBar = ({ isActive = false, progress: controlledProgress, useFakePr
67
67
  }
68
68
  return (_jsx("div", { className: cn(className), style: {
69
69
  position: 'fixed',
70
- left: 0,
71
- right: 0,
70
+ insetInlineStart: 0,
71
+ insetInlineEnd: 0,
72
72
  zIndex: 9999,
73
73
  height: '4px',
74
74
  backgroundColor: 'transparent',
@@ -219,7 +219,7 @@ export function RedirectOverlay() {
219
219
  textAlign: 'center',
220
220
  maxWidth: '400px',
221
221
  padding: 'var(--gap-lg)',
222
- }, children: [_jsxs(Stack, { direction: "row", gap: "medium", align: "center", children: [IconComponent && (_jsx(IconComponent, { style: {
222
+ }, children: [_jsxs(Stack, { direction: "row", align: "center", children: [IconComponent && (_jsx(IconComponent, { style: {
223
223
  width: '1.5rem',
224
224
  height: '1.5rem',
225
225
  color: 'var(--primary)',
@@ -1,4 +1,4 @@
1
- import type { BentoColumns, BentoGap, CardVariant, ResponsiveCols } from '@donotdev/components';
1
+ import type { BentoColumns, BentoGap, CardVariant, ResponsiveCols, Tone } from '@donotdev/components';
2
2
  import { type TechKey } from '../../data/techLogos';
3
3
  export type TechBentoProps = {
4
4
  title?: string;
@@ -22,8 +22,20 @@ export type TechBentoProps = {
22
22
  columns?: BentoColumns;
23
23
  gap?: BentoGap;
24
24
  separator?: boolean;
25
+ /** Tone system for background colors (matches Section/CallToAction) */
26
+ tone?: Tone;
27
+ /** Content alignment @default 'center' */
28
+ align?: 'start' | 'center' | 'end';
29
+ /** Whether the section is collapsible */
30
+ collapsible?: boolean;
31
+ /** Controlled open state (when collapsible) */
32
+ open?: boolean;
33
+ /** Callback when open state changes (when collapsible) */
34
+ onOpenChange?: (open: boolean) => void;
35
+ /** Default open state (uncontrolled, when collapsible) */
36
+ defaultOpen?: boolean;
25
37
  className?: string;
26
38
  };
27
- export declare function TechBento({ title, techs, cols, columns, gap, separator, className, }: TechBentoProps): import("react/jsx-runtime").JSX.Element;
39
+ export declare function TechBento({ title, techs, cols, columns, gap, separator, tone, align, collapsible, open, onOpenChange, defaultOpen, className, }: TechBentoProps): import("react/jsx-runtime").JSX.Element;
28
40
  export default TechBento;
29
41
  //# sourceMappingURL=TechBento.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TechBento.d.ts","sourceRoot":"","sources":["../../../src/components/common/TechBento.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAI/D,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,OAAO,CAAC;QACd,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC3C,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,CAAC,CAAC;IACH;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAwCF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,IAAQ,EACR,OAAO,EACP,GAAc,EACd,SAAiB,EACjB,SAAS,GACV,EAAE,cAAc,2CAsDhB;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"TechBento.d.ts","sourceRoot":"","sources":["../../../src/components/common/TechBento.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,cAAc,EACd,IAAI,EACL,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAK/D,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,OAAO,CAAC;QACd,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC3C,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,CAAC,CAAC;IACH;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uEAAuE;IACvE,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAwCF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,IAAQ,EACR,OAAO,EACP,GAAc,EACd,SAAiB,EACjB,IAAiB,EACjB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,SAAS,GACV,EAAE,cAAc,2CA4DhB;AAED,eAAe,SAAS,CAAC"}
@@ -1,18 +1,19 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // packages/ui/src/components/common/TechBento.tsx
3
3
  import { useState } from 'react';
4
- import { Bento, Card, Section, Stack, Text, cn } from '@donotdev/components';
4
+ import { Bento, Card, Section, Stack, Text, TONE, cn } from '@donotdev/components';
5
5
  import { techLogos } from '../../data/techLogos';
6
+ import { sanitizeSvg } from '../../utils/sanitizeSvg';
6
7
  function TechCard({ techKey, variant, }) {
7
8
  const logo = techLogos[techKey];
8
9
  const [isHovered, setIsHovered] = useState(false);
9
10
  if (!logo)
10
11
  return null;
11
- const svgContent = logo.svg.replace('data:image/svg+xml,', '');
12
- const decodedSvg = decodeURIComponent(svgContent);
12
+ const rawSvg = decodeURIComponent(logo.svg.replace('data:image/svg+xml,', ''));
13
+ const decodedSvg = sanitizeSvg(rawSvg);
13
14
  return (_jsx(Card, { variant: variant, className: "dndev-tech-card", style: { '--tech-color': logo.color }, "data-hover": isHovered, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: _jsxs(Stack, { direction: "column", align: "center", gap: "tight", children: [_jsx("div", { className: "dndev-tech-card-logo", "data-tech": techKey, dangerouslySetInnerHTML: { __html: decodedSvg } }), _jsx(Text, { as: "span", level: "small", children: logo.name })] }) }));
14
15
  }
15
- export function TechBento({ title, techs, cols = 3, columns, gap = 'medium', separator = false, className, }) {
16
+ export function TechBento({ title, techs, cols = 3, columns, gap = 'medium', separator = false, tone = TONE.GHOST, align, collapsible, open, onOpenChange, defaultOpen, className, }) {
16
17
  // Convert Grid's cols format to Bento's columns format
17
18
  // Grid: [mobile, tablet, laptop, desktop]
18
19
  // Bento: { mobile, tablet, desktop, wide }
@@ -47,10 +48,8 @@ export function TechBento({ title, techs, cols = 3, columns, gap = 'medium', sep
47
48
  content: _jsx(TechCard, { techKey: tech.name, variant: tech.variant }),
48
49
  span: getSpan(tech.size),
49
50
  }));
50
- const bento = (_jsx(Bento, { items: items, columns: bentoColumns, gap: gap, className: className, ariaLabel: "Technology stack" }));
51
- if (title) {
52
- return (_jsx(Section, { title: title, separator: separator, className: "dndev-tech-bento", children: _jsx("div", { className: "dndev-tech-bento-grid", children: bento }) }));
53
- }
54
- return _jsx("div", { className: cn('dndev-tech-bento', className), children: bento });
51
+ const bento = (_jsx(Bento, { items: items, columns: bentoColumns, gap: gap, ariaLabel: "Technology stack" }));
52
+ // Always use Section - TechBento is a Section with a Bento grid
53
+ return (_jsx(Section, { title: title, separator: separator, tone: tone, align: align, collapsible: collapsible, open: open, onOpenChange: onOpenChange, defaultOpen: defaultOpen, className: cn('dndev-tech-bento', className), children: _jsx("div", { className: "dndev-tech-bento-grid", children: bento }) }));
55
54
  }
56
55
  export default TechBento;
@@ -1 +1 @@
1
- {"version":3,"file":"CookieConsent.d.ts","sourceRoot":"","sources":["../../../src/components/cookie-consent/CookieConsent.tsx"],"names":[],"mappings":"AA6BA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,aAAa,CAAC,EACrB,QAAmB,EACnB,YAAmB,EACnB,YAA8C,EAC9C,SAAc,GACf,EAAE,kBAAkB,kDAuUpB;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"CookieConsent.d.ts","sourceRoot":"","sources":["../../../src/components/cookie-consent/CookieConsent.tsx"],"names":[],"mappings":"AA6BA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,aAAa,CAAC,EACrB,QAAmB,EACnB,YAAmB,EACnB,YAA8C,EAC9C,SAAc,GACf,EAAE,kBAAkB,kDAqUpB;AAED,eAAe,aAAa,CAAC"}
@@ -14,7 +14,6 @@ function CookieConsent({ position = 'bottom', showBranding = true, brandingText
14
14
  const declineAll = useConsent('declineAll');
15
15
  const updateCategory = useConsent('updateCategory');
16
16
  const storeShowBanner = useConsent('showBanner');
17
- const hideBanner = useConsent('showCookieBanner');
18
17
  const { t } = useTranslation('cookies');
19
18
  const [showPreferences, setShowPreferences] = useState(false);
20
19
  const [showBanner, setShowBanner] = useState(!hasConsented || storeShowBanner);
@@ -141,14 +140,14 @@ function CookieConsent({ position = 'bottom', showBranding = true, brandingText
141
140
  declineAll();
142
141
  setShowBanner(false);
143
142
  };
144
- const bannerContent = (_jsxs(Stack, { gap: "medium", children: [_jsx(Text, { as: "p", variant: "muted", level: "small", children: t('cookieBannerDescription') }), hasOptionalCategories && (_jsx(Accordion, { type: "single", collapsible: true, value: showPreferences ? 'preferences' : '', onValueChange: (value) => setShowPreferences(value === 'preferences'), items: [
143
+ const bannerContent = (_jsxs(Stack, { children: [_jsx(Text, { as: "p", variant: "muted", level: "small", children: t('cookieBannerDescription') }), hasOptionalCategories && (_jsx(Accordion, { type: "single", collapsible: true, value: showPreferences ? 'preferences' : '', onValueChange: (value) => setShowPreferences(value === 'preferences'), items: [
145
144
  {
146
145
  value: 'preferences',
147
146
  trigger: (_jsxs(Stack, { direction: "row", align: "center", gap: "tight", children: [_jsx(Settings, { className: "dndev-size-md" }), t('customize')] })),
148
- content: (_jsx(Stack, { gap: "medium", children: categoryDefs.map((cat) => {
147
+ content: (_jsx(Stack, { children: categoryDefs.map((cat) => {
149
148
  const Icon = cat.icon;
150
149
  const enabled = preferenceCategories[cat.id] ?? false;
151
- return (_jsx(Card, { content: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "medium", children: [_jsxs(Stack, { direction: "row", align: "start", gap: "tight", style: { flex: 1 }, children: [_jsx(Icon, { className: "dndev-size-md", style: {
150
+ return (_jsx(Card, { content: _jsxs(Stack, { direction: "row", align: "center", justify: "between", children: [_jsxs(Stack, { direction: "row", align: "start", gap: "tight", style: { flex: 1 }, children: [_jsx(Icon, { className: "dndev-size-md", style: {
152
151
  color: 'var(--primary)',
153
152
  marginTop: '0.125rem',
154
153
  } }), _jsxs(Stack, { gap: "tight", children: [_jsx(Text, { as: "span", level: "body", style: { fontWeight: 600 }, children: cat.title }), _jsx(Text, { as: "span", variant: "muted", level: "small", children: cat.description }), cat.examples && (_jsx(Text, { as: "span", variant: "muted", level: "small", style: { fontStyle: 'italic' }, children: cat.examples }))] })] }), cat.locked ? (_jsx(Text, { as: "span", variant: "muted", level: "small", children: t('alwaysOn') })) : (_jsx(Switch, { checked: enabled, onCheckedChange: (val) => setPreferenceCategories((prev) => ({
@@ -161,10 +160,10 @@ function CookieConsent({ position = 'bottom', showBranding = true, brandingText
161
160
  const bannerFooter = showPreferences ? (_jsxs(Stack, { direction: "row", gap: "tight", style: { width: '100%' }, children: [_jsx(Button, { onClick: handleSave, variant: BUTTON_VARIANT.DEFAULT, style: { flex: 1 }, children: t('savePreferences', 'Save Preferences') }), _jsx(Button, { onClick: () => setShowPreferences(false), variant: BUTTON_VARIANT.OUTLINE, style: { flex: 1 }, children: t('form.cancel', 'Cancel') })] })) : (_jsxs(Stack, { direction: "row", gap: "tight", style: { width: '100%' }, children: [_jsx(Button, { onClick: handleAcceptAll, variant: BUTTON_VARIANT.DEFAULT, style: { flex: 1 }, children: t('acceptAll') }), hasOptionalCategories && (_jsx(Button, { onClick: handleDeclineAll, variant: BUTTON_VARIANT.OUTLINE, style: { flex: 1 }, children: t('declineOptional') }))] }));
162
161
  return (_jsxs(_Fragment, { children: [showBanner && (_jsx(Card, { ref: bannerRef, className: cn('dndev-fixed dndev-z-modal', className), icon: Cookie, title: t('cookiePreferences'), content: bannerContent, footer: bannerFooter, style: {
163
162
  [position === 'top' ? 'top' : 'bottom']: 'var(--gap-md)',
164
- left: 'var(--gap-md)',
165
- right: 'var(--gap-md)',
163
+ insetInlineStart: 'var(--gap-md)',
164
+ insetInlineEnd: 'var(--gap-md)',
166
165
  maxWidth: '100%',
167
166
  width: 'calc(100% - var(--gap-md) * 2)',
168
- } })), !showBanner && !hasConsented && (_jsx(Button, { onClick: () => setShowBanner(true), className: "dndev-fixed dndev-z-toast", style: { bottom: 'var(--gap-md)', left: 'var(--gap-md)' }, icon: Cookie, title: t('cookiePreferences') }))] }));
167
+ } })), !showBanner && !hasConsented && (_jsx(Button, { onClick: () => setShowBanner(true), className: "dndev-fixed dndev-z-toast", style: { bottom: 'var(--gap-md)', insetInlineStart: 'var(--gap-md)' }, icon: Cookie, title: t('cookiePreferences') }))] }));
169
168
  }
170
169
  export default CookieConsent;
@@ -1,24 +1,28 @@
1
1
  import type { ReactNode } from 'react';
2
+ /**
3
+ * CTA button definition
4
+ */
5
+ export interface CTAButton {
6
+ label: string;
7
+ onClick: () => void;
8
+ disabled?: boolean;
9
+ variant?: 'default' | 'outline' | 'ghost' | 'link';
10
+ }
2
11
  /**
3
12
  * GameContainer props
4
13
  */
5
14
  export interface GameContainerProps {
6
15
  /** Main content area (scrollable, centered by default) */
7
16
  content: ReactNode;
8
- /** Optional fixed CTA button at bottom */
9
- cta?: {
10
- label: string;
11
- onClick: () => void;
12
- disabled?: boolean;
13
- variant?: 'default' | 'outline' | 'ghost' | 'link';
14
- };
17
+ /** Optional fixed CTA button(s) at bottom - single button or array for multiple buttons */
18
+ cta?: CTAButton | CTAButton[];
15
19
  /** Alignment variant for content area */
16
20
  align?: 'center' | 'start' | 'stretch';
17
21
  /** Justify variant for content area */
18
22
  justify?: 'center' | 'start' | 'end' | 'between';
19
23
  /** Disable ScrollArea (use plain overflow) - for interactive content */
20
24
  disableScrollArea?: boolean;
21
- /** Content width: 'full' (default) or 'narrow' (constrained by --narrow-content-max) */
25
+ /** Content width: 'narrow' (default, constrained) or 'full' */
22
26
  contentVariant?: 'full' | 'narrow';
23
27
  /** Additional className for content wrapper */
24
28
  contentClassName?: string;
@@ -68,6 +72,18 @@ export interface GameContainerProps {
68
72
  * />
69
73
  * ```
70
74
  *
75
+ * @example
76
+ * Multiple CTA buttons (side by side)
77
+ * ```tsx
78
+ * <GameContainer
79
+ * content={<ChallengeContent />}
80
+ * cta={[
81
+ * { label: 'Accept', onClick: handleAccept, variant: 'default' },
82
+ * { label: 'Decline', onClick: handleDecline, variant: 'outline' }
83
+ * ]}
84
+ * />
85
+ * ```
86
+ *
71
87
  * @version 0.0.1
72
88
  * @since 0.0.1
73
89
  * @author AMBROISE PARK Consulting
@@ -1 +1 @@
1
- {"version":3,"file":"GameContainer.d.ts","sourceRoot":"","sources":["../../../src/components/layout/GameContainer.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,OAAO,EAAE,SAAS,CAAC;IAEnB,0CAA0C;IAC1C,GAAG,CAAC,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;KACpD,CAAC;IAEF,yCAAyC;IACzC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAEvC,uCAAuC;IACvC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IAEjD,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAEnC,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,GAAG,EACH,KAAgB,EAChB,OAAkB,EAClB,iBAAyB,EACzB,cAAuB,EACvB,gBAAgB,EAChB,YAAY,GACb,EAAE,kBAAkB,2CA0CpB"}
1
+ {"version":3,"file":"GameContainer.d.ts","sourceRoot":"","sources":["../../../src/components/layout/GameContainer.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,OAAO,EAAE,SAAS,CAAC;IAEnB,2FAA2F;IAC3F,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAE9B,yCAAyC;IACzC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAEvC,uCAAuC;IACvC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IAEjD,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAEnC,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,GAAG,EACH,KAAgB,EAChB,OAAkB,EAClB,iBAAyB,EACzB,cAAyB,EACzB,gBAAgB,EAChB,YAAY,GACb,EAAE,kBAAkB,2CAoEpB"}
@@ -53,11 +53,29 @@ import { cn } from '@donotdev/components';
53
53
  * />
54
54
  * ```
55
55
  *
56
+ * @example
57
+ * Multiple CTA buttons (side by side)
58
+ * ```tsx
59
+ * <GameContainer
60
+ * content={<ChallengeContent />}
61
+ * cta={[
62
+ * { label: 'Accept', onClick: handleAccept, variant: 'default' },
63
+ * { label: 'Decline', onClick: handleDecline, variant: 'outline' }
64
+ * ]}
65
+ * />
66
+ * ```
67
+ *
56
68
  * @version 0.0.1
57
69
  * @since 0.0.1
58
70
  * @author AMBROISE PARK Consulting
59
71
  */
60
- export function GameContainer({ content, cta, align = 'center', justify = 'center', disableScrollArea = false, contentVariant = 'full', contentClassName, ctaClassName, }) {
61
- const contentInner = disableScrollArea ? (_jsx("div", { style: { overflow: 'auto', overscrollBehavior: 'contain' }, children: content })) : (_jsx(ScrollArea, { className: "dndev-game-container__scroll", children: content }));
62
- return (_jsxs("div", { className: "dndev-game-container", children: [_jsx("div", { className: cn('dndev-game-container__content', contentClassName), "data-align": align, "data-justify": justify, "data-content-variant": contentVariant, children: contentVariant === 'narrow' ? (_jsx("div", { className: "dndev-game-container__content-narrow", children: contentInner })) : (contentInner) }), cta && (_jsx("div", { className: cn('dndev-game-container__cta', ctaClassName), children: _jsx(Button, { onClick: cta.onClick, disabled: cta.disabled ?? false, variant: cta.variant ?? 'default', className: "dndev-game-container__cta-button", children: cta.label }) }))] }));
72
+ export function GameContainer({ content, cta, align = 'center', justify = 'center', disableScrollArea = false, contentVariant = 'narrow', contentClassName, ctaClassName, }) {
73
+ const narrowWrapper = contentVariant === 'narrow' && (_jsx("div", { className: "dndev-game-container__content-narrow", children: content }));
74
+ const scrollContent = contentVariant === 'narrow' ? narrowWrapper : content;
75
+ const contentInner = disableScrollArea ? (_jsx("div", { style: {
76
+ overflow: 'auto',
77
+ overscrollBehavior: 'contain',
78
+ height: '100%',
79
+ }, children: scrollContent })) : (_jsx(ScrollArea, { className: "dndev-game-container__scroll", children: scrollContent }));
80
+ return (_jsxs("div", { className: "dndev-game-container", children: [_jsx("div", { className: cn('dndev-game-container__content', contentClassName), "data-align": align, "data-justify": justify, "data-content-variant": contentVariant, children: _jsx("div", { className: "dndev-game-container__scroll-wrapper", children: contentInner }) }), cta && (_jsx("div", { className: cn('dndev-game-container__cta', ctaClassName), children: Array.isArray(cta) ? (_jsx("div", { className: "dndev-game-container__cta-buttons", children: cta.map((button, index) => (_jsx(Button, { onClick: button.onClick, disabled: button.disabled ?? false, variant: button.variant ?? 'default', className: "dndev-game-container__cta-button", fullWidth: true, children: button.label }, index))) })) : (_jsx(Button, { onClick: cta.onClick, disabled: cta.disabled ?? false, variant: cta.variant ?? 'default', className: "dndev-game-container__cta-button", children: cta.label })) }))] }));
63
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GameFlow.d.ts","sourceRoot":"","sources":["../../../src/components/layout/GameFlow.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CACjC,MAAM,EACN,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,CAC/C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAC;IAC/B,oCAAoC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,QAAQ,CAAC,EACvB,cAAc,EACd,aAAa,EACb,UAAU,EACV,QAAe,GAChB,EAAE,aAAa,kDAqCf"}
1
+ {"version":3,"file":"GameFlow.d.ts","sourceRoot":"","sources":["../../../src/components/layout/GameFlow.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CACjC,MAAM,EACN,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,CAC/C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAC;IAC/B,oCAAoC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,QAAQ,CAAC,EACvB,cAAc,EACd,aAAa,EACb,UAAU,EACV,QAAe,GAChB,EAAE,aAAa,kDAgCf"}
@@ -8,12 +8,34 @@ import { jsx as _jsx } from "react/jsx-runtime";
8
8
  * @since 0.0.1
9
9
  * @author AMBROISE PARK Consulting
10
10
  */
11
- import { useEffect, useMemo, Suspense, lazy, } from 'react';
11
+ import { useEffect, Suspense, lazy, } from 'react';
12
12
  /**
13
13
  * Module-level cache for preloaded screens
14
14
  * Tracks which screens have been preloaded to avoid duplicate preloading
15
15
  */
16
16
  const preloadedScreens = new Set();
17
+ /**
18
+ * Module-level cache for lazy components.
19
+ * CRITICAL: lazy() must NOT be called inside a component (useMemo or otherwise).
20
+ * Doing so creates a new component TYPE on each call, which causes React to
21
+ * unmount/remount the entire subtree and can trigger Rules of Hooks violations.
22
+ * This cache ensures each screen name always resolves to the same lazy component ref.
23
+ */
24
+ const lazyComponentCache = new Map();
25
+ /**
26
+ * Get or create a cached lazy component for a screen name
27
+ */
28
+ function getLazyComponent(screenName, registry) {
29
+ const cached = lazyComponentCache.get(screenName);
30
+ if (cached)
31
+ return cached;
32
+ const importer = registry[screenName];
33
+ if (!importer)
34
+ return null;
35
+ const component = lazy(importer);
36
+ lazyComponentCache.set(screenName, component);
37
+ return component;
38
+ }
17
39
  /**
18
40
  * GameFlow - Screen router for game/session flows
19
41
  *
@@ -59,16 +81,10 @@ export function GameFlow({ screenRegistry, currentScreen, nextScreen, fallback =
59
81
  }
60
82
  }
61
83
  }, [nextScreen, screenRegistry]);
62
- // Get lazy component for currentScreen
63
- const ScreenComponent = useMemo(() => {
64
- if (!currentScreen)
65
- return null;
66
- const importer = screenRegistry[currentScreen];
67
- if (!importer)
68
- return null;
69
- // Create lazy component from registry
70
- return lazy(importer);
71
- }, [currentScreen, screenRegistry]);
84
+ // Get cached lazy component for currentScreen (stable reference per screen name)
85
+ const ScreenComponent = currentScreen
86
+ ? getLazyComponent(currentScreen, screenRegistry)
87
+ : null;
72
88
  // If no currentScreen or no component found, return null
73
89
  if (!currentScreen || !ScreenComponent) {
74
90
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/components/DropdownNavigation.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAyF9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"DropdownNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/components/DropdownNavigation.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAsD9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -34,20 +34,11 @@ import { NavigationItemComponent } from '../../../routing/NavigationItem';
34
34
  */
35
35
  const DropdownNavigation = ({ navigation, className, }) => {
36
36
  return (_jsx(Stack, { role: "navigation", direction: "row", align: "center", className: className, style: { gap: 'var(--gap-sm)' }, children: navigation.map((item, idx) => item.routes && item.routes.length > 0 ? (_jsx(DropdownMenu, { trigger: _jsx(Button, { icon: item.icon, children: item.label }), items: item.routes.map((route) => {
37
- const content = route.path ? (route.external ? (_jsx("a", { href: route.path, target: "_blank", rel: "noopener noreferrer", style: {
38
- display: 'flex',
39
- alignItems: 'center',
40
- gap: 'var(--gap-sm)',
41
- width: '100%',
42
- }, children: _jsx(NavigationItemComponent, { route: route }) })) : (_jsx(Link, { path: route.path, style: {
43
- display: 'flex',
44
- alignItems: 'center',
45
- gap: 'var(--gap-sm)',
46
- width: '100%',
47
- }, children: _jsx(NavigationItemComponent, { route: route }) }))) : (_jsx(Stack, { direction: "row", align: "center", style: { gap: 'var(--gap-sm)', width: '100%' }, children: _jsx(NavigationItemComponent, { route: route }) }));
37
+ // NavigationItemComponent already renders a Link/anchor use it directly.
38
+ // External links are handled via the route.external flag inside NavigationItemComponent.
48
39
  return {
49
40
  label: route.label,
50
- children: content,
41
+ children: _jsx(NavigationItemComponent, { route: route }),
51
42
  asChild: !!route.path,
52
43
  };
53
44
  }), contentAlign: "start" }, item.label + idx)) : item.path ? (_jsx(Button, { icon: item.icon, "aria-label": item.label, render: ({ children, ...props }) => (_jsx(Link, { path: item.path, ...props, children: children })), children: item.label }, item.label + idx)) : (_jsx(Button, { icon: item.icon, disabled: true, "aria-label": item.label, children: item.label }, item.label + idx))) }));
@@ -20,7 +20,7 @@ const FloatingLanguageSwitcher = ({ languages, currentLanguage, onLanguageChange
20
20
  return (_jsx(Card, { className: cn('dndev-z-modal', className), style: {
21
21
  position: 'fixed',
22
22
  bottom: 'var(--gap-md)',
23
- right: 'var(--gap-md)',
23
+ insetInlineEnd: 'var(--gap-md)',
24
24
  display: 'flex',
25
25
  alignItems: 'center',
26
26
  gap: 'var(--gap-sm)',
@@ -41,8 +41,6 @@ export interface NotificationsProps {
41
41
  loading?: boolean;
42
42
  /** Callback when notification is dismissed from toast */
43
43
  onNotificationClick?: (notification: NotificationItem) => void;
44
- /** Callback when mark all as read is clicked */
45
- onMarkAllRead?: () => void;
46
44
  /** Callback when dropdown opens */
47
45
  onDropdownOpen?: () => void;
48
46
  /** Maximum number of visible notifications */
@@ -112,6 +110,6 @@ export interface NotificationsProps {
112
110
  * @since 0.0.1
113
111
  * @author AMBROISE PARK Consulting
114
112
  */
115
- export declare const Notifications: ({ notifications, count, loading, onNotificationClick, onMarkAllRead, onDropdownOpen, className, maxVisible, alwaysShow, size, disabled, }: NotificationsProps) => import("react/jsx-runtime").JSX.Element | null;
113
+ export declare const Notifications: ({ notifications, count, loading, onNotificationClick, onDropdownOpen, className, maxVisible, alwaysShow, size, disabled, }: NotificationsProps) => import("react/jsx-runtime").JSX.Element | null;
116
114
  export default Notifications;
117
115
  //# sourceMappingURL=Notifications.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Notifications.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/components/Notifications.tsx"],"names":[],"mappings":"AA+BA;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IAEX,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAEhD,6CAA6C;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IAEjB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEnC,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAE/D,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAE3B,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,mBAAmB;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAE1B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,aAAa,GAAI,2IAY3B,kBAAkB,mDA4FpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"Notifications.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/components/Notifications.tsx"],"names":[],"mappings":"AA+BA;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IAEX,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAEhD,6CAA6C;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IAEjB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEnC,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAE/D,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,mBAAmB;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAE1B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,aAAa,GAAI,4HAW3B,kBAAkB,mDA+FpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -113,7 +113,7 @@ const SIZE_VARIANTS = {
113
113
  * @since 0.0.1
114
114
  * @author AMBROISE PARK Consulting
115
115
  */
116
- export const Notifications = ({ notifications = [], count = 0, loading = false, onNotificationClick, onMarkAllRead, onDropdownOpen, className, maxVisible = 10, alwaysShow = false, size = 'md', disabled = false, }) => {
116
+ export const Notifications = ({ notifications = [], count = 0, loading = false, onNotificationClick, onDropdownOpen, className, maxVisible = 10, alwaysShow = false, size = 'md', disabled = false, }) => {
117
117
  const sizeVariant = SIZE_VARIANTS[size];
118
118
  const shownNotificationIds = useRef(new Set());
119
119
  // Calculate display count (format large numbers)
@@ -159,6 +159,8 @@ export const Notifications = ({ notifications = [], count = 0, loading = false,
159
159
  return (_jsx("div", { className: cn(className), style: { position: 'relative' }, children: _jsx(Button, { disabled: disabled, style: {
160
160
  ...sizeVariant.button,
161
161
  position: 'relative',
162
+ }, onClick: () => {
163
+ onDropdownOpen?.();
162
164
  }, onFocus: (e) => {
163
165
  e.currentTarget.style.outline = '2px solid var(--ring)';
164
166
  e.currentTarget.style.outlineOffset = '2px';
@@ -167,7 +169,7 @@ export const Notifications = ({ notifications = [], count = 0, loading = false,
167
169
  }, "aria-label": `${count} notification${count !== 1 ? 's' : ''}`, icon: Bell, children: displayCount && (_jsx(Stack, { align: "center", justify: "center", style: {
168
170
  position: 'absolute',
169
171
  top: '-0.25rem',
170
- right: '-0.25rem',
172
+ insetInlineEnd: '-0.25rem',
171
173
  backgroundColor: 'var(--destructive)',
172
174
  color: 'var(--destructive-foreground)',
173
175
  borderRadius: 'var(--radius-full)',
@@ -1 +1 @@
1
- {"version":3,"file":"AppBranding.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/AppBranding.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAM,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAMnD,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IACjD,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,WAAW,GAAI,qCAIzB,gBAAgB,4CA2ClB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"AppBranding.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/AppBranding.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAM,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAOnD,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IACjD,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,WAAW,GAAI,qCAIzB,gBAAgB,4CA2ClB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -13,6 +13,7 @@ import { cn, DISPLAY } from '@donotdev/components';
13
13
  import { useAppConfig } from '@donotdev/core';
14
14
  import { Link } from '../../../../routing/Link';
15
15
  import { AssetResolver } from '../../../../utils/assetResolver';
16
+ import { sanitizeSvg } from '../../../../utils/sanitizeSvg';
16
17
  /**
17
18
  * AppBranding - Unified branding component
18
19
  *
@@ -42,7 +43,7 @@ export const AppBranding = ({ display = DISPLAY.AUTO, linkToHome = true, classNa
42
43
  const svgContent = AssetResolver.getLogoSvgContent();
43
44
  const logoPath = AssetResolver.resolveLogo();
44
45
  const showTitle = display === DISPLAY.FULL || display === DISPLAY.AUTO;
45
- const logo = svgContent ? (_jsx("div", { className: "app-branding-logo", role: "img", "aria-label": displayTitle, dangerouslySetInnerHTML: { __html: svgContent } })) : AssetResolver.assetExists(logoPath) ? (_jsx("img", { src: logoPath, alt: displayTitle, className: "app-branding-logo" })) : null;
46
+ const logo = svgContent ? (_jsx("div", { className: "app-branding-logo", role: "img", "aria-label": displayTitle, dangerouslySetInnerHTML: { __html: sanitizeSvg(svgContent) } })) : AssetResolver.assetExists(logoPath) ? (_jsx("img", { src: logoPath, alt: displayTitle, className: "app-branding-logo" })) : null;
46
47
  const title = showTitle && (_jsx("span", { className: "app-branding-title", "data-display": display, children: displayTitle }));
47
48
  const content = (_jsxs("div", { className: cn('app-branding', className), "data-display": display, children: [logo, title] }));
48
49
  if (linkToHome) {
@@ -1 +1 @@
1
- {"version":3,"file":"AppIcon.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/AppIcon.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrD,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,0BAAqC,YAAY,4CA0CxE,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"AppIcon.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/AppIcon.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrD,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,0BAAqC,YAAY,4CA2CxE,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -13,6 +13,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { cn } from '@donotdev/components';
14
14
  import { useAppConfig } from '@donotdev/core';
15
15
  import { AssetResolver } from '../../../../utils/assetResolver';
16
+ import { sanitizeSvg } from '../../../../utils/sanitizeSvg';
16
17
  const SIZE_STYLES = {
17
18
  sm: { width: 'var(--icon-md)', height: 'var(--icon-md)' },
18
19
  md: { width: 'var(--icon-touch)', height: 'var(--icon-touch)' },
@@ -32,7 +33,9 @@ const SIZE_STYLES = {
32
33
  * @author AMBROISE PARK Consulting
33
34
  */
34
35
  export const AppIcon = ({ alt, size = 'header', className }) => {
35
- const resolvedAlt = alt || useAppConfig('name') || useAppConfig('shortName') || 'App';
36
+ const appName = useAppConfig('name');
37
+ const appShortName = useAppConfig('shortName');
38
+ const resolvedAlt = alt || appName || appShortName || 'App';
36
39
  const svgContent = AssetResolver.getLogoSvgContent();
37
40
  const logoPath = AssetResolver.resolveLogo();
38
41
  const sizeStyle = typeof size === 'string' && size in SIZE_STYLES
@@ -45,7 +48,7 @@ export const AppIcon = ({ alt, size = 'header', className }) => {
45
48
  return (_jsx("div", { className: cn('app-icon-header', className), style: {
46
49
  display: 'inline-flex',
47
50
  ...sizeStyle,
48
- }, role: "img", "aria-label": resolvedAlt, dangerouslySetInnerHTML: { __html: svgContent } }));
51
+ }, role: "img", "aria-label": resolvedAlt, dangerouslySetInnerHTML: { __html: sanitizeSvg(svgContent) } }));
49
52
  }
50
53
  // Fallback to img tag if SVG content not available
51
54
  return (_jsx("img", { src: logoPath, alt: resolvedAlt, className: cn(className), style: {
@@ -1 +1 @@
1
- {"version":3,"file":"CacheSettings.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/CacheSettings.tsx"],"names":[],"mappings":"AA0BA;;;;;;;;;GASG;AACH,iBAAS,aAAa,4CAqPrB;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"CacheSettings.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/components/header/CacheSettings.tsx"],"names":[],"mappings":"AA0BA;;;;;;;;;GASG;AACH,iBAAS,aAAa,4CAuPrB;AAED,eAAe,aAAa,CAAC"}