@flamingo-stack/openframe-frontend-core 0.0.775 → 0.0.777

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 (83) hide show
  1. package/dist/case-study-card-FMH622O5.cjs +25 -0
  2. package/dist/{chunk-F67SEXCW.cjs → chunk-3PCSEZNZ.cjs} +53 -53
  3. package/dist/{chunk-R3JX4MXD.cjs → chunk-3ZLPYEL5.cjs} +10 -10
  4. package/dist/{chunk-SWEPHSIP.cjs → chunk-4JZDJ34E.cjs} +17 -17
  5. package/dist/{chunk-DGFDBPO7.cjs → chunk-5GJM7VRR.cjs} +1 -94
  6. package/dist/{chunk-E64HPPRH.cjs → chunk-5PK22JP7.cjs} +50 -50
  7. package/dist/{chunk-57B5RUYD.cjs → chunk-64KBI5MI.cjs} +2 -2
  8. package/dist/{chunk-PMX6QNNN.cjs → chunk-7LJSGOWS.cjs} +18 -16
  9. package/dist/{chunk-ASMNNSUQ.cjs → chunk-7PNRXJX2.cjs} +3 -3
  10. package/dist/{chunk-VAGZJRYV.cjs → chunk-ALA4KHTE.cjs} +6 -6
  11. package/dist/{chunk-VFZFCRAL.cjs → chunk-AQXKXZWB.cjs} +4 -4
  12. package/dist/{chunk-4LFB4YY3.cjs → chunk-BDDOC425.cjs} +8 -8
  13. package/dist/{chunk-VFUMM6JC.cjs → chunk-BEMGJDXI.cjs} +2 -2
  14. package/dist/{chunk-HY6BCZH7.cjs → chunk-BNUZKBNV.cjs} +3 -3
  15. package/dist/{chunk-Y3EBUFX4.cjs → chunk-CGQ7CL62.cjs} +213 -1647
  16. package/dist/{chunk-ODF3KCRK.cjs → chunk-DOM5CUEY.cjs} +33 -31
  17. package/dist/{chunk-36GYLB3Z.cjs → chunk-G2N7INFT.cjs} +28 -28
  18. package/dist/{chunk-42JGOJCB.cjs → chunk-HXLOCZMG.cjs} +595 -591
  19. package/dist/{chunk-CZIMISAR.cjs → chunk-JB2SEF6Q.cjs} +7 -7
  20. package/dist/{chunk-6SJYFUGD.cjs → chunk-JMFF3L3T.cjs} +28 -26
  21. package/dist/{chunk-LJT2KRE2.cjs → chunk-KLTUTZBO.cjs} +24 -24
  22. package/dist/{chunk-EHJE3UWZ.cjs → chunk-LBGAHB6X.cjs} +20 -20
  23. package/dist/{chunk-TUXPFF4P.cjs → chunk-LGNJTSKB.cjs} +37 -35
  24. package/dist/{chunk-FHTTRWAK.cjs → chunk-LU2DGST4.cjs} +97 -95
  25. package/dist/chunk-MQPTOJMF.cjs +1504 -0
  26. package/dist/{chunk-XXJL5GY3.cjs → chunk-OJZBZH56.cjs} +3 -3
  27. package/dist/{chunk-TF2XYDH3.cjs → chunk-QIATO42V.cjs} +3 -3
  28. package/dist/{chunk-RB7VLVMD.cjs → chunk-R6BKQKIF.cjs} +9 -7
  29. package/dist/{chunk-BTVO676B.cjs → chunk-S3YDUX2I.cjs} +114 -112
  30. package/dist/{chunk-VISK6LKE.cjs → chunk-SDZG7VV7.cjs} +5 -5
  31. package/dist/{chunk-V3W56L2D.cjs → chunk-SIDDZZKL.cjs} +38 -38
  32. package/dist/chunk-SZHDXXMK.cjs +102 -0
  33. package/dist/{chunk-5YJWT5ZQ.cjs → chunk-T47VAUYR.cjs} +91 -89
  34. package/dist/{chunk-IQQ3SLUK.cjs → chunk-T7NDPPLF.cjs} +23 -21
  35. package/dist/{chunk-5P4TDV7V.cjs → chunk-TUAATMUE.cjs} +5 -93
  36. package/dist/{chunk-KWZ62LPZ.cjs → chunk-TZP7PSPG.cjs} +249 -243
  37. package/dist/{chunk-USMR73ND.cjs → chunk-U5VQFKRZ.cjs} +6 -6
  38. package/dist/{chunk-L5CKY5WA.cjs → chunk-UW6AOF42.cjs} +22 -22
  39. package/dist/chunk-V4FXUIMH.cjs +92 -0
  40. package/dist/{chunk-2JRSYWFP.cjs → chunk-VXAKQRV7.cjs} +5 -5
  41. package/dist/{chunk-3XLDYEQD.cjs → chunk-VY3NGJRH.cjs} +53 -51
  42. package/dist/{chunk-TOPGBOCN.cjs → chunk-WCSWWVPF.cjs} +2 -2
  43. package/dist/{chunk-EQBJHJS7.cjs → chunk-WMZIBRTR.cjs} +2 -2
  44. package/dist/{chunk-5QP3K2CE.cjs → chunk-XEYL6AFZ.cjs} +9 -9
  45. package/dist/{chunk-VDXBACD3.cjs → chunk-XVAVQ4BK.cjs} +116 -82
  46. package/dist/{chunk-5AOKXXHV.cjs → chunk-Y6MQBLTZ.cjs} +4 -4
  47. package/dist/{cloud-tenants-ISGAMTJD.cjs → cloud-tenants-EUH42CCL.cjs} +27 -24
  48. package/dist/components/case-studies/index.cjs +45 -41
  49. package/dist/components/chat/index.cjs +21 -17
  50. package/dist/components/contact/index.cjs +28 -25
  51. package/dist/components/docs/index.cjs +31 -28
  52. package/dist/components/embeds/index.cjs +28 -25
  53. package/dist/components/faq/index.cjs +29 -26
  54. package/dist/components/features/index.cjs +28 -24
  55. package/dist/components/features/use-file-playback.d.ts +6 -4
  56. package/dist/components/features/use-file-playback.d.ts.map +1 -1
  57. package/dist/components/features/use-file-playback.js +16 -7
  58. package/dist/components/help-center-pages/index.cjs +131 -127
  59. package/dist/components/index.cjs +94 -90
  60. package/dist/components/meeting-scheduler/index.cjs +95 -92
  61. package/dist/components/navigation/index.cjs +30 -27
  62. package/dist/components/navigation/nav-panel.d.ts.map +1 -1
  63. package/dist/components/navigation/nav-panel.js +47 -13
  64. package/dist/components/onboarding-guides/index.cjs +30 -27
  65. package/dist/components/product-demo/index.cjs +38 -35
  66. package/dist/components/related-content/index.cjs +15 -12
  67. package/dist/components/tickets/index.cjs +33 -30
  68. package/dist/components/ui/index.cjs +28 -24
  69. package/dist/{devices-AHJX6ACJ.cjs → devices-WL3I23EE.cjs} +28 -25
  70. package/dist/{embeddable-chat-DI7ZZTBP.cjs → embeddable-chat-KEWUGQIF.cjs} +99 -95
  71. package/dist/hooks/index.cjs +12 -10
  72. package/dist/index.cjs +36 -30
  73. package/dist/{knowledge-FH5GVRVP.cjs → knowledge-O3PXUX73.cjs} +28 -25
  74. package/dist/{logs-JBIHHLUQ.cjs → logs-XODCXWYI.cjs} +35 -32
  75. package/dist/{policies-XLJ2ABY5.cjs → policies-CQACBIKK.cjs} +31 -28
  76. package/dist/{remote-session-TC3BZDBZ.cjs → remote-session-TGM2OTTV.cjs} +12 -10
  77. package/dist/{scripts-CQLXM7PP.cjs → scripts-QMM6SEB5.cjs} +34 -31
  78. package/dist/{software-update-7NYZ7L76.cjs → software-update-CCCKS4ZE.cjs} +31 -28
  79. package/dist/{tickets-board-YT25IX3O.cjs → tickets-board-FB5AGLJD.cjs} +16 -14
  80. package/dist/{video-file-player-4TXA7BZF.cjs → video-file-player-SIJW5UWU.cjs} +19 -9
  81. package/package.json +1 -1
  82. package/src/components/features/use-file-playback.ts +33 -14
  83. package/src/components/navigation/nav-panel.tsx +74 -14
