@flamingo-stack/openframe-frontend-core 0.0.406-snapshot.20260711131925 → 0.0.406

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 (135) hide show
  1. package/dist/{chunk-2B6773QM.cjs → chunk-3KEBI6TP.cjs} +1 -1
  2. package/dist/chunk-3KEBI6TP.cjs.map +1 -0
  3. package/dist/{chunk-HJIRG7R6.js → chunk-3KZXOLFK.js} +4 -4
  4. package/dist/{chunk-43H2WOAW.js → chunk-6WMVBCNA.js} +3 -3
  5. package/dist/{chunk-XFP43YKG.js → chunk-7RVSGGO6.js} +6 -6
  6. package/dist/{chunk-KLBEIJVZ.js → chunk-AYFWYOL6.js} +7 -7
  7. package/dist/{chunk-GMZL4T7C.js → chunk-C3NPMZBI.js} +3 -3
  8. package/dist/{chunk-STGWQFYT.cjs → chunk-CCIBZ7TO.cjs} +5 -5
  9. package/dist/chunk-CCIBZ7TO.cjs.map +1 -0
  10. package/dist/{chunk-Q2MC3CBI.cjs → chunk-CF3LBCNI.cjs} +35 -35
  11. package/dist/{chunk-Q2MC3CBI.cjs.map → chunk-CF3LBCNI.cjs.map} +1 -1
  12. package/dist/{chunk-DOBNDDNE.cjs → chunk-COERBDG4.cjs} +75 -75
  13. package/dist/{chunk-DOBNDDNE.cjs.map → chunk-COERBDG4.cjs.map} +1 -1
  14. package/dist/{chunk-7Q52HP45.js → chunk-E6YHDT3D.js} +2 -2
  15. package/dist/chunk-E6YHDT3D.js.map +1 -0
  16. package/dist/{chunk-74FWQI73.cjs → chunk-GNS65HNC.cjs} +18 -18
  17. package/dist/{chunk-74FWQI73.cjs.map → chunk-GNS65HNC.cjs.map} +1 -1
  18. package/dist/{chunk-WCPUJA3Y.cjs → chunk-HJJXNMM7.cjs} +7 -7
  19. package/dist/{chunk-WCPUJA3Y.cjs.map → chunk-HJJXNMM7.cjs.map} +1 -1
  20. package/dist/{chunk-R4MXLJUS.cjs → chunk-ISYVNPRT.cjs} +42 -42
  21. package/dist/{chunk-R4MXLJUS.cjs.map → chunk-ISYVNPRT.cjs.map} +1 -1
  22. package/dist/{chunk-YX7C5JD7.cjs → chunk-JAPP2F4M.cjs} +77 -77
  23. package/dist/{chunk-YX7C5JD7.cjs.map → chunk-JAPP2F4M.cjs.map} +1 -1
  24. package/dist/{chunk-GGDM5J4B.cjs → chunk-LL4QQSAD.cjs} +322 -331
  25. package/dist/chunk-LL4QQSAD.cjs.map +1 -0
  26. package/dist/{chunk-GJSLKATJ.js → chunk-LSPBPUQM.js} +2 -2
  27. package/dist/{chunk-KFQXO7QB.js → chunk-NA7XJRWB.js} +1 -1
  28. package/dist/chunk-NA7XJRWB.js.map +1 -0
  29. package/dist/{chunk-H66L2265.js → chunk-OATWTTCI.js} +6 -6
  30. package/dist/{chunk-LPC3C7MG.cjs → chunk-P43ZHPM6.cjs} +40 -40
  31. package/dist/{chunk-LPC3C7MG.cjs.map → chunk-P43ZHPM6.cjs.map} +1 -1
  32. package/dist/{chunk-NO2KT42M.js → chunk-PNJ5LMVK.js} +10 -9
  33. package/dist/{chunk-NO2KT42M.js.map → chunk-PNJ5LMVK.js.map} +1 -1
  34. package/dist/{chunk-NSF7JUXF.js → chunk-PQN5R5II.js} +7 -7
  35. package/dist/{chunk-CUN4CJUN.cjs → chunk-QAFRLO5N.cjs} +11 -10
  36. package/dist/chunk-QAFRLO5N.cjs.map +1 -0
  37. package/dist/{chunk-LC6RRLFA.cjs → chunk-SF4G7M6U.cjs} +15 -15
  38. package/dist/{chunk-LC6RRLFA.cjs.map → chunk-SF4G7M6U.cjs.map} +1 -1
  39. package/dist/{chunk-CVYSW33D.js → chunk-SOK32D6C.js} +189 -198
  40. package/dist/chunk-SOK32D6C.js.map +1 -0
  41. package/dist/{chunk-4UZH3MT2.js → chunk-TFDNJTBX.js} +4 -4
  42. package/dist/{chunk-5M5W6XDY.cjs → chunk-VANFD4FX.cjs} +7 -7
  43. package/dist/{chunk-5M5W6XDY.cjs.map → chunk-VANFD4FX.cjs.map} +1 -1
  44. package/dist/{chunk-PRKMOF2U.cjs → chunk-VIB4SGCD.cjs} +14 -14
  45. package/dist/{chunk-PRKMOF2U.cjs.map → chunk-VIB4SGCD.cjs.map} +1 -1
  46. package/dist/{chunk-SY3QS2E5.cjs → chunk-VZGU4BV6.cjs} +29 -29
  47. package/dist/{chunk-SY3QS2E5.cjs.map → chunk-VZGU4BV6.cjs.map} +1 -1
  48. package/dist/{chunk-7XVFSGQA.js → chunk-XXG2Z2JT.js} +3 -3
  49. package/dist/{chunk-HB63TQQO.js → chunk-ZVUR3A33.js} +2 -2
  50. package/dist/components/announcement-bar.d.ts.map +1 -1
  51. package/dist/components/case-studies/index.cjs +10 -10
  52. package/dist/components/case-studies/index.js +4 -4
  53. package/dist/components/chat/index.cjs +4 -4
  54. package/dist/components/chat/index.js +3 -3
  55. package/dist/components/contact/index.cjs +5 -5
  56. package/dist/components/contact/index.js +4 -4
  57. package/dist/components/docs/index.cjs +7 -7
  58. package/dist/components/docs/index.js +6 -6
  59. package/dist/components/embeds/index.cjs +5 -5
  60. package/dist/components/embeds/index.js +4 -4
  61. package/dist/components/faq/index.cjs +6 -6
  62. package/dist/components/faq/index.js +5 -5
  63. package/dist/components/features/index.cjs +4 -4
  64. package/dist/components/features/index.js +3 -3
  65. package/dist/components/help-center-pages/index.cjs +23 -23
  66. package/dist/components/help-center-pages/index.js +14 -14
  67. package/dist/components/index.cjs +179 -185
  68. package/dist/components/index.cjs.map +1 -1
  69. package/dist/components/index.js +32 -38
  70. package/dist/components/index.js.map +1 -1
  71. package/dist/components/navigation/index.cjs +4 -4
  72. package/dist/components/navigation/index.js +3 -3
  73. package/dist/components/onboarding-guides/index.cjs +8 -8
  74. package/dist/components/onboarding-guides/index.js +7 -7
  75. package/dist/components/related-content/index.cjs +6 -6
  76. package/dist/components/related-content/index.js +5 -5
  77. package/dist/components/tickets/index.cjs +7 -7
  78. package/dist/components/tickets/index.js +6 -6
  79. package/dist/components/ui/index.cjs +4 -4
  80. package/dist/components/ui/index.js +3 -3
  81. package/dist/contexts/endpoints-runtime-context.d.ts +1 -1
  82. package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -1
  83. package/dist/contexts/index.cjs +2 -2
  84. package/dist/contexts/index.js +1 -1
  85. package/dist/hooks/index.cjs +3 -3
  86. package/dist/hooks/index.js +2 -2
  87. package/dist/hooks/use-self-fetch.d.ts.map +1 -1
  88. package/dist/index.cjs +4 -4
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.js +5 -5
  91. package/dist/types/announcement.cjs.map +1 -1
  92. package/dist/types/announcement.d.ts +6 -0
  93. package/dist/types/announcement.d.ts.map +1 -1
  94. package/dist/types/announcement.js.map +1 -1
  95. package/dist/types/index.cjs.map +1 -1
  96. package/dist/types/index.js.map +1 -1
  97. package/dist/utils/announcement-storage.d.ts +0 -3
  98. package/dist/utils/announcement-storage.d.ts.map +1 -1
  99. package/dist/utils/app-config.d.ts.map +1 -1
  100. package/dist/utils/color-analysis.d.ts +4 -0
  101. package/dist/utils/color-analysis.d.ts.map +1 -1
  102. package/dist/utils/index.cjs +177 -186
  103. package/dist/utils/index.cjs.map +1 -1
  104. package/dist/utils/index.js +176 -185
  105. package/dist/utils/index.js.map +1 -1
  106. package/dist/utils/ods-color-utils.d.ts +1 -2
  107. package/dist/utils/ods-color-utils.d.ts.map +1 -1
  108. package/package.json +1 -1
  109. package/src/components/announcement-bar.tsx +21 -38
  110. package/src/contexts/endpoints-runtime-context.tsx +1 -1
  111. package/src/hooks/use-self-fetch.ts +9 -10
  112. package/src/stories/AnnouncementBar.stories.tsx +14 -8
  113. package/src/types/announcement.ts +8 -0
  114. package/src/utils/announcement-storage.ts +0 -17
  115. package/src/utils/app-config.ts +2 -3
  116. package/src/utils/color-analysis.ts +2 -5
  117. package/src/utils/ods-color-utils.ts +7 -4
  118. package/dist/chunk-2B6773QM.cjs.map +0 -1
  119. package/dist/chunk-7Q52HP45.js.map +0 -1
  120. package/dist/chunk-CUN4CJUN.cjs.map +0 -1
  121. package/dist/chunk-CVYSW33D.js.map +0 -1
  122. package/dist/chunk-GGDM5J4B.cjs.map +0 -1
  123. package/dist/chunk-KFQXO7QB.js.map +0 -1
  124. package/dist/chunk-STGWQFYT.cjs.map +0 -1
  125. /package/dist/{chunk-HJIRG7R6.js.map → chunk-3KZXOLFK.js.map} +0 -0
  126. /package/dist/{chunk-43H2WOAW.js.map → chunk-6WMVBCNA.js.map} +0 -0
  127. /package/dist/{chunk-XFP43YKG.js.map → chunk-7RVSGGO6.js.map} +0 -0
  128. /package/dist/{chunk-KLBEIJVZ.js.map → chunk-AYFWYOL6.js.map} +0 -0
  129. /package/dist/{chunk-GMZL4T7C.js.map → chunk-C3NPMZBI.js.map} +0 -0
  130. /package/dist/{chunk-GJSLKATJ.js.map → chunk-LSPBPUQM.js.map} +0 -0
  131. /package/dist/{chunk-H66L2265.js.map → chunk-OATWTTCI.js.map} +0 -0
  132. /package/dist/{chunk-NSF7JUXF.js.map → chunk-PQN5R5II.js.map} +0 -0
  133. /package/dist/{chunk-4UZH3MT2.js.map → chunk-TFDNJTBX.js.map} +0 -0
  134. /package/dist/{chunk-7XVFSGQA.js.map → chunk-XXG2Z2JT.js.map} +0 -0
  135. /package/dist/{chunk-HB63TQQO.js.map → chunk-ZVUR3A33.js.map} +0 -0
