@donotdev/components 0.0.2 → 0.0.3

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 (43) hide show
  1. package/dist/atomic/Button/index.d.ts.map +1 -1
  2. package/dist/atomic/Button/index.js +3 -2
  3. package/dist/atomic/CallToAction/index.d.ts +2 -1
  4. package/dist/atomic/CallToAction/index.d.ts.map +1 -1
  5. package/dist/atomic/CallToAction/index.js +2 -1
  6. package/dist/atomic/Card/index.d.ts.map +1 -1
  7. package/dist/atomic/Card/index.js +4 -2
  8. package/dist/atomic/Command/index.d.ts.map +1 -1
  9. package/dist/atomic/Command/index.js +3 -1
  10. package/dist/atomic/CommandDialog/index.d.ts.map +1 -1
  11. package/dist/atomic/CopyToClipboard/index.d.ts.map +1 -1
  12. package/dist/atomic/DropdownMenu/index.d.ts.map +1 -1
  13. package/dist/atomic/DualCard/index.d.ts +2 -0
  14. package/dist/atomic/DualCard/index.d.ts.map +1 -1
  15. package/dist/atomic/DualCard/index.js +2 -2
  16. package/dist/atomic/Grid/index.d.ts +17 -4
  17. package/dist/atomic/Grid/index.d.ts.map +1 -1
  18. package/dist/atomic/Grid/index.js +17 -4
  19. package/dist/atomic/HeroSection/index.d.ts +2 -1
  20. package/dist/atomic/HeroSection/index.d.ts.map +1 -1
  21. package/dist/atomic/HeroSection/index.js +17 -2
  22. package/dist/atomic/Input/index.d.ts.map +1 -1
  23. package/dist/atomic/Input/index.js +4 -0
  24. package/dist/atomic/NavigationMenu/index.d.ts +1 -1
  25. package/dist/atomic/NavigationMenu/index.d.ts.map +1 -1
  26. package/dist/atomic/Popover/index.d.ts +24 -2
  27. package/dist/atomic/Popover/index.d.ts.map +1 -1
  28. package/dist/atomic/Popover/index.js +9 -0
  29. package/dist/atomic/RadioGroup/index.d.ts +4 -2
  30. package/dist/atomic/RadioGroup/index.d.ts.map +1 -1
  31. package/dist/atomic/RadioGroup/index.js +4 -5
  32. package/dist/atomic/Section/index.d.ts +2 -1
  33. package/dist/atomic/Section/index.d.ts.map +1 -1
  34. package/dist/atomic/Section/index.js +2 -1
  35. package/dist/atomic/Tooltip/index.d.ts +6 -1
  36. package/dist/atomic/Tooltip/index.d.ts.map +1 -1
  37. package/dist/atomic/Tooltip/index.js +19 -2
  38. package/dist/atomic/VideoPlayer/index.d.ts.map +1 -1
  39. package/dist/atomic/VideoPlayer/index.js +15 -5
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js +4 -4
  42. package/dist/styles/index.css +127 -106
  43. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // packages/components/src/atomic/Tooltip/index.tsx
3
3
  /**
4
4
  * @fileoverview Tooltip component
5
5
  * @description Accessible tooltip component built on Radix UI primitives.
6
6
  *
7
- * @version 0.0.2
7
+ * @version 0.0.3
8
8
  * @since 0.0.1
9
9
  * @author AMBROISE PARK Consulting
10
10
  */
@@ -20,6 +20,11 @@ import { useRef, useState, useEffect } from 'react';
20
20
  * 2. CSS `--tooltip-side` property (set by container like Sidebar)
21
21
  * 3. Radix auto-positioning (default)
22
22
  *
23
+ * SSR Safety:
24
+ * During SSR/static generation (Next.js prerendering), TooltipProvider may not
25
+ * be available. This component gracefully degrades by rendering just children
26
+ * during SSR, then hydrating with full tooltip functionality on client.
27
+ *
23
28
  * @example