@@ -15,26 +15,26 @@ var _chunkDKOLQPE7cjs = require('./chunk-DKOLQPE7.cjs');
15
15
 
16
16
 
17
17
 
18
- var _chunk42JGOJCBcjs = require('./chunk-42JGOJCB.cjs');
19
- require('./chunk-LJT2KRE2.cjs');
20
- require('./chunk-RB7VLVMD.cjs');
18
+ var _chunkHXLOCZMGcjs = require('./chunk-HXLOCZMG.cjs');
19
+ require('./chunk-KLTUTZBO.cjs');
20
+ require('./chunk-R6BKQKIF.cjs');
21
21
 
22
22
 
23
- var _chunkV3W56L2Dcjs = require('./chunk-V3W56L2D.cjs');
23
+ var _chunkSIDDZZKLcjs = require('./chunk-SIDDZZKL.cjs');
24
24
  require('./chunk-HQQE74RO.cjs');
25
25
  require('./chunk-DEY6XXGO.cjs');
26
- require('./chunk-E64HPPRH.cjs');
27
- require('./chunk-2JRSYWFP.cjs');
26
+ require('./chunk-5PK22JP7.cjs');
27
+ require('./chunk-VXAKQRV7.cjs');
28
28
  require('./chunk-24I6RFVU.cjs');