@@ -4,7 +4,7 @@ import "../chunk-GZ4C3XW6.js";
4
4
  import {
5
5
  GROUP_PAGE_SIZE,
6
6
  RelatedContentSection
7
- } from "../chunk-7XVFSGQA.js";
7
+ } from "../chunk-XXG2Z2JT.js";
8
8
  import {
9
9
  DeliveryLists,
10
10
  DeliveryTable,
@@ -21,7 +21,7 @@ import {
21
21
  useLegalDocs,
22
22
  usePaginationLoading,
23
23
  useRoadmapVoting
24
- } from "../chunk-KLBEIJVZ.js";
24
+ } from "../chunk-AYFWYOL6.js";
25
25
  import {
26
26
  AnnouncementBarSkeleton,
27
27
  ArticleLayoutSkeleton,
@@ -54,17 +54,17 @@ import {
54
54
  useDocNavigation,
55
55
  useDocumentTree,
56
56
  useScrollSpy
57
- } from "../chunk-XFP43YKG.js";
57
+ } from "../chunk-7RVSGGO6.js";
58
58
  import {
59
59
  FileDownloadCard,
60
60
  GoogleSheetsViewer,
61
61
  PdfViewer
62
- } from "../chunk-GJSLKATJ.js";
62
+ } from "../chunk-LSPBPUQM.js";
63
63
  import {
64
64
  FaqAccordion,
65
65
  FaqDocumentPage,
66
66
  FaqSection
67
- } from "../chunk-4UZH3MT2.js";
67
+ } from "../chunk-TFDNJTBX.js";
68
68
  import {
69
69
  DeliveryRow,
70
70
  DevCardRowContent,
@@ -75,11 +75,11 @@ import {
75
75
  EmptyState,
76
76
  UnifiedPagination,
77
77
  init_unified_pagination
78
- } from "../chunk-HB63TQQO.js";
78
+ } from "../chunk-ZVUR3A33.js";
79
79
  import {
80
80
  ArticleAuthorByline,
81
81
  DetailPageSkeleton
82
- } from "../chunk-GMZL4T7C.js";
82
+ } from "../chunk-C3NPMZBI.js";
83
83
  import {
84
84
  DocSearchBar,
85
85
  DocSearchResultRow,
@@ -87,10 +87,10 @@ import {
87
87
  mapDocSearchResults,
88
88
  resolveSearchResultAction,
89
89
  useDocSearch
90
- } from "../chunk-HJIRG7R6.js";
90
+ } from "../chunk-3KZXOLFK.js";
91
91
  import {
92
92
  useSelfFetch
93
- } from "../chunk-NO2KT42M.js";
93
+ } from "../chunk-PNJ5LMVK.js";
94
94
  import "../chunk-4XLJWX2N.js";
