@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.
- package/dist/{chunk-MNQVBME4.js → chunk-2OOZASQE.js} +3 -3
- package/dist/{chunk-WBLRUO3F.cjs → chunk-2U3YPWHG.cjs} +3 -3
- package/dist/{chunk-WBLRUO3F.cjs.map → chunk-2U3YPWHG.cjs.map} +1 -1
- package/dist/{chunk-MGJZQ3EE.js → chunk-3E4BDAHJ.js} +2 -2
- package/dist/{chunk-WJSUUOPU.cjs → chunk-43C5ECNT.cjs} +40 -40
- package/dist/{chunk-WJSUUOPU.cjs.map → chunk-43C5ECNT.cjs.map} +1 -1
- package/dist/{chunk-PE37UDPF.cjs → chunk-55SNCMFS.cjs} +40 -40
- package/dist/{chunk-PE37UDPF.cjs.map → chunk-55SNCMFS.cjs.map} +1 -1
- package/dist/{chunk-JWBRDNYH.cjs → chunk-743FCO64.cjs} +31 -31
- package/dist/{chunk-JWBRDNYH.cjs.map → chunk-743FCO64.cjs.map} +1 -1
- package/dist/{chunk-LBDKAMOH.cjs → chunk-BB7TZ6KS.cjs} +75 -75
- package/dist/{chunk-LBDKAMOH.cjs.map → chunk-BB7TZ6KS.cjs.map} +1 -1
- package/dist/{chunk-B2K5COVE.js → chunk-CK5UZLIN.js} +3189 -3305
- package/dist/chunk-CK5UZLIN.js.map +1 -0
- package/dist/{chunk-WXOIEYXW.js → chunk-D4F7ZLJG.js} +5 -5
- package/dist/{chunk-7Q2DZEUA.cjs → chunk-DB6CUWTL.cjs} +32 -32
- package/dist/{chunk-7Q2DZEUA.cjs.map → chunk-DB6CUWTL.cjs.map} +1 -1
- package/dist/{chunk-FZIMFLJG.cjs → chunk-HPQKX5IW.cjs} +15 -15
- package/dist/{chunk-FZIMFLJG.cjs.map → chunk-HPQKX5IW.cjs.map} +1 -1
- package/dist/{chunk-N4R7TRF3.js → chunk-IVXOR2IA.js} +2 -2
- package/dist/{chunk-URODM26E.js → chunk-J6TAK6HE.js} +6 -6
- package/dist/{chunk-VDDNJ6XC.js → chunk-JNU3YPLP.js} +5 -5
- package/dist/{chunk-2TBXIW7L.js → chunk-K5FRWPWF.js} +3 -3
- package/dist/{chunk-ZSZRJWY3.js → chunk-KQESCGVG.js} +2 -2
- package/dist/{chunk-N7YBNHVT.js → chunk-LQHMXPOJ.js} +509 -563
- package/dist/chunk-LQHMXPOJ.js.map +1 -0
- package/dist/{chunk-LPH2JDOW.cjs → chunk-LWNPMLIH.cjs} +2 -56
- package/dist/chunk-LWNPMLIH.cjs.map +1 -0
- package/dist/{chunk-YEWGFWNM.cjs → chunk-M6NPDNVB.cjs} +29 -29
- package/dist/{chunk-YEWGFWNM.cjs.map → chunk-M6NPDNVB.cjs.map} +1 -1
- package/dist/{chunk-C4DHYDXB.cjs → chunk-OAENYOKC.cjs} +12 -12
- package/dist/{chunk-C4DHYDXB.cjs.map → chunk-OAENYOKC.cjs.map} +1 -1
- package/dist/{chunk-XYT5PIKZ.cjs → chunk-SBWTMJPQ.cjs} +5 -5
- package/dist/{chunk-XYT5PIKZ.cjs.map → chunk-SBWTMJPQ.cjs.map} +1 -1
- package/dist/{chunk-2DGA5LHT.cjs → chunk-T5F54MN4.cjs} +19 -19
- package/dist/{chunk-2DGA5LHT.cjs.map → chunk-T5F54MN4.cjs.map} +1 -1
- package/dist/{chunk-Y3FREU4B.js → chunk-TTHTO5H5.js} +7 -7
- package/dist/{chunk-MQXUIYYN.js → chunk-VTR4QDL2.js} +4 -4
- package/dist/{chunk-GKRJOS6S.js → chunk-WCDM226S.js} +3 -3
- package/dist/{chunk-4KWIQEZT.js → chunk-WWHPTP4B.js} +2 -2
- package/dist/{chunk-4BVRLCCA.cjs → chunk-XNAYZHPK.cjs} +73 -73
- package/dist/{chunk-4BVRLCCA.cjs.map → chunk-XNAYZHPK.cjs.map} +1 -1
- package/dist/{chunk-HMTOQGYU.cjs → chunk-Z6PAD2UN.cjs} +7 -7
- package/dist/{chunk-HMTOQGYU.cjs.map → chunk-Z6PAD2UN.cjs.map} +1 -1
- package/dist/{chunk-G42EXM23.js → chunk-ZFK4HHRX.js} +2 -2
- package/dist/{chunk-VVO7AZKZ.cjs → chunk-ZUKBC2ZX.cjs} +190 -306
- package/dist/chunk-ZUKBC2ZX.cjs.map +1 -0
- package/dist/components/case-studies/index.cjs +14 -14
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/index.cjs +4 -4
- package/dist/components/chat/index.js +3 -3
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +4 -8
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.d.ts +0 -1
- package/dist/components/features/index.d.ts.map +1 -1
- package/dist/components/features/index.js +3 -7
- package/dist/components/features/video-bites-strip.d.ts.map +1 -1
- package/dist/components/features/video.d.ts +4 -7
- package/dist/components/features/video.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/icons/index.cjs +2 -6
- package/dist/components/icons/index.cjs.map +1 -1
- package/dist/components/icons/index.d.ts +0 -2
- package/dist/components/icons/index.d.ts.map +1 -1
- package/dist/components/icons/index.js +1 -5
- package/dist/components/index.cjs +142 -152
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +12 -22
- package/dist/components/index.js.map +1 -1
- package/dist/components/media-carousel.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +8 -8
- package/dist/components/onboarding-guides/index.js +7 -7
- package/dist/components/related-content/index.cjs +6 -6
- package/dist/components/related-content/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +4 -6
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +0 -1
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +3 -5
- package/dist/components/ui/tab-navigation.d.ts +2 -6
- package/dist/components/ui/tab-navigation.d.ts.map +1 -1
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +4 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -13
- package/package.json +4 -4
- package/src/components/features/index.ts +0 -1
- package/src/components/features/video-bites-strip.tsx +15 -73
- package/src/components/features/video.tsx +28 -51
- package/src/components/icons/index.ts +0 -2
- package/src/components/media-carousel.tsx +4 -2
- package/src/components/ui/index.ts +0 -1
- package/src/components/ui/tab-navigation.tsx +14 -31
- package/src/styles/app-globals.css +0 -23
- package/dist/chunk-B2K5COVE.js.map +0 -1
- package/dist/chunk-LPH2JDOW.cjs.map +0 -1
- package/dist/chunk-N7YBNHVT.js.map +0 -1
- package/dist/chunk-VVO7AZKZ.cjs.map +0 -1
- package/dist/components/features/video-center-badge.d.ts +0 -40
- package/dist/components/features/video-center-badge.d.ts.map +0 -1
- package/dist/components/icons/play-filled-icon.d.ts +0 -15
- package/dist/components/icons/play-filled-icon.d.ts.map +0 -1
- package/dist/components/icons/volume-off-filled-icon.d.ts +0 -14
- package/dist/components/icons/volume-off-filled-icon.d.ts.map +0 -1
- package/dist/components/ui/crossfade-panels.d.ts +0 -52
- package/dist/components/ui/crossfade-panels.d.ts.map +0 -1
- package/src/components/features/video-center-badge.tsx +0 -77
- package/src/components/icons/play-filled-icon.tsx +0 -36
- package/src/components/icons/volume-off-filled-icon.tsx +0 -38
- package/src/components/ui/crossfade-panels.tsx +0 -88
- /package/dist/{chunk-MNQVBME4.js.map → chunk-2OOZASQE.js.map} +0 -0
- /package/dist/{chunk-MGJZQ3EE.js.map → chunk-3E4BDAHJ.js.map} +0 -0
- /package/dist/{chunk-WXOIEYXW.js.map → chunk-D4F7ZLJG.js.map} +0 -0
- /package/dist/{chunk-N4R7TRF3.js.map → chunk-IVXOR2IA.js.map} +0 -0
- /package/dist/{chunk-URODM26E.js.map → chunk-J6TAK6HE.js.map} +0 -0
- /package/dist/{chunk-VDDNJ6XC.js.map → chunk-JNU3YPLP.js.map} +0 -0
- /package/dist/{chunk-2TBXIW7L.js.map → chunk-K5FRWPWF.js.map} +0 -0
- /package/dist/{chunk-ZSZRJWY3.js.map → chunk-KQESCGVG.js.map} +0 -0
- /package/dist/{chunk-Y3FREU4B.js.map → chunk-TTHTO5H5.js.map} +0 -0
- /package/dist/{chunk-MQXUIYYN.js.map → chunk-VTR4QDL2.js.map} +0 -0
- /package/dist/{chunk-GKRJOS6S.js.map → chunk-WCDM226S.js.map} +0 -0
- /package/dist/{chunk-4KWIQEZT.js.map → chunk-WWHPTP4B.js.map} +0 -0
- /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
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|