29
29
  require('./chunk-A6P6DHEZ.cjs');
30
30
  require('./chunk-MZ4KBSH7.cjs');
31
- require('./chunk-TOPGBOCN.cjs');
31
+ require('./chunk-WCSWWVPF.cjs');
32
32
  require('./chunk-C42WIUH6.cjs');
33
- require('./chunk-BTVO676B.cjs');
34
- require('./chunk-KWZ62LPZ.cjs');
35
- require('./chunk-EHJE3UWZ.cjs');
33
+ require('./chunk-S3YDUX2I.cjs');
34
+ require('./chunk-TZP7PSPG.cjs');
35
+ require('./chunk-LBGAHB6X.cjs');
36
36
  require('./chunk-KKAY6GPU.cjs');
37
- require('./chunk-5QP3K2CE.cjs');
37
+ require('./chunk-XEYL6AFZ.cjs');
38
38
  require('./chunk-LELS4XMX.cjs');
39
39
  require('./chunk-ZOZR3QI2.cjs');
40
40
  require('./chunk-OMV5S5PI.cjs');
@@ -1824,20 +1824,21 @@ require('./chunk-LMBYZITR.cjs');
1824
1824
  require('./chunk-TMVC7S2R.cjs');
1825
1825
  require('./chunk-IYHH5EIO.cjs');
1826
1826
  require('./chunk-XIBCMGBW.cjs');
1827
- require('./chunk-CZIMISAR.cjs');
1828
- require('./chunk-XXJL5GY3.cjs');
1829
- require('./chunk-57B5RUYD.cjs');
1827
+ require('./chunk-JB2SEF6Q.cjs');
1828
+ require('./chunk-OJZBZH56.cjs');
1829
+ require('./chunk-64KBI5MI.cjs');
1830
1830
  require('./chunk-JKX2C3I2.cjs');
1831
1831
  require('./chunk-7DNL734S.cjs');
1832
1832
  require('./chunk-WWUSFOJ7.cjs');
1833
1833
  require('./chunk-SKI6NKOE.cjs');
1834
1834
  require('./chunk-EWPR7662.cjs');
1835
- require('./chunk-TUXPFF4P.cjs');
1836
- require('./chunk-Y3EBUFX4.cjs');
1837
- require('./chunk-R3JX4MXD.cjs');
1835
+ require('./chunk-LGNJTSKB.cjs');
1836
+ require('./chunk-CGQ7CL62.cjs');
1837
+ require('./chunk-MQPTOJMF.cjs');
1838
+ require('./chunk-3ZLPYEL5.cjs');
1838
1839
  require('./chunk-SETFUCZA.cjs');
1839
- require('./chunk-VFUMM6JC.cjs');
1840
- require('./chunk-HY6BCZH7.cjs');
1840
+ require('./chunk-BEMGJDXI.cjs');
1841
+ require('./chunk-BNUZKBNV.cjs');
1841
1842
  require('./chunk-S5C3OZCO.cjs');
1842
1843
  require('./chunk-32ASZMTV.cjs');
1843
1844
  require('./chunk-OOYBIS7D.cjs');
@@ -1847,11 +1848,13 @@ require('./chunk-ORO54HDF.cjs');
1847
1848
  require('./chunk-RUHKTWGB.cjs');
1848
1849
  require('./chunk-BLH2SFOO.cjs');
1849
1850
  require('./chunk-3LW5TD54.cjs');
1850
- require('./chunk-ASMNNSUQ.cjs');
1851
+ require('./chunk-7PNRXJX2.cjs');
1851
1852
  require('./chunk-NTPX5GXI.cjs');
1852
- require('./chunk-VFZFCRAL.cjs');
1853
- require('./chunk-5P4TDV7V.cjs');
1854
- require('./chunk-DGFDBPO7.cjs');
1853
+ require('./chunk-AQXKXZWB.cjs');
1854
+ require('./chunk-V4FXUIMH.cjs');
1855
+ require('./chunk-SZHDXXMK.cjs');
1856
+ require('./chunk-TUAATMUE.cjs');
1857
+ require('./chunk-5GJM7VRR.cjs');
1855
1858
  require('./chunk-E76ONBKF.cjs');
