@flamingo-stack/openframe-frontend-core 0.0.397-snapshot.20260710044003 → 0.0.397

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 (137) hide show
  1. package/dist/{chunk-MNQVBME4.js → chunk-2OOZASQE.js} +3 -3
  2. package/dist/{chunk-WBLRUO3F.cjs → chunk-2U3YPWHG.cjs} +3 -3
  3. package/dist/{chunk-WBLRUO3F.cjs.map → chunk-2U3YPWHG.cjs.map} +1 -1
  4. package/dist/{chunk-MGJZQ3EE.js → chunk-3E4BDAHJ.js} +2 -2
  5. package/dist/{chunk-WJSUUOPU.cjs → chunk-43C5ECNT.cjs} +40 -40
  6. package/dist/{chunk-WJSUUOPU.cjs.map → chunk-43C5ECNT.cjs.map} +1 -1
  7. package/dist/{chunk-PE37UDPF.cjs → chunk-55SNCMFS.cjs} +40 -40
  8. package/dist/{chunk-PE37UDPF.cjs.map → chunk-55SNCMFS.cjs.map} +1 -1
  9. package/dist/{chunk-JWBRDNYH.cjs → chunk-743FCO64.cjs} +31 -31
  10. package/dist/{chunk-JWBRDNYH.cjs.map → chunk-743FCO64.cjs.map} +1 -1
  11. package/dist/{chunk-LBDKAMOH.cjs → chunk-BB7TZ6KS.cjs} +75 -75
  12. package/dist/{chunk-LBDKAMOH.cjs.map → chunk-BB7TZ6KS.cjs.map} +1 -1
  13. package/dist/{chunk-B2K5COVE.js → chunk-CK5UZLIN.js} +3189 -3305
  14. package/dist/chunk-CK5UZLIN.js.map +1 -0
  15. package/dist/{chunk-WXOIEYXW.js → chunk-D4F7ZLJG.js} +5 -5
  16. package/dist/{chunk-7Q2DZEUA.cjs → chunk-DB6CUWTL.cjs} +32 -32
  17. package/dist/{chunk-7Q2DZEUA.cjs.map → chunk-DB6CUWTL.cjs.map} +1 -1
  18. package/dist/{chunk-FZIMFLJG.cjs → chunk-HPQKX5IW.cjs} +15 -15
  19. package/dist/{chunk-FZIMFLJG.cjs.map → chunk-HPQKX5IW.cjs.map} +1 -1
  20. package/dist/{chunk-N4R7TRF3.js → chunk-IVXOR2IA.js} +2 -2
  21. package/dist/{chunk-URODM26E.js → chunk-J6TAK6HE.js} +6 -6
  22. package/dist/{chunk-VDDNJ6XC.js → chunk-JNU3YPLP.js} +5 -5
  23. package/dist/{chunk-2TBXIW7L.js → chunk-K5FRWPWF.js} +3 -3
  24. package/dist/{chunk-ZSZRJWY3.js → chunk-KQESCGVG.js} +2 -2
  25. package/dist/{chunk-N7YBNHVT.js → chunk-LQHMXPOJ.js} +509 -563
  26. package/dist/chunk-LQHMXPOJ.js.map +1 -0
  27. package/dist/{chunk-LPH2JDOW.cjs → chunk-LWNPMLIH.cjs} +2 -56
  28. package/dist/chunk-LWNPMLIH.cjs.map +1 -0
  29. package/dist/{chunk-YEWGFWNM.cjs → chunk-M6NPDNVB.cjs} +29 -29
  30. package/dist/{chunk-YEWGFWNM.cjs.map → chunk-M6NPDNVB.cjs.map} +1 -1
  31. package/dist/{chunk-C4DHYDXB.cjs → chunk-OAENYOKC.cjs} +12 -12
  32. package/dist/{chunk-C4DHYDXB.cjs.map → chunk-OAENYOKC.cjs.map} +1 -1
  33. package/dist/{chunk-XYT5PIKZ.cjs → chunk-SBWTMJPQ.cjs} +5 -5
  34. package/dist/{chunk-XYT5PIKZ.cjs.map → chunk-SBWTMJPQ.cjs.map} +1 -1
  35. package/dist/{chunk-2DGA5LHT.cjs → chunk-T5F54MN4.cjs} +19 -19
  36. package/dist/{chunk-2DGA5LHT.cjs.map → chunk-T5F54MN4.cjs.map} +1 -1
  37. package/dist/{chunk-Y3FREU4B.js → chunk-TTHTO5H5.js} +7 -7
  38. package/dist/{chunk-MQXUIYYN.js → chunk-VTR4QDL2.js} +4 -4
  39. package/dist/{chunk-GKRJOS6S.js → chunk-WCDM226S.js} +3 -3
  40. package/dist/{chunk-4KWIQEZT.js → chunk-WWHPTP4B.js} +2 -2
  41. package/dist/{chunk-4BVRLCCA.cjs → chunk-XNAYZHPK.cjs} +73 -73
  42. package/dist/{chunk-4BVRLCCA.cjs.map → chunk-XNAYZHPK.cjs.map} +1 -1
  43. package/dist/{chunk-HMTOQGYU.cjs → chunk-Z6PAD2UN.cjs} +7 -7
  44. package/dist/{chunk-HMTOQGYU.cjs.map → chunk-Z6PAD2UN.cjs.map} +1 -1
  45. package/dist/{chunk-G42EXM23.js → chunk-ZFK4HHRX.js} +2 -2
  46. package/dist/{chunk-VVO7AZKZ.cjs → chunk-ZUKBC2ZX.cjs} +190 -306
  47. package/dist/chunk-ZUKBC2ZX.cjs.map +1 -0
  48. package/dist/components/case-studies/index.cjs +14 -14
  49. package/dist/components/case-studies/index.js +4 -4
  50. package/dist/components/chat/index.cjs +4 -4
  51. package/dist/components/chat/index.js +3 -3
  52. package/dist/components/contact/index.cjs +5 -5
  53. package/dist/components/contact/index.js +4 -4
  54. package/dist/components/docs/index.cjs +7 -7
  55. package/dist/components/docs/index.js +6 -6
  56. package/dist/components/embeds/index.cjs +5 -5
  57. package/dist/components/embeds/index.js +4 -4
  58. package/dist/components/faq/index.cjs +6 -6
  59. package/dist/components/faq/index.js +5 -5
  60. package/dist/components/features/index.cjs +4 -8
  61. package/dist/components/features/index.cjs.map +1 -1
  62. package/dist/components/features/index.d.ts +0 -1
  63. package/dist/components/features/index.d.ts.map +1 -1
  64. package/dist/components/features/index.js +3 -7
  65. package/dist/components/features/video-bites-strip.d.ts.map +1 -1
  66. package/dist/components/features/video.d.ts +4 -7
  67. package/dist/components/features/video.d.ts.map +1 -1
  68. package/dist/components/help-center-pages/index.cjs +23 -23
  69. package/dist/components/help-center-pages/index.js +14 -14
  70. package/dist/components/icons/index.cjs +2 -6
  71. package/dist/components/icons/index.cjs.map +1 -1
  72. package/dist/components/icons/index.d.ts +0 -2
  73. package/dist/components/icons/index.d.ts.map +1 -1
  74. package/dist/components/icons/index.js +1 -5
  75. package/dist/components/index.cjs +142 -152
  76. package/dist/components/index.cjs.map +1 -1
  77. package/dist/components/index.js +12 -22
  78. package/dist/components/index.js.map +1 -1
  79. package/dist/components/media-carousel.d.ts.map +1 -1
  80. package/dist/components/navigation/index.cjs +4 -4
  81. package/dist/components/navigation/index.js +3 -3
  82. package/dist/components/onboarding-guides/index.cjs +8 -8
  83. package/dist/components/onboarding-guides/index.js +7 -7
  84. package/dist/components/related-content/index.cjs +6 -6
  85. package/dist/components/related-content/index.js +5 -5
  86. package/dist/components/tickets/index.cjs +7 -7
  87. package/dist/components/tickets/index.js +6 -6
  88. package/dist/components/ui/index.cjs +4 -6
  89. package/dist/components/ui/index.cjs.map +1 -1
  90. package/dist/components/ui/index.d.ts +0 -1
  91. package/dist/components/ui/index.d.ts.map +1 -1
  92. package/dist/components/ui/index.js +3 -5
  93. package/dist/components/ui/tab-navigation.d.ts +2 -6
  94. package/dist/components/ui/tab-navigation.d.ts.map +1 -1
  95. package/dist/hooks/index.cjs +3 -3
  96. package/dist/hooks/index.js +2 -2
  97. package/dist/index.cjs +4 -14
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.js +3 -13
  100. package/package.json +4 -4
  101. package/src/components/features/index.ts +0 -1
  102. package/src/components/features/video-bites-strip.tsx +15 -73
  103. package/src/components/features/video.tsx +28 -51
  104. package/src/components/icons/index.ts +0 -2
  105. package/src/components/media-carousel.tsx +4 -2
  106. package/src/components/ui/index.ts +0 -1
  107. package/src/components/ui/tab-navigation.tsx +14 -31
  108. package/src/styles/app-globals.css +0 -23
  109. package/dist/chunk-B2K5COVE.js.map +0 -1
  110. package/dist/chunk-LPH2JDOW.cjs.map +0 -1
  111. package/dist/chunk-N7YBNHVT.js.map +0 -1
  112. package/dist/chunk-VVO7AZKZ.cjs.map +0 -1
  113. package/dist/components/features/video-center-badge.d.ts +0 -40
  114. package/dist/components/features/video-center-badge.d.ts.map +0 -1
  115. package/dist/components/icons/play-filled-icon.d.ts +0 -15
  116. package/dist/components/icons/play-filled-icon.d.ts.map +0 -1
  117. package/dist/components/icons/volume-off-filled-icon.d.ts +0 -14
  118. package/dist/components/icons/volume-off-filled-icon.d.ts.map +0 -1
  119. package/dist/components/ui/crossfade-panels.d.ts +0 -52
  120. package/dist/components/ui/crossfade-panels.d.ts.map +0 -1
  121. package/src/components/features/video-center-badge.tsx +0 -77
  122. package/src/components/icons/play-filled-icon.tsx +0 -36
  123. package/src/components/icons/volume-off-filled-icon.tsx +0 -38
  124. package/src/components/ui/crossfade-panels.tsx +0 -88
  125. /package/dist/{chunk-MNQVBME4.js.map → chunk-2OOZASQE.js.map} +0 -0
  126. /package/dist/{chunk-MGJZQ3EE.js.map → chunk-3E4BDAHJ.js.map} +0 -0
  127. /package/dist/{chunk-WXOIEYXW.js.map → chunk-D4F7ZLJG.js.map} +0 -0
  128. /package/dist/{chunk-N4R7TRF3.js.map → chunk-IVXOR2IA.js.map} +0 -0
  129. /package/dist/{chunk-URODM26E.js.map → chunk-J6TAK6HE.js.map} +0 -0
  130. /package/dist/{chunk-VDDNJ6XC.js.map → chunk-JNU3YPLP.js.map} +0 -0
  131. /package/dist/{chunk-2TBXIW7L.js.map → chunk-K5FRWPWF.js.map} +0 -0
  132. /package/dist/{chunk-ZSZRJWY3.js.map → chunk-KQESCGVG.js.map} +0 -0
  133. /package/dist/{chunk-Y3FREU4B.js.map → chunk-TTHTO5H5.js.map} +0 -0
  134. /package/dist/{chunk-MQXUIYYN.js.map → chunk-VTR4QDL2.js.map} +0 -0
  135. /package/dist/{chunk-GKRJOS6S.js.map → chunk-WCDM226S.js.map} +0 -0
  136. /package/dist/{chunk-4KWIQEZT.js.map → chunk-WWHPTP4B.js.map} +0 -0
  137. /package/dist/{chunk-G42EXM23.js.map → chunk-ZFK4HHRX.js.map} +0 -0