24
29
  * ```css
25
30
  * .sidebar { --tooltip-side: right; }
@@ -32,6 +37,12 @@ import { useRef, useState, useEffect } from 'react';
32
37
  const Tooltip = ({ content, children, side, align = 'center', delayDuration = 300, variant, }) => {
33
38
  const triggerRef = useRef(null);
34
39
  const [computedSide, setComputedSide] = useState(side);
40
+ // SSR safety: Track if component has mounted on client
41
+ // During SSR/static generation, render just children to avoid TooltipProvider dependency
42
+ const [isMounted, setIsMounted] = useState(false);
43
+ useEffect(() => {
44
+ setIsMounted(true);
45
+ }, []);
35
46
  // Read CSS custom property after mount (CSR only, SSR-safe)
36
47
  // Priority: CSS --tooltip-side > explicit side prop > Radix auto
37
48
  useEffect(() => {
@@ -53,6 +64,12 @@ const Tooltip = ({ content, children, side, align = 'center', delayDuration = 30
53
64
  // No side specified - Radix will auto-position
54
65
  setComputedSide(undefined);
55
66
  }, [side]);
67
+ // During SSR/static generation, render just children
68
+ // This prevents TooltipProvider requirement during prerendering
69
+ // After hydration, full tooltip functionality is available
70
+ if (!isMounted) {
71
+ return _jsx(_Fragment, { children: children });
72
+ }
56
73
  const variantAttrs = getVariantDataAttrs({
57
74
  variant: variant !== FLOATING_VARIANT.DEFAULT ? variant : undefined,
58
75
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/VideoPlayer/index.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,eAAe;IACf,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,QAAA,MAAM,WAAW,GAAI,sGAWlB,gBAAgB,4CA6GlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/VideoPlayer/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,eAAe;IACf,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,QAAA,MAAM,WAAW,GAAI,sGAWlB,gBAAgB,4CA+IlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -14,6 +14,7 @@ import { useTranslation } from '@donotdev/core';
14
14
  import { cn } from '../../utils/helpers';
15
15
  import Button, { BUTTON_VARIANT } from '../Button';
16
16
  import Dialog from '../Dialog';
17
+ import Spinner from '../Spinner';
17
18
  /**
18
19
  * Constructs embed URL from VideoConfig or returns string URL as-is
19
20
  *
@@ -136,6 +137,7 @@ const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger
136
137
  const { t } = useTranslation(['dndev']);
137
138
  const [isOpen, setIsOpen] = useState(false);
138
139
  const [isLoaded, setIsLoaded] = useState(false);
140
+ const [iframeReady, setIframeReady] = useState(false);
139
141
  const embedUrl = getEmbedUrl(url, autoplay);
140
142
  const thumbnailUrl = thumbnail || getThumbnailUrl(url);
141
143
  // Lazy-load iframe when modal opens
@@ -144,11 +146,15 @@ const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger
144
146
  setIsLoaded(true);
145
147
  }
146
148
  }, [isOpen, isLoaded]);
147
- const videoFrame = (_jsx("iframe", { src: isLoaded ? embedUrl : '', title: title, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: allowFullscreen, className: cn('dndev-video-frame', className), style: { aspectRatio } }));
149
+ // Reset iframe ready state when video changes
150
+ useEffect(() => {
151
+ setIframeReady(false);
152
+ }, [embedUrl]);
153
+ const videoFrame = (_jsx("iframe", { src: isLoaded ? embedUrl : '', title: title, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: allowFullscreen, className: cn('dndev-video-frame', className), style: { aspectRatio }, onLoad: () => setIframeReady(true) }));
148
154
  // Inline video (no modal) - lazy-load on click
149
155
  if (!modal) {
156
+ // Not clicked yet - show thumbnail only
150
157
  if (!isLoaded) {
151
- // Show thumbnail facade
152
158
  if (thumbnailUrl) {
153
159
  return (_jsxs("button", { type: "button", onClick: () => setIsLoaded(true), onKeyDown: (e) => {
154
160
  if (e.key === 'Enter' || e.key === ' ') {
@@ -157,11 +163,15 @@ const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger
157
163
  }
158
164
  }, className: cn('dndev-video-thumbnail', className), style: { aspectRatio }, "aria-label": t('video.clickToWatch', 'Click to watch video'), children: [_jsx("img", { src: thumbnailUrl, alt: title, loading: eager ? 'eager' : 'lazy', fetchPriority: eager ? 'high' : 'low', decoding: "async" }), _jsx("div", { className: "dndev-video-play-overlay", children: _jsx(Play, { className: "dndev-video-play-icon" }) })] }));
159
165
  }
160
- // No thumbnail available - show button
166
+ // No thumbnail - show button
161
167
  return (_jsx(Button, { icon: Play, onClick: () => setIsLoaded(true), className: className, children: t('video.watchVideo', 'Watch Video') }));
162
168
  }
163
- // Show iframe after click
164
- return (_jsx("div", { className: cn('dndev-video-container', className), children: videoFrame }));
169
+ // Clicked - show iframe with thumbnail overlay until iframe loads
170
+ return (_jsxs("div", { className: cn('dndev-video-container', className), style: { aspectRatio, position: 'relative' }, children: [videoFrame, !iframeReady && thumbnailUrl && (_jsxs("div", { className: "dndev-video-thumbnail dndev-video-loading-overlay", style: {
171
+ position: 'absolute',
172
+ inset: 0,
173
+ pointerEvents: 'none',
174
+ }, children: [_jsx("img", { src: thumbnailUrl, alt: title, loading: "eager", decoding: "async" }), _jsx("div", { className: "dndev-video-play-overlay dndev-video-loading", children: _jsx(Spinner, { "aria-label": t('video.loading', 'Loading video') }) })] }))] }));
165
175
  }
166
176
  // Modal mode - lazy-load iframe when modal opens
167
177
  const defaultTrigger = thumbnailUrl ? (_jsxs("button", { type: "button", className: "dndev-video-thumbnail", style: { aspectRatio }, "aria-label": t('video.clickToWatch', 'Click to watch video'), children: [_jsx("img", { src: thumbnailUrl, alt: title, loading: eager ? 'eager' : 'lazy', fetchPriority: eager ? 'high' : 'low', decoding: "async" }), _jsx("div", { className: "dndev-video-play-overlay", children: _jsx(Play, { className: "dndev-video-play-icon" }) })] })) : (_jsx(Button, { icon: Play, children: t('video.watchVideo', 'Watch Video') }));
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview Components package
3
3
  * @description UI component library for DoNotDev framework
4
- * @version 0.0.1
4
+ * @version 0.0.3
5
5
  * @since 0.0.1
6
6
  * @author AMBROISE PARK Consulting
7
7
  */