1856
1859
  require('./chunk-UJ7AXHRZ.cjs');
1857
1860
  require('./chunk-YXDHVHB2.cjs');
@@ -1918,14 +1921,14 @@ var noop = () => {
1918
1921
  var HIDDEN_WHEN_COMPACT = ["organization"];
1919
1922
  function StaticPackageField({ value }) {
1920
1923
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1921
- _chunkV3W56L2Dcjs.Autocomplete,
1924
+ _chunkSIDDZZKLcjs.Autocomplete,
1922
1925
  {
1923
- label: _chunk42JGOJCBcjs.PACKAGE_SEARCH_LABEL,
1926
+ label: _chunkHXLOCZMGcjs.PACKAGE_SEARCH_LABEL,
1924
1927
  labelVariant: "large",
1925
1928
  options: value ? [{ value: value.id, label: value.name, description: _nullishCoalesce(value.description, () => ( void 0)) }] : [],
1926
1929
  value: _nullishCoalesce(_optionalChain([value, 'optionalAccess', _ => _.id]), () => ( null)),
1927
1930
  onChange: noop,
1928
- placeholder: _chunk42JGOJCBcjs.PACKAGE_SEARCH_PLACEHOLDER
1931
+ placeholder: _chunkHXLOCZMGcjs.PACKAGE_SEARCH_PLACEHOLDER
1929
1932
  }
1930
1933
  );
1931
1934
  }
@@ -1939,7 +1942,7 @@ function SoftwareUpdateScreen({ compact = false }) {
1939
1942
  [fixture.devices, fixture.selectedIds]
1940
1943
  );