95
95
  import {
96
96
  ADMIN_APPROVAL_REQUEST_CONTEXT_TYPE,
@@ -879,7 +879,7 @@ import {
879
879
  useVideoOriginPreconnect,
880
880
  useVideoWarmup,
881
881
  usesCanonicalStatusStyle
882
- } from "../chunk-CVYSW33D.js";
882
+ } from "../chunk-SOK32D6C.js";
883
883
  import {
884
884
  CommandApprovalToast,
885
885
  ToastCard,
@@ -898,12 +898,12 @@ import {
898
898
  showToast,
899
899
  useOnboardingState,
900
900
  useToast
901
- } from "../chunk-7Q52HP45.js";
901
+ } from "../chunk-E6YHDT3D.js";
902
902
  import "../chunk-OYGFWWLQ.js";
903
903
  import {
904
904
  useChatRuntime,
905
905
  useEndpointsRuntime
906
- } from "../chunk-KFQXO7QB.js";
906
+ } from "../chunk-NA7XJRWB.js";
907
907
  import "../chunk-EL5YVPD5.js";
908
908
  import {
909
909
  init_next_navigation,
@@ -1115,7 +1115,7 @@ import "../chunk-GGWZFCYS.js";
1115
1115
 
1116
1116
  // src/components/announcement-bar.tsx
1117
1117
  init_button();
1118
- import { useEffect, useMemo, useRef, useState } from "react";
1118
+ import { useEffect, useMemo, useState } from "react";
1119
1119
  import { X } from "lucide-react";
1120
1120
  import { jsx, jsxs } from "react/jsx-runtime";
1121
1121
  function AnnouncementBar({
@@ -1135,11 +1135,6 @@ function AnnouncementBar({
1135
1135
  revalidateOnVisibleAfterMs: 6e4
1136
1136
  });
1137
1137
  const announcement = data?.announcement ?? null;
1138
- const lastAnnouncementRef = useRef(initialAnnouncement ?? null);
1139
- useEffect(() => {
1140
- if (announcement) lastAnnouncementRef.current = announcement;
1141
- }, [announcement]);
1142
- const displayAnnouncement = announcement ?? lastAnnouncementRef.current;
1143
1138
  const [expandedState, setExpandedState] = useState(() => initialAnnouncement != null);
1144
1139
  const expanded = previewMode ? announcement != null : expandedState;
1145
1140
  useEffect(() => {
@@ -1162,14 +1157,13 @@ function AnnouncementBar({
1162
1157
  const handleDismiss = () => {
1163
1158
  if (previewMode || !announcement) return;
1164
1159
  dismissAnnouncement(platform, announcement.id);
1165
- document.activeElement?.blur?.();
1166
1160
  setExpandedState(false);
1167
1161
  };
1168
1162
  const handleCtaClick = () => {
1169
1163
  if (previewMode || !announcement?.cta_url) return;
1170
1164
  let safeUrl;
1171
1165
  try {
1172
- const parsed = new URL(announcement.cta_url, window.location.href);
1166
+ const parsed = new URL(announcement.cta_url, window.location.origin);
1173
1167
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return;
1174
1168
  safeUrl = parsed.href;
1175
1169
  } catch {
@@ -1177,10 +1171,10 @@ function AnnouncementBar({
1177
1171
  }
1178
1172
  announcement.cta_target === "_blank" ? window.open(safeUrl, "_blank", "noopener,noreferrer") : window.location.href = safeUrl;
1179
1173
  };
1180
- if (!displayAnnouncement) return null;
1181
- const themeScope = pickReadableTextColor(displayAnnouncement.background_color) === "dark" ? "theme-light" : "theme-dark";
1174
+ if (!announcement) return null;
1175
+ const themeScope = pickReadableTextColor(announcement.background_color) === "dark" ? "theme-light" : "theme-dark";
1182
1176
  const barButtonClasses = "text-[color:var(--ods-system-greys-white)] hover:bg-[var(--ods-system-greys-black-hover)] active:bg-[var(--ods-system-greys-black-action)]";
1183
- const hasCta = Boolean(displayAnnouncement.cta_enabled && displayAnnouncement.cta_url && displayAnnouncement.cta_text);
1177
+ const hasCta = Boolean(announcement.cta_enabled && announcement.cta_url);
1184
1178
  return /* @__PURE__ */ jsx(
1185
1179
  "div",
1186
1180
  {
@@ -1190,7 +1184,7 @@ function AnnouncementBar({
1190
1184
  "data-announcement-bar": true,
1191
1185
  className: `relative w-full z-50 grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none ${className ?? ""}`,
1192
1186
  style: { gridTemplateRows: expanded ? "1fr" : "0fr" },
1193
- children: /* @__PURE__ */ jsx("div", { className: `min-h-0 overflow-hidden ${themeScope}`, style: { backgroundColor: displayAnnouncement.background_color }, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center w-full max-w-full min-h-11 text-[color:var(--ods-system-greys-white)]", children: [
1187
+ children: /* @__PURE__ */ jsx("div", { className: `min-h-0 overflow-hidden ${themeScope}`, style: { backgroundColor: announcement.background_color }, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center w-full max-w-full min-h-11 text-[color:var(--ods-system-greys-white)]", children: [
1194
1188
  /* @__PURE__ */ jsxs(
1195
1189
  "div",
1196
1190
  {
@@ -1206,22 +1200,22 @@ function AnnouncementBar({
1206
1200
  EntityIcon,
1207
1201
  {
1208
1202
  icon: {
1209
- name: displayAnnouncement.icon_name || "openframe-logo",
1210
- url: displayAnnouncement.icon_url,
1211
- props: displayAnnouncement.icon_props
1203
+ name: announcement.icon_name || "openframe-logo",
1204
+ url: announcement.icon_url,
1205
+ props: announcement.icon_props
1212
1206
  },
1213
1207
  size: 24,
1214
1208
  className: "relative shrink-0 w-5 h-5 md:w-6 md:h-6"
1215
1209
  }
1216
1210
  ),
1217
1211
  /* @__PURE__ */ jsxs("p", { className: "font-body flex-1 min-w-0 max-w-full text-[13px] md:text-sm leading-snug truncate mb-0", children: [
1218
- /* @__PURE__ */ jsx("span", { className: "font-semibold", children: displayAnnouncement.title }),
1219
- displayAnnouncement.description && /* @__PURE__ */ jsxs("span", { className: "hidden sm:inline opacity-80", children: [
1212
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: announcement.title }),
1213
+ announcement.description && /* @__PURE__ */ jsxs("span", { className: "hidden sm:inline opacity-80", children: [
1220
1214
  " \xB7 ",
1221
- displayAnnouncement.description
1215
+ announcement.description
1222
1216
  ] })
1223
1217
  ] }),
1224
- hasCta && displayAnnouncement.cta_text && /* @__PURE__ */ jsx("div", { className: "hidden md:flex flex-shrink-0 ml-1", children: /* @__PURE__ */ jsx(
1218
+ hasCta && announcement.cta_text && /* @__PURE__ */ jsx("div", { className: "hidden md:flex flex-shrink-0 ml-1", children: /* @__PURE__ */ jsx(
1225
1219
  Button,
1226
1220
  {
1227
1221
  onClick: handleCtaClick,
@@ -1229,15 +1223,15 @@ function AnnouncementBar({
1229
1223
  size: "small",
1230
1224
  className: barButtonClasses,
1231
1225
  tabIndex: expanded ? 0 : -1,
1232
- leftIcon: displayAnnouncement.cta_show_icon && displayAnnouncement.cta_icon_name ? /* @__PURE__ */ jsx(
1226
+ leftIcon: announcement.cta_show_icon && announcement.cta_icon_name ? /* @__PURE__ */ jsx(
1233
1227
  EntityIcon,
1234
1228
  {
1235
- icon: { name: displayAnnouncement.cta_icon_name, props: displayAnnouncement.cta_icon_props },
1229
+ icon: { name: announcement.cta_icon_name, props: announcement.cta_icon_props },
1236
1230
  size: 14,
1237
1231
  className: "w-3.5 h-3.5"
1238
1232
  }
1239
1233
  ) : void 0,
1240
- children: displayAnnouncement.cta_text
1234
+ children: announcement.cta_text
1241
1235
  }
1242
1236
  ) })
1243
1237
  ]
@@ -2642,11 +2636,11 @@ function FooterWaitlistButton({ className }) {
2642
2636
 
2643
2637
  // src/components/hero-image-uploader.tsx
2644
2638
  init_button();
2645
- import { useRef as useRef2, useState as useState2 } from "react";
2639
+ import { useRef, useState as useState2 } from "react";
2646
2640
  import { Loader2, Image as ImageIcon2, Upload, X as X3 } from "lucide-react";
2647
2641
  import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
2648
2642
  function HeroImageUploader({ imageUrl, onChange, uploadEndpoint, height = 300, objectFit = "cover", showReplaceButton = true, deferUpload = false, onUpload, onDelete }) {
2649
- const inputRef = useRef2(null);
2643
+ const inputRef = useRef(null);
2650
2644
  const { toast } = useToast();
2651
2645
  const [uploading, setUploading] = useState2(false);
2652
2646
  const ALLOWED_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"];
@@ -2764,7 +2758,7 @@ function HeroImageUploader({ imageUrl, onChange, uploadEndpoint, height = 300, o
2764
2758
  }
2765
2759
 
2766
2760
  // src/components/icons-block.tsx
2767
- import { useState as useState3, useEffect as useEffect2, useRef as useRef3 } from "react";
2761
+ import { useState as useState3, useEffect as useEffect2, useRef as useRef2 } from "react";
2768
2762
 
2769
2763
  // src/components/icons-stub.tsx
2770
2764
  import { DollarSign, Code, Users, Building, GitCompare, MessageSquare } from "lucide-react";
@@ -2803,7 +2797,7 @@ function ResponsiveIconsBlock({ loading = false }) {
2803
2797
  const [columns, setColumns] = useState3(24);
2804
2798
  const [iconGrid, setIconGrid] = useState3([]);
2805
2799
  const [iconsLoaded, setIconsLoaded] = useState3(false);
2806
- const randomSeedRef = useRef3(0);
2800
+ const randomSeedRef = useRef2(0);
2807
2801
  useEffect2(() => {
2808
2802
  function calculateColumns() {
2809
2803
  const cols = Math.ceil(window.innerWidth / 56) + 4;