@@ -1,40 +0,0 @@
1
- /**
2
- * THE center media glyphs — the single visual identity for every play/unmute
3
- * affordance over video, across the whole project: a SOLID WHITE GLYPH
4
- * (`text-ods-text-primary`), NO background disc, with a soft drop-shadow for
5
- * legibility over arbitrary frames. Accent color appears ONLY while the
6
- * icon's own control is hovered (hosts pass `group-hover:text-ods-accent`;
7
- * mux-player controls get the same via `::part(button):hover` in
8
- * styles/app-globals.css).
9
- *
10
- * Glyphs come from THE icon system — never inline SVG paths here:
11
- * PlayFilledIcon / VolumeOffFilledIcon (components/icons — the FILLED
12
- * media-chrome-matching glyphs, so custom affordances are pixel-identical to
13
- * MuxPlayer's native center button on real players).
14
- *
15
- * Consumers:
16
- * - <VideoBiteCard> resting/paused posters (md)
17
- * - <YouTubeFacade> poster (lg)
18
- * - <MediaCarousel> video thumbnails (sm)
19
- * - <FilePlayer>'s unmute chip (VideoUnmuteGlyph, md)
20
- * - MuxPlayer's native center pre-play button is stripped to the same bare
21
- * glyph language via CSS (see styles/app-globals.css).
22
- */
23
- import React from 'react';
24
- export type VideoCenterBadgeSize = 'sm' | 'md' | 'lg';
25
- export interface VideoPlayBadgeProps {
26
- size?: VideoCenterBadgeSize;
27
- className?: string;
28
- }
29
- /** Bare play glyph (the icon system's PlayIcon). Decorative
30
- * (`pointer-events-none`) — the host surface owns activation. */
31
- export declare function VideoPlayBadge({ size, className }: VideoPlayBadgeProps): React.ReactElement;
32
- export interface VideoUnmuteGlyphProps {
33
- size?: VideoCenterBadgeSize;
34
- className?: string;
35
- }
36
- /** Bare muted-volume glyph (the icon system's VolumeOffFilledIcon). Rendered
37
- * by FilePlayer's unmute button; exported here so play + unmute share one
38
- * identity. */
39
- export declare function VideoUnmuteGlyph({ size, className }: VideoUnmuteGlyphProps): React.ReactElement;
40
- //# sourceMappingURL=video-center-badge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"video-center-badge.d.ts","sourceRoot":"","sources":["../../../src/components/features/video-center-badge.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAWrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,oBAAoB,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;kEACkE;AAClE,wBAAgB,cAAc,CAAC,EAAE,IAAW,EAAE,SAAS,EAAE,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CASlG;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,oBAAoB,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;gBAEgB;AAChB,wBAAgB,gBAAgB,CAAC,EAAE,IAAW,EAAE,SAAS,EAAE,EAAE,qBAAqB,GAAG,KAAK,CAAC,YAAY,CAStG"}
@@ -1,15 +0,0 @@
1
- import type { SVGProps } from "react";
2
- export interface PlayFilledIconProps extends Omit<SVGProps<SVGSVGElement>, "width" | "height"> {
3
- className?: string;
4
- size?: number;
5
- color?: string;
6
- }
7
- /**
8
- * Solid play triangle — the SAME glyph media-chrome/MuxPlayer renders in its
9
- * native center play button, so custom video affordances (strip cards,
10
- * facades, carousels) stay pixel-consistent with real player chrome.
11
- * Hand-maintained (not in the Figma-generated set, which has only the
12
- * outline `PlayIcon`).
13
- */
14
- export declare function PlayFilledIcon({ className, size, color, ...props }: PlayFilledIconProps): import("react").JSX.Element;
15
- //# sourceMappingURL=play-filled-icon.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"play-filled-icon.d.ts","sourceRoot":"","sources":["../../../src/components/icons/play-filled-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,WAAW,mBACf,SAAQ,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,SAAc,EACd,IAAS,EACT,KAAsB,EACtB,GAAG,KAAK,EACT,EAAE,mBAAmB,+BAcrB"}
@@ -1,14 +0,0 @@
1
- import type { SVGProps } from "react";
2
- export interface VolumeOffFilledIconProps extends Omit<SVGProps<SVGSVGElement>, "width" | "height"> {
3
- className?: string;
4
- size?: number;
5
- color?: string;
6
- }
7
- /**
8
- * Solid muted-volume glyph (speaker + slash) — the filled companion to
9
- * `PlayFilledIcon`, matching media-chrome's icon family so video unmute
10
- * affordances read identically to real player chrome. Hand-maintained (the
11
- * Figma-generated set has only outline volume icons).
12
- */
13
- export declare function VolumeOffFilledIcon({ className, size, color, ...props }: VolumeOffFilledIconProps): import("react").JSX.Element;
14
- //# sourceMappingURL=volume-off-filled-icon.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"volume-off-filled-icon.d.ts","sourceRoot":"","sources":["../../../src/components/icons/volume-off-filled-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,WAAW,wBACf,SAAQ,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAc,EACd,IAAS,EACT,KAAsB,EACtB,GAAG,KAAK,EACT,EAAE,wBAAwB,+BAiB1B"}
@@ -1,52 +0,0 @@
1
- /**
2
- * <CrossfadePanels> — THE keep-mounted tab-panel stack: every panel stays in
3
- * the DOM, stacked in the SAME grid cell, and switching is an opacity
4
- * crossfade. Use it under any tab control (TabNavigation, TabSelector, …)
5
- * whenever panels are content surfaces where height stability and a soft
6
- * switch matter (strips, media rails, dashboards-in-view).
7
- *
8
- * Invariants encoded HERE exactly once (so no consumer re-derives them):
9
- * - HEIGHT LOCK: grid items in one cell size the row to max(panel heights) —
10
- * switching never shifts the page (no CLS), and surrounding layout treats
11
- * the stack as one constant-height block.
12
- * - FADE-THEN-HIDE: `visibility` transitions alongside `opacity`; per the CSS
13
- * transitions spec's special visibility interpolation the outgoing panel
14
- * stays paintable until the fade completes, THEN becomes `hidden` — no
15
- * pop-out, and the settled hidden panel is fully removed from paint.
16
- * - DEAD WHILE HIDDEN: `inert` + `aria-hidden` + `pointer-events-none` on
17
- * inactive panels — no tab-stops, no screen-reader content, no hover/click
18
- * leaks from the invisible layer (WCAG aria-hidden-focus).
19
- * - MOTION RESPECT: `prefers-reduced-motion` collapses the fade to an
20
- * instant swap.
21
- * - The ACTIVE panel takes `z-[1]` so the incoming layer composites on top
22
- * during the crossfade regardless of DOM order.
23
- *
24
- * This deliberately complements (not replaces) <TabContent>, which MOUNTS one
25
- * panel at a time — right for heavy admin surfaces that should unmount when
26
- * hidden. CrossfadePanels is for surfaces whose panels are cheap enough to
27
- * keep alive and whose switch must be seamless.
28
- *
29
- * NOTE for marquee/animated panel content: hidden panels stay mounted and
30
- * their animations keep running unless the content self-pauses. CardsStrip
31
- * panels are fine (its rAF gates on near-viewport + visibility), but a
32
- * consumer embedding heavier always-on content should pause it via its own
33
- * visibility signal.
34
- */
35
- import React from 'react';
36
- export interface CrossfadePanel {
37
- id: string;
38
- content: React.ReactNode;
39
- }
40
- export interface CrossfadePanelsProps {
41
- /** Which panel is shown. Unknown id → all panels hidden (renders the
42
- * stack's reserved height, nothing visible). */
43
- activeId: string | undefined;
44
- panels: ReadonlyArray<CrossfadePanel>;
45
- /** Crossfade duration in ms. Default 300. */
46
- durationMs?: number;
47
- className?: string;
48
- /** Extra classes for every panel wrapper (e.g. `min-w-0` is built in). */
49
- panelClassName?: string;
50
- }
51
- export declare function CrossfadePanels({ activeId, panels, durationMs, className, panelClassName, }: CrossfadePanelsProps): React.JSX.Element | null;
52
- //# sourceMappingURL=crossfade-panels.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crossfade-panels.d.ts","sourceRoot":"","sources":["../../../src/components/ui/crossfade-panels.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC;qDACiD;IACjD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACrC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,MAAM,EACN,UAAgB,EAChB,SAAS,EACT,cAAc,GACf,EAAE,oBAAoB,4BAwBtB"}
@@ -1,77 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * THE center media glyphs — the single visual identity for every play/unmute
5
- * affordance over video, across the whole project: a SOLID WHITE GLYPH
6
- * (`text-ods-text-primary`), NO background disc, with a soft drop-shadow for
7
- * legibility over arbitrary frames. Accent color appears ONLY while the
8
- * icon's own control is hovered (hosts pass `group-hover:text-ods-accent`;
9
- * mux-player controls get the same via `::part(button):hover` in
10
- * styles/app-globals.css).
11
- *
12
- * Glyphs come from THE icon system — never inline SVG paths here:
13
- * PlayFilledIcon / VolumeOffFilledIcon (components/icons — the FILLED
14
- * media-chrome-matching glyphs, so custom affordances are pixel-identical to
15
- * MuxPlayer's native center button on real players).
16
- *
17
- * Consumers:
18
- * - <VideoBiteCard> resting/paused posters (md)
19
- * - <YouTubeFacade> poster (lg)
20
- * - <MediaCarousel> video thumbnails (sm)
21
- * - <FilePlayer>'s unmute chip (VideoUnmuteGlyph, md)
22
- * - MuxPlayer's native center pre-play button is stripped to the same bare
23
- * glyph language via CSS (see styles/app-globals.css).
24
- */
25
-
26
- import React from 'react'
27
- import { PlayFilledIcon } from '../icons/play-filled-icon'
28
- import { VolumeOffFilledIcon } from '../icons/volume-off-filled-icon'
29
- import { cn } from '../../utils/cn'
30
-
31
- export type VideoCenterBadgeSize = 'sm' | 'md' | 'lg'
32
-
33
- const SIZES: Record<VideoCenterBadgeSize, number> = {
34
- sm: 20, // gallery thumbnails
35
- md: 56, // strip cards + unmute chip
36
- lg: 64, // hero facades
37
- }
38
-
39
- /** Soft legibility shadow — NOT a background (per design: bare glyphs). */
40
- const GLYPH_SHADOW = 'drop-shadow(0 1px 4px rgba(0,0,0,0.5))'
41
-
42
- export interface VideoPlayBadgeProps {
43
- size?: VideoCenterBadgeSize
44
- className?: string
45
- }
46
-
47
- /** Bare play glyph (the icon system's PlayIcon). Decorative
48
- * (`pointer-events-none`) — the host surface owns activation. */
49
- export function VideoPlayBadge({ size = 'md', className }: VideoPlayBadgeProps): React.ReactElement {
50
- return (
51
- <div
52
- className={cn('pointer-events-none flex items-center justify-center text-ods-text-primary transition-colors', className)}
53
- style={{ filter: GLYPH_SHADOW }}
54
- >
55
- <PlayFilledIcon size={SIZES[size]} color="currentColor" />
56
- </div>
57
- )
58
- }
59
-
60
- export interface VideoUnmuteGlyphProps {
61
- size?: VideoCenterBadgeSize
62
- className?: string
63
- }
64
-
65
- /** Bare muted-volume glyph (the icon system's VolumeOffFilledIcon). Rendered
66
- * by FilePlayer's unmute button; exported here so play + unmute share one
67
- * identity. */
68
- export function VideoUnmuteGlyph({ size = 'md', className }: VideoUnmuteGlyphProps): React.ReactElement {
69
- return (
70
- <VolumeOffFilledIcon
71
- size={SIZES[size]}
72
- color="currentColor"
73
- className={className}
74
- style={{ filter: GLYPH_SHADOW }}
75
- />
76
- )
77
- }
@@ -1,36 +0,0 @@
1
- import type { SVGProps } from "react";
2
-
3
- export interface PlayFilledIconProps
4
- extends Omit<SVGProps<SVGSVGElement>, "width" | "height"> {
5
- className?: string;
6
- size?: number;
7
- color?: string;
8
- }
9
-
10
- /**
11
- * Solid play triangle — the SAME glyph media-chrome/MuxPlayer renders in its
12
- * native center play button, so custom video affordances (strip cards,
13
- * facades, carousels) stay pixel-consistent with real player chrome.
14
- * Hand-maintained (not in the Figma-generated set, which has only the
15
- * outline `PlayIcon`).
16
- */
17
- export function PlayFilledIcon({
18
- className = "",
19
- size = 24,
20
- color = "currentColor",
21
- ...props
22
- }: PlayFilledIconProps) {
23
- return (
24
- <svg
25
- xmlns="http://www.w3.org/2000/svg"
26
- width={size}
27
- height={size}
28
- fill="none"
29
- viewBox="0 0 24 24"
30
- className={className}
31
- {...props}
32
- >
33
- <path fill={color} d="m6 21 15-9L6 3v18Z" />
34
- </svg>
35
- );
36
- }
@@ -1,38 +0,0 @@
1
- import type { SVGProps } from "react";
2
-
3
- export interface VolumeOffFilledIconProps
4
- extends Omit<SVGProps<SVGSVGElement>, "width" | "height"> {
5
- className?: string;
6
- size?: number;
7
- color?: string;
8
- }
9
-
10
- /**
11
- * Solid muted-volume glyph (speaker + slash) — the filled companion to
12
- * `PlayFilledIcon`, matching media-chrome's icon family so video unmute
13
- * affordances read identically to real player chrome. Hand-maintained (the
14
- * Figma-generated set has only outline volume icons).
15
- */
16
- export function VolumeOffFilledIcon({
17
- className = "",
18
- size = 24,
19
- color = "currentColor",
20
- ...props
21
- }: VolumeOffFilledIconProps) {
22
- return (
23
- <svg
24
- xmlns="http://www.w3.org/2000/svg"
25
- width={size}
26
- height={size}
27
- fill="none"
28
- viewBox="0 0 24 24"
29
- className={className}
30
- {...props}
31
- >
32
- <path
33
- fill={color}
34
- d="M16.5 12A4.5 4.5 0 0 0 14 7.97v2.21l2.45 2.45c.03-.2.05-.41.05-.63Zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51A8.796 8.796 0 0 0 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71ZM4.27 3 3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06a8.99 8.99 0 0 0 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3ZM12 4 9.91 6.09 12 8.18V4Z"
35
- />
36
- </svg>
37
- );
38
- }
@@ -1,88 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * <CrossfadePanels> — THE keep-mounted tab-panel stack: every panel stays in
5
- * the DOM, stacked in the SAME grid cell, and switching is an opacity
6
- * crossfade. Use it under any tab control (TabNavigation, TabSelector, …)
7
- * whenever panels are content surfaces where height stability and a soft
8
- * switch matter (strips, media rails, dashboards-in-view).
9
- *
10
- * Invariants encoded HERE exactly once (so no consumer re-derives them):
11
- * - HEIGHT LOCK: grid items in one cell size the row to max(panel heights) —
12
- * switching never shifts the page (no CLS), and surrounding layout treats
13
- * the stack as one constant-height block.
14
- * - FADE-THEN-HIDE: `visibility` transitions alongside `opacity`; per the CSS
15
- * transitions spec's special visibility interpolation the outgoing panel
16
- * stays paintable until the fade completes, THEN becomes `hidden` — no
17
- * pop-out, and the settled hidden panel is fully removed from paint.
18
- * - DEAD WHILE HIDDEN: `inert` + `aria-hidden` + `pointer-events-none` on
19
- * inactive panels — no tab-stops, no screen-reader content, no hover/click
20
- * leaks from the invisible layer (WCAG aria-hidden-focus).
21
- * - MOTION RESPECT: `prefers-reduced-motion` collapses the fade to an
22
- * instant swap.
23
- * - The ACTIVE panel takes `z-[1]` so the incoming layer composites on top
24
- * during the crossfade regardless of DOM order.
25
- *
26
- * This deliberately complements (not replaces) <TabContent>, which MOUNTS one
27
- * panel at a time — right for heavy admin surfaces that should unmount when
28
- * hidden. CrossfadePanels is for surfaces whose panels are cheap enough to
29
- * keep alive and whose switch must be seamless.
30
- *
31
- * NOTE for marquee/animated panel content: hidden panels stay mounted and
32
- * their animations keep running unless the content self-pauses. CardsStrip
33
- * panels are fine (its rAF gates on near-viewport + visibility), but a
34
- * consumer embedding heavier always-on content should pause it via its own
35
- * visibility signal.
36
- */
37
-
38
- import React from 'react'
39
- import { cn } from '../../utils/cn'
40
-
41
- export interface CrossfadePanel {
42
- id: string
43
- content: React.ReactNode
44
- }
45
-
46
- export interface CrossfadePanelsProps {
47
- /** Which panel is shown. Unknown id → all panels hidden (renders the
48
- * stack's reserved height, nothing visible). */
49
- activeId: string | undefined
50
- panels: ReadonlyArray<CrossfadePanel>
51
- /** Crossfade duration in ms. Default 300. */
52
- durationMs?: number
53
- className?: string
54
- /** Extra classes for every panel wrapper (e.g. `min-w-0` is built in). */
55
- panelClassName?: string
56
- }
57
-
58
- export function CrossfadePanels({
59
- activeId,
60
- panels,
61
- durationMs = 300,
62
- className,
63
- panelClassName,
64
- }: CrossfadePanelsProps) {
65
- if (panels.length === 0) return null
66
- return (
67
- <div className={cn('grid w-full', className)}>
68
- {panels.map(p => {
69
- const active = p.id === activeId
70
- return (
71
- <div
72
- key={p.id}
73
- className={cn(
74
- 'col-start-1 row-start-1 min-w-0 transition-[opacity,visibility] ease-out motion-reduce:transition-none',
75
- active ? 'visible opacity-100 z-[1]' : 'invisible opacity-0 pointer-events-none',
76
- panelClassName,
77
- )}
78
- style={{ transitionDuration: `${durationMs}ms` }}
79
- aria-hidden={!active || undefined}
80
- inert={!active || undefined}
81
- >
82
- {p.content}
83
- </div>
84
- )
85
- })}
86
- </div>
87
- )
88
- }