1941
1944
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full bg-ods-bg pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1942
- _chunk42JGOJCBcjs.SoftwareActionForm,
1945
+ _chunkHXLOCZMGcjs.SoftwareActionForm,
1943
1946
  {
1944
1947
  action: fixture.action,
1945
1948
  showHeader: false,
@@ -1951,7 +1954,7 @@ function SoftwareUpdateScreen({ compact = false }) {
1951
1954
  initialValues: fixture.initialValues,
1952
1955
  renderPackageSearch,
1953
1956
  renderDevicePicker: () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1954
- _chunk42JGOJCBcjs.DeviceSelector,
1957
+ _chunkHXLOCZMGcjs.DeviceSelector,
1955
1958
  {
1956
1959
  devices: selected,
1957
1960
  loading: false,
@@ -10,9 +10,9 @@ var _chunkDKOLQPE7cjs = require('./chunk-DKOLQPE7.cjs');
10
10
 
11
11
 
12
12
 
13
- var _chunkLJT2KRE2cjs = require('./chunk-LJT2KRE2.cjs');
14
- require('./chunk-2JRSYWFP.cjs');
15
- require('./chunk-EHJE3UWZ.cjs');
13
+ var _chunkKLTUTZBOcjs = require('./chunk-KLTUTZBO.cjs');
14
+ require('./chunk-VXAKQRV7.cjs');
15
+ require('./chunk-LBGAHB6X.cjs');
16
16
  require('./chunk-LELS4XMX.cjs');
17
17
  require('./chunk-ZOZR3QI2.cjs');
18
18
  require('./chunk-OMV5S5PI.cjs');
@@ -1802,11 +1802,11 @@ require('./chunk-LMBYZITR.cjs');
1802
1802
  require('./chunk-TMVC7S2R.cjs');
1803
1803
  require('./chunk-IYHH5EIO.cjs');
1804
1804
  require('./chunk-XIBCMGBW.cjs');
1805
- require('./chunk-57B5RUYD.cjs');
1805
+ require('./chunk-64KBI5MI.cjs');
1806
1806
  require('./chunk-WWUSFOJ7.cjs');
1807
1807
  require('./chunk-SKI6NKOE.cjs');
1808
- require('./chunk-R3JX4MXD.cjs');
1809
- require('./chunk-HY6BCZH7.cjs');
1808
+ require('./chunk-3ZLPYEL5.cjs');
1809
+ require('./chunk-BNUZKBNV.cjs');
1810
1810
  require('./chunk-S5C3OZCO.cjs');
1811
1811
  require('./chunk-32ASZMTV.cjs');
1812
1812
  require('./chunk-OOYBIS7D.cjs');
@@ -1814,9 +1814,11 @@ require('./chunk-4IYNDV3G.cjs');
1814
1814
  require('./chunk-6VOOPMP5.cjs');
1815
1815
  require('./chunk-ORO54HDF.cjs');
1816
1816
  require('./chunk-RUHKTWGB.cjs');
1817
- require('./chunk-ASMNNSUQ.cjs');
1818
- require('./chunk-5P4TDV7V.cjs');
1819
- require('./chunk-DGFDBPO7.cjs');
1817
+ require('./chunk-7PNRXJX2.cjs');
1818
+ require('./chunk-V4FXUIMH.cjs');
1819
+ require('./chunk-SZHDXXMK.cjs');
1820
+ require('./chunk-TUAATMUE.cjs');
1821
+ require('./chunk-5GJM7VRR.cjs');
1820
1822
  require('./chunk-E76ONBKF.cjs');
1821
1823
  require('./chunk-XIFEZ2JT.cjs');
1822
1824
  require('./chunk-Z74QE57T.cjs');
@@ -1838,7 +1840,7 @@ function buildTicketsBoardFixture(cast) {
1838
1840
  const dana = assignee(cast.person("dana"));
1839
1841
  const alex = assignee(cast.person("alex"));
1840
1842
  return [
1841
- _chunkLJT2KRE2cjs.columnFromTicketStatus.call(void 0, "ACTIVE", [
1843
+ _chunkKLTUTZBOcjs.columnFromTicketStatus.call(void 0, "ACTIVE", [
1842
1844
  ticket("tk-1051", "Printer offline at the front desk", "ACTIVE", {
1843
1845
  ticketNumber: "1051",
1844
1846
  agent: "fae",
@@ -1856,7 +1858,7 @@ function buildTicketsBoardFixture(cast) {
1856
1858
  tags: ["onboarding"]
1857
1859
  })
1858
1860
  ]),
1859
- _chunkLJT2KRE2cjs.columnFromTicketStatus.call(void 0, "TECH_REQUIRED", [
1861
+ _chunkKLTUTZBOcjs.columnFromTicketStatus.call(void 0, "TECH_REQUIRED", [
1860
1862
  ticket("tk-1049", "Acrobat Pro for Maya", "TECH_REQUIRED", {
1861
1863
  ticketNumber: "1049",
1862
1864
  agent: "fae",
@@ -1880,7 +1882,7 @@ function buildTicketsBoardFixture(cast) {
1880
1882
  escalatedByUser: true
1881
1883
  })
1882
1884
  ]),
1883
- _chunkLJT2KRE2cjs.columnFromTicketStatus.call(void 0, "ON_HOLD", [
1885
+ _chunkKLTUTZBOcjs.columnFromTicketStatus.call(void 0, "ON_HOLD", [
1884
1886
  ticket("tk-1046", "Replace the conference room display", "ON_HOLD", {
1885
1887
  ticketNumber: "1046",
1886
1888
  organizationName: _chunkDKOLQPE7cjs.DEMO_ORGANIZATIONS.acme.name,
@@ -1889,7 +1891,7 @@ function buildTicketsBoardFixture(cast) {
1889
1891
  activity: { kind: "waiting-external" }
1890
1892
  })
1891
1893
  ]),
1892
- _chunkLJT2KRE2cjs.columnFromTicketStatus.call(void 0,
1894
+ _chunkKLTUTZBOcjs.columnFromTicketStatus.call(void 0,
1893
1895
  "RESOLVED",
1894
1896
  [
1895
1897
  ticket("tk-1048", "Slow laptop", "RESOLVED", {
@@ -1925,7 +1927,7 @@ function TicketsBoardScreen({ compact = false }) {
1925
1927
  const cast = _chunkSTEJZPIOcjs.useProductDemoCast.call(void 0, );
1926
1928
  const board = _react.useMemo.call(void 0, () => buildTicketsBoardFixture(cast), [cast]);
1927
1929
  const columns = compact ? board.filter((column) => column.id !== "ON_HOLD") : board;
1928
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full bg-ods-bg p-[var(--spacing-system-m)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLJT2KRE2cjs.Board, { columns, onChange: noop, initialCollapsed: compact ? void 0 : FOLDED }) });
1930
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full bg-ods-bg p-[var(--spacing-system-m)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkKLTUTZBOcjs.Board, { columns, onChange: noop, initialCollapsed: compact ? void 0 : FOLDED }) });
1929
1931
  }
1930
1932
 
1931
1933
 
@@ -19,7 +19,8 @@ require('./chunk-4IYNDV3G.cjs');
19
19
  require('./chunk-NTPX5GXI.cjs');
20
20
 
21
21
 
22
- var _chunkDGFDBPO7cjs = require('./chunk-DGFDBPO7.cjs');
22
+ var _chunkSZHDXXMKcjs = require('./chunk-SZHDXXMK.cjs');
23
+ require('./chunk-5GJM7VRR.cjs');
23
24
  require('./chunk-UJ7AXHRZ.cjs');
24
25
 
25
26
 
@@ -101,6 +102,7 @@ function useMediaEvent(mediaRef, type, handler) {
101
102
  return () => onLiveElement(() => _optionalChain([element, 'access', _6 => _6.removeEventListener, 'optionalCall', _7 => _7(type, listener)]));
102
103
  }, [mediaRef, type, handlerRef]);
103
104
  }
105
+ var INTERRUPTED_PLAY_RETRIES = 2;
104
106
  async function play(element) {
105
107
  try {
106
108
  await _optionalChain([element, 'access', _8 => _8.play, 'optionalCall', _9 => _9()]);
@@ -117,12 +119,16 @@ function usePlaybackSound(mediaRef, { autoPlay, autoPlayUnmuted, startMuted, onM
117
119
  const started = play(element);
118
120
  setBlocked(false);
119
121
  setMutedFallback(true);
120
- if (await started !== "playing" && wanted()) setBlocked(true);
122
+ const outcome = await started;
123
+ if (outcome !== "playing" && wanted()) setBlocked(true);
124
+ return outcome;
121
125
  }, []);
122
126
  const playWithSound = _react.useCallback.call(void 0,
123
127
  async (element, muted, wanted = always) => {
124
128
  onLiveElement(() => Object.assign(element, { muted }));
125
- if (await play(element) === "refused" && wanted()) await playMuted(element, wanted);
129
+ const outcome = await play(element);
130
+ if (outcome === "refused" && wanted()) return playMuted(element, wanted);
131
+ return outcome;
126
132
  },
127
133
  [playMuted]
128
134
  );
@@ -244,11 +250,15 @@ function useHoverPlayback(mediaRef, sound, { playOnHover, playWhenHovered, muted
244
250
  onLiveElement(() => {
245
251
  element.volume = SOUND_VOLUME;
246
252
  });
247
- if (_chunkSETFUCZAcjs.hasUserInteracted.call(void 0, )) {
248
- void playWithSound(element, hostMutedRef.current, wanted);
249
- return;
250
- }
251
- void playMuted(element, wanted);
253
+ const attempt = (retriesLeft) => {
254
+ const played = _chunkSETFUCZAcjs.hasUserInteracted.call(void 0, ) ? playWithSound(element, hostMutedRef.current, wanted) : playMuted(element, wanted);
255
+ void played.then((outcome) => {
256
+ if (outcome === "interrupted" && hovered && element.paused !== false && retriesLeft > 0)
257
+ attempt(retriesLeft - 1);
258
+ });
259
+ };
260
+ attempt(INTERRUPTED_PLAY_RETRIES);
261
+ if (_chunkSETFUCZAcjs.hasUserInteracted.call(void 0, )) return;
252
262
  const onFirstGesture = () => {
253
263
  if (!hovered) return;
254
264
  onLiveElement(() => {
@@ -406,7 +416,7 @@ function FilePlayer({
406
416
  const hover = useHoverPlayback(mediaRef, sound, { playOnHover, playWhenHovered, mutedIntent });
407
417
  const health = usePlaybackHealth(mediaRef, url, !chromeless);
408
418
  useIosNativeVideoFullscreen(mediaRef);
409
- const captions = _chunkDGFDBPO7cjs.useAuthedAssetSrc.call(void 0, captionsUrl, "text/vtt, */*");
419
+ const captions = _chunkSZHDXXMKcjs.useAuthedAssetSrc.call(void 0, captionsUrl, "text/vtt, */*");
410
420
  const player = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
411
421
  _muxplayerreact2.default,
412
422
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.775",
3
+ "version": "0.0.777",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -77,7 +77,10 @@ function useMediaEvent(mediaRef: MediaRef, type: string, handler: () => void): v
77
77
  }
78
78
 
79
79
  /** How a `play()` ended: it plays, the autoplay policy refused it, or something else stopped it (a pause, a teardown). */
80
- type PlayOutcome = 'playing' | 'refused' | 'interrupted';
80
+ /** How many times a hover asks again after its `play()` was aborted (each attempt waits for the element). */
81
+ const INTERRUPTED_PLAY_RETRIES = 2;
82
+
83
+ export type PlayOutcome = 'playing' | 'refused' | 'interrupted';
81
84
 
82
85
  async function play(element: MediaElement): Promise<PlayOutcome> {
83
86
  try {
@@ -100,10 +103,11 @@ type SoundOptions = Pick<
100
103
  export interface PlaybackSound {
101
104
  /** Playback runs muted because the browser refused sound: the unmute control shows. */
102
105
  mutedFallback: boolean;
103
- /** Play with sound (or `muted`, a host's standing choice); refused, play muted. `wanted` says the play is still asked for. */
104
- playWithSound: (element: MediaElement, muted: boolean, wanted?: () => boolean) => Promise<void>;
105
- /** Play muted, and say so. `wanted` says the play is still asked for. */
106
- playMuted: (element: MediaElement, wanted?: () => boolean) => Promise<void>;
106
+ /** Play with sound (or `muted`, a host's standing choice); refused, play muted. `wanted` says the play is still
107
+ * asked for. Resolves with how the last `play()` ended. */
108
+ playWithSound: (element: MediaElement, muted: boolean, wanted?: () => boolean) => Promise<PlayOutcome>;
109
+ /** Play muted, and say so. `wanted` says the play is still asked for. Resolves with how the `play()` ended. */
110
+ playMuted: (element: MediaElement, wanted?: () => boolean) => Promise<PlayOutcome>;
107
111
  /** The muted fallback is over (sound is on, or playback stopped). */
108
112
  endMutedFallback: () => void;
109
113
  /** The unmute control's click: it is the gesture the autoplay policy wants, so sound always starts. */
@@ -125,7 +129,9 @@ export function usePlaybackSound(
125
129
  const started = play(element);
126
130
  setBlocked(false);
127
131
  setMutedFallback(true);
128
- if ((await started) !== 'playing' && wanted()) setBlocked(true);
132
+ const outcome = await started;
133
+ if (outcome !== 'playing' && wanted()) setBlocked(true);
134
+ return outcome;
129
135
  }, []);
130
136
 
131
137
  const playWithSound = useCallback(
@@ -133,7 +139,9 @@ export function usePlaybackSound(
133
139
  onLiveElement(() => Object.assign(element, { muted }));
134
140
  // Only a refusal falls back to muted. A pause that interrupts the play (a
135
141
  // fast hover-out) must not start playback again behind the pointer.
136
- if ((await play(element)) === 'refused' && wanted()) await playMuted(element, wanted);
142
+ const outcome = await play(element);
143
+ if (outcome === 'refused' && wanted()) return playMuted(element, wanted);
144
+ return outcome;
137
145
  },
138
146
  [playMuted],
139
147
  );
@@ -300,13 +308,24 @@ export function useHoverPlayback(
300
308
  onLiveElement(() => {
301
309
  element.volume = SOUND_VOLUME;
302
310
  });
303
- if (hasUserInteracted()) {
304
- void playWithSound(element, hostMutedRef.current, wanted);
305
- return;
306
- }
307
- // No gesture on the page yet, so sound would be refused: start muted with no
308
- // refusal to wait for, and turn the sound on the moment the first gesture lands.
309
- void playMuted(element, wanted);
311
+ // A `play()` can be aborted by the element itself: a player drawn BY this hover (a bite card mounts its player
312
+ // on the first hover) is asked to play while its stream is still attaching, and attaching it aborts the play
313
+ // (AbortError, "interrupted by a new load request"). The first hover on every card did nothing. The play()
314
+ // promise is how the browser and Mux say a play did not happen; while the hover lasts, ask again: a `play()`
315
+ // on a loading element waits until it can play. A hover-out's own pause ends the hover, so it is never retried.
316
+ const attempt = (retriesLeft: number) => {
317
+ const played = hasUserInteracted()
318
+ ? playWithSound(element, hostMutedRef.current, wanted)
319
+ : playMuted(element, wanted);
320
+ void played.then(outcome => {
321
+ if (outcome === 'interrupted' && hovered && element.paused !== false && retriesLeft > 0)
322
+ attempt(retriesLeft - 1);
323
+ });
324
+ };
325
+ attempt(INTERRUPTED_PLAY_RETRIES);
326
+ if (hasUserInteracted()) return;
327
+ // No gesture on the page yet, so sound would be refused: it started muted with no
328
+ // refusal to wait for, and the sound turns on the moment the first gesture lands.
310
329
  const onFirstGesture = () => {
311
330
  if (!hovered) return;
312
331
  onLiveElement(() => {
@@ -1,13 +1,84 @@
1
1
  'use client';
2
2
 
3
3
  import type React from 'react';
4
- import { forwardRef, type HTMLAttributes } from 'react';
4
+ import { forwardRef, useEffect, useSyncExternalStore, type HTMLAttributes } from 'react';
5
5
  import type { NavGroup, NavMenu } from '../../types/navigation';
6
+ import { afterPageLoad } from '../../utils/after-page-load';
6
7
  import { cn } from '../../utils/cn';
7
- import { CaseStudyCard } from '../chat/entity-cards/case-study-card';
8
+ import type { CaseStudyCard as CaseStudyCardComponent } from '../chat/entity-cards/case-study-card';
8
9
  import { NavItemRow } from './nav-item-row';
9
10
  import { defaultRenderSiteNavLink, type SiteNavLinkRenderer } from './site-nav-link';
10
11
 
12
+ /**
13
+ * The featured cards' component (a case study card, with its video hover preview), fetched once the page has loaded,
14
+ * or at once when a menu opens first. The panel is on every page, closed, so a static import put the card and its video
15
+ * code in every page's first-load script, ahead of the page's largest paint (CU-17tkuw5xp4q). The server and the first
16
+ * draw show the closed panel without the cards; they are there before a visitor can open it.
17
+ */
18
+ type FeatureCardComponent = typeof CaseStudyCardComponent;
19
+ let featureCard: FeatureCardComponent | null = null;
20
+ let featureCardLoad: Promise<void> | null = null;
21
+ const featureCardListeners = new Set<() => void>();
22
+
23
+ function loadFeatureCard(): void {
24
+ if (featureCard || featureCardLoad) return;
25
+ featureCardLoad = import('../chat/entity-cards/case-study-card')
26
+ .then(module => {
27
+ featureCard = module.CaseStudyCard;
28
+ for (const listener of featureCardListeners) listener();
29
+ })
30
+ // A failed load is forgotten, so the next open asks again.
31
+ .catch(() => undefined)
32
+ .finally(() => {
33
+ featureCardLoad = null;
34
+ });
35
+ }
36
+
37
+ function subscribeToFeatureCard(listener: () => void): () => void {
38
+ featureCardListeners.add(listener);
39
+ const cancel = afterPageLoad(loadFeatureCard);
40
+ return () => {
41
+ featureCardListeners.delete(listener);
42
+ cancel();
43
+ };
44
+ }
45
+
46
+ const loadedFeatureCard = () => featureCard;
47
+ const noFeatureCard = () => null;
48
+
49
+ /** A menu's featured cards, drawn once their component has arrived. */
50
+ function FeatureCards({
51
+ features,
52
+ open,
53
+ onNavigate,
54
+ }: {
55
+ features: NonNullable<NavMenu['features']>;
56
+ open: boolean;
57
+ onNavigate?: () => void;
58
+ }) {
59
+ const Card = useSyncExternalStore(subscribeToFeatureCard, loadedFeatureCard, noFeatureCard);
60
+ useEffect(() => {
61
+ if (open) loadFeatureCard();
62
+ }, [open]);
63
+ if (!Card) return null;
64
+ return (
65
+ <>
66
+ {features.map(feature => (
67
+ <div key={feature.id} className="min-h-0 min-w-0 overflow-hidden">
68
+ <Card
69
+ size="menu"
70
+ study={feature.study}
71
+ href={feature.href}
72
+ mediaMounted={open}
73
+ onNavigate={onNavigate}
74
+ className="h-full"
75
+ />
76
+ </div>
77
+ ))}
78
+ </>
79
+ );
80
+ }
81
+
11
82
  /** A column with more links than this lays them out in two columns. */
12
83
  const TWO_COLUMN_OVER = 4;
13
84
 
@@ -143,18 +214,7 @@ export const NavPanel = forwardRef<HTMLDivElement, NavPanelProps>(function NavPa
143
214
  // One row of cards, as many as the bar's width holds: a card that
144
215
  // would wrap lands on a zero-height row, where its cell clips it.
145
216
  <div className="grid min-w-0 flex-[3] auto-rows-[0px] grid-cols-[repeat(auto-fit,minmax(240px,1fr))] grid-rows-[minmax(0,1fr)] gap-x-[var(--spacing-system-mf)]">
146
- {menu.features.map(feature => (
147
- <div key={feature.id} className="min-h-0 min-w-0 overflow-hidden">
148
- <CaseStudyCard
149
- size="menu"
150
- study={feature.study}
151
- href={feature.href}
152
- mediaMounted={open}
153
- onNavigate={onNavigate}
154
- className="h-full"
155
- />
156
- </div>
157
- ))}
217
+ <FeatureCards features={menu.features} open={open} onNavigate={onNavigate} />
158
218
  </div>
159
219
  )}
160
220
  {!!menu.sideLinks?.length && (