@flamingo-stack/openframe-frontend-core 0.0.176 → 0.0.177-snapshot.20260514141929

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 (44) hide show
  1. package/dist/{chunk-VY6SYM2L.js → chunk-AAX27BCR.js} +311 -467
  2. package/dist/chunk-AAX27BCR.js.map +1 -0
  3. package/dist/{chunk-WX7PT5C7.cjs → chunk-ALW3D72O.cjs} +61 -2
  4. package/dist/chunk-ALW3D72O.cjs.map +1 -0
  5. package/dist/{chunk-KB2N44BY.js → chunk-FMWHOUFE.js} +61 -2
  6. package/dist/chunk-FMWHOUFE.js.map +1 -0
  7. package/dist/{chunk-SVF4YOGM.cjs → chunk-L4T24AN4.cjs} +482 -638
  8. package/dist/chunk-L4T24AN4.cjs.map +1 -0
  9. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  10. package/dist/components/features/index.cjs +3 -5
  11. package/dist/components/features/index.cjs.map +1 -1
  12. package/dist/components/features/index.js +2 -4
  13. package/dist/components/features/video-player.d.ts +17 -20
  14. package/dist/components/features/video-player.d.ts.map +1 -1
  15. package/dist/components/features/youtube-embed.d.ts +18 -4
  16. package/dist/components/features/youtube-embed.d.ts.map +1 -1
  17. package/dist/components/index.cjs +3 -5
  18. package/dist/components/index.cjs.map +1 -1
  19. package/dist/components/index.js +2 -4
  20. package/dist/components/navigation/index.cjs +3 -3
  21. package/dist/components/navigation/index.js +2 -2
  22. package/dist/components/ui/index.cjs +3 -3
  23. package/dist/components/ui/index.js +2 -2
  24. package/dist/hooks/index.cjs +4 -2
  25. package/dist/hooks/index.cjs.map +1 -1
  26. package/dist/hooks/index.d.ts +1 -0
  27. package/dist/hooks/index.d.ts.map +1 -1
  28. package/dist/hooks/index.js +3 -1
  29. package/dist/hooks/use-near-viewport.d.ts +42 -0
  30. package/dist/hooks/use-near-viewport.d.ts.map +1 -0
  31. package/dist/index.cjs +3 -3
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +4 -4
  34. package/package.json +1 -1
  35. package/src/components/chat/chat-message-list.tsx +48 -27
  36. package/src/components/features/video-player.tsx +39 -176
  37. package/src/components/features/youtube-embed.tsx +107 -224
  38. package/src/hooks/index.ts +3 -0
  39. package/src/hooks/use-near-viewport.ts +118 -0
  40. package/dist/chunk-KB2N44BY.js.map +0 -1
  41. package/dist/chunk-SVF4YOGM.cjs.map +0 -1
  42. package/dist/chunk-VY6SYM2L.js.map +0 -1
  43. package/dist/chunk-WX7PT5C7.cjs.map +0 -1
  44. package/src/components/features/__tests__/video-player.test.tsx +0 -142
@@ -16,7 +16,7 @@ import {
16
16
  useMdUp,
17
17
  useOnboardingState,
18
18
  useToast
19
- } from "./chunk-KB2N44BY.js";
19
+ } from "./chunk-FMWHOUFE.js";
20
20
  import {
21
21
  Button,
22
22
  Checkbox,
@@ -413,7 +413,7 @@ function useDynamicTheme() {
413
413
  }
414
414
 
415
415
  // src/components/features/array-entry-manager.tsx
416
- import { useState as useState58, useEffect as useEffect43 } from "react";
416
+ import { useState as useState58, useEffect as useEffect42 } from "react";
417
417
 
418
418
  // src/components/ui/allowed-domains-input.tsx
419
419
  init_cn();
@@ -5315,7 +5315,7 @@ MemoizedChatMessageEnhanced.displayName = "MemoizedChatMessageEnhanced";
5315
5315
 
5316
5316
  // src/components/chat/chat-message-list.tsx
5317
5317
  init_cn();
5318
- import { useRef as useRef6, useState as useState14, useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useImperativeHandle as useImperativeHandle3, forwardRef as forwardRef22 } from "react";
5318
+ import { useRef as useRef6, useState as useState14, useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3, useImperativeHandle as useImperativeHandle3, forwardRef as forwardRef22 } from "react";
5319
5319
  import { useStickToBottom } from "use-stick-to-bottom";
5320
5320
 
5321
5321
  // src/components/chat/chat-message-loader.tsx
@@ -5432,10 +5432,13 @@ var ChatMessageList = forwardRef22(
5432
5432
  return;
5433
5433
  }
5434
5434
  if (newCount > prevCount) {
5435
- const newSlice = messages.slice(prevCount);
5436
- const hasNewUser = newSlice.some((m) => m.role === "user");
5437
- if (hasNewUser) {
5438
- void scrollToBottom({ animation: "instant", ignoreEscapes: true });
5435
+ const isPrepend = prependRef.current.firstMessageId !== void 0 && messages[0]?.id !== prependRef.current.firstMessageId;
5436
+ if (!isPrepend) {
5437
+ const newSlice = messages.slice(prevCount);
5438
+ const hasNewUser = newSlice.some((m) => m.role === "user");
5439
+ if (hasNewUser) {
5440
+ void scrollToBottom({ animation: "instant", ignoreEscapes: true });
5441
+ }
5439
5442
  }
5440
5443
  }
5441
5444
  }, [autoScroll, messages, dialogId, scrollToBottom, scrollEl]);
@@ -5499,6 +5502,13 @@ var ChatMessageList = forwardRef22(
5499
5502
  }, [hasNextPage, scrollEl, sentinelEl, messages.length]);
5500
5503
  useImperativeHandle3(ref, () => scrollRef.current, [scrollRef]);
5501
5504
  const showLoader = useDelayedFlag(isLoading, { delay: 200, minDuration: 400 });
5505
+ const setScrollRef = useCallback3((el) => {
5506
+ scrollRef(el);
5507
+ setScrollEl(el);
5508
+ }, [scrollRef]);
5509
+ const setContentRef = useCallback3((el) => {
5510
+ contentRef(el);
5511
+ }, [contentRef]);
5502
5512
  if (showLoader) {
5503
5513
  return /* @__PURE__ */ jsx33(
5504
5514
  ChatMessageListLoader,
@@ -5509,13 +5519,6 @@ var ChatMessageList = forwardRef22(
5509
5519
  }
5510
5520
  );
5511
5521
  }
5512
- const setScrollRef = (el) => {
5513
- scrollRef(el);
5514
- setScrollEl(el);
5515
- };
5516
- const setContentRef = (el) => {
5517
- contentRef(el);
5518
- };
5519
5522
  return /* @__PURE__ */ jsxs28("div", { className: "relative flex-1 min-h-0 flex flex-col", children: [
5520
5523
  /* @__PURE__ */ jsx33(
5521
5524
  "div",
@@ -6220,7 +6223,7 @@ var NETWORK_CONFIG = {
6220
6223
  };
6221
6224
 
6222
6225
  // src/components/chat/hooks/use-chunk-catchup.ts
6223
- import { useCallback as useCallback5, useRef as useRef9 } from "react";
6226
+ import { useCallback as useCallback6, useRef as useRef9 } from "react";
6224
6227
  function makeSeqKey(messageType, chunkType, sequenceId) {
6225
6228
  return `${messageType}:${chunkType}:${sequenceId}`;
6226
6229
  }
@@ -6257,7 +6260,7 @@ function useChunkCatchup({
6257
6260
  fetchChunksRef.current = fetchChunks;
6258
6261
  const onChunkReceivedRef = useRef9(onChunkReceived);
6259
6262
  onChunkReceivedRef.current = onChunkReceived;
6260
- const processChunk = useCallback5((chunk, messageType, forceProcess = false) => {
6263
+ const processChunk = useCallback6((chunk, messageType, forceProcess = false) => {
6261
6264
  if (bufferUntilInitialCatchupComplete.current && !forceProcess) {
6262
6265
  chunkBuffer.current.push({ chunk, messageType });
6263
6266
  return true;
@@ -6270,7 +6273,7 @@ function useChunkCatchup({
6270
6273
  onChunkReceivedRef.current(chunk, messageType);
6271
6274
  return true;
6272
6275
  }, []);
6273
- const flushBufferedRealtimeChunks = useCallback5(() => {
6276
+ const flushBufferedRealtimeChunks = useCallback6(() => {
6274
6277
  if (chunkBuffer.current.length === 0) return;
6275
6278
  const buffered = [...chunkBuffer.current];
6276
6279
  chunkBuffer.current = [];
@@ -6283,7 +6286,7 @@ function useChunkCatchup({
6283
6286
  processChunk(chunk, messageType, true);
6284
6287
  });
6285
6288
  }, [processChunk]);
6286
- const catchUpChunks = useCallback5(async (fromSequenceId) => {
6289
+ const catchUpChunks = useCallback6(async (fromSequenceId) => {
6287
6290
  const dialogId2 = dialogIdRef.current;
6288
6291
  const chatTypes2 = chatTypesRef.current;
6289
6292
  const fetchChunks2 = fetchChunksRef.current;
@@ -6396,7 +6399,7 @@ function useChunkCatchup({
6396
6399
  }
6397
6400
  }
6398
6401
  }, [flushBufferedRealtimeChunks]);
6399
- const resetChunkTracking = useCallback5(() => {
6402
+ const resetChunkTracking = useCallback6(() => {
6400
6403
  processedSequenceKeys.current.clear();
6401
6404
  lastSequenceId.current = null;
6402
6405
  fetchingInProgress.current = false;
@@ -6405,13 +6408,13 @@ function useChunkCatchup({
6405
6408
  bufferUntilInitialCatchupComplete.current = false;
6406
6409
  hasCompletedInitialCatchup.current = false;
6407
6410
  }, []);
6408
- const startInitialBuffering = useCallback5(() => {
6411
+ const startInitialBuffering = useCallback6(() => {
6409
6412
  chunkBuffer.current = [];
6410
6413
  bufferUntilInitialCatchupComplete.current = true;
6411
6414
  hasCompletedInitialCatchup.current = false;
6412
6415
  }, []);
6413
- const isBufferingActive = useCallback5(() => bufferUntilInitialCatchupComplete.current, []);
6414
- const resetAndCatchUp = useCallback5(async () => {
6416
+ const isBufferingActive = useCallback6(() => bufferUntilInitialCatchupComplete.current, []);
6417
+ const resetAndCatchUp = useCallback6(async () => {
6415
6418
  if (!dialogIdRef.current) return;
6416
6419
  const fromSeq = lastSequenceId.current;
6417
6420
  hasCompletedInitialCatchup.current = false;
@@ -6432,7 +6435,7 @@ function useChunkCatchup({
6432
6435
  }
6433
6436
 
6434
6437
  // src/components/chat/hooks/use-nats-dialog-subscription.ts
6435
- import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef10, useState as useState16 } from "react";
6438
+ import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef10, useState as useState16 } from "react";
6436
6439
  var shared = null;
6437
6440
  function useNatsDialogSubscription({
6438
6441
  enabled,
@@ -6481,7 +6484,7 @@ function useNatsDialogSubscription({
6481
6484
  useEffect8(() => {
6482
6485
  reconnectionBackoffRef.current = reconnectionBackoff;
6483
6486
  }, [reconnectionBackoff]);
6484
- const acquireClient = useCallback6((url) => {
6487
+ const acquireClient = useCallback7((url) => {
6485
6488
  if (shared?.wsUrl !== url) {
6486
6489
  if (shared) {
6487
6490
  shared.closeTimer && clearTimeout(shared.closeTimer);
@@ -6508,7 +6511,7 @@ function useNatsDialogSubscription({
6508
6511
  shared.closeTimer = null;
6509
6512
  return shared;
6510
6513
  }, [clientConfig]);
6511
- const releaseClient = useCallback6((url) => {
6514
+ const releaseClient = useCallback7((url) => {
6512
6515
  if (!shared || shared.wsUrl !== url) return;
6513
6516
  shared.refCount = Math.max(0, shared.refCount - 1);
6514
6517
  if (shared.refCount > 0) return;
@@ -6805,7 +6808,7 @@ function buildNatsWsUrl(apiBaseUrl, options) {
6805
6808
  }
6806
6809
 
6807
6810
  // src/components/chat/hooks/use-realtime-chunk-processor.ts
6808
- import { useCallback as useCallback7, useRef as useRef11, useEffect as useEffect9 } from "react";
6811
+ import { useCallback as useCallback8, useRef as useRef11, useEffect as useEffect9 } from "react";
6809
6812
 
6810
6813
  // src/components/chat/utils/chunk-parser.ts
6811
6814
  function normalizeToolCalls(raw) {
@@ -7429,7 +7432,7 @@ function useRealtimeChunkProcessor(options) {
7429
7432
  }, [initialState, callbacks]);
7430
7433
  const isInStreamRef = useRef11(false);
7431
7434
  const pendingEscalatedRef = useRef11(/* @__PURE__ */ new Map());
7432
- const processChunk = useCallback7(
7435
+ const processChunk = useCallback8(
7433
7436
  (chunk) => {
7434
7437
  if (!enableThinking && chunk && typeof chunk === "object" && chunk.type === MESSAGE_TYPE.THINKING) {
7435
7438
  return;
@@ -7628,21 +7631,21 @@ function useRealtimeChunkProcessor(options) {
7628
7631
  },
7629
7632
  [callbacks, displayApprovalTypes, approvalStatuses, initialState, enableThinking]
7630
7633
  );
7631
- const getSegments = useCallback7(() => {
7634
+ const getSegments = useCallback8(() => {
7632
7635
  return accumulatorRef.current.getSegments();
7633
7636
  }, []);
7634
- const reset = useCallback7(() => {
7637
+ const reset = useCallback8(() => {
7635
7638
  accumulatorRef.current.reset();
7636
7639
  pendingEscalatedRef.current.clear();
7637
7640
  hasInitializedWithData.current = false;
7638
7641
  }, []);
7639
- const updateApprovalStatus = useCallback7(
7642
+ const updateApprovalStatus = useCallback8(
7640
7643
  (requestId, status) => {
7641
7644
  return accumulatorRef.current.updateApprovalStatus(requestId, status);
7642
7645
  },
7643
7646
  []
7644
7647
  );
7645
- const getPendingApprovals = useCallback7(() => {
7648
+ const getPendingApprovals = useCallback8(() => {
7646
7649
  return new Map(pendingEscalatedRef.current);
7647
7650
  }, []);
7648
7651
  return {
@@ -8774,7 +8777,7 @@ function SlidingSidebar({ config }) {
8774
8777
  }
8775
8778
 
8776
8779
  // src/components/navigation/sticky-section-nav.tsx
8777
- import { useEffect as useEffect14, useState as useState20, useCallback as useCallback8, useRef as useRef14 } from "react";
8780
+ import { useEffect as useEffect14, useState as useState20, useCallback as useCallback9, useRef as useRef14 } from "react";
8778
8781
  import { jsx as jsx46, jsxs as jsxs39 } from "react/jsx-runtime";
8779
8782
  function StickySectionNav({
8780
8783
  sections,
@@ -8838,7 +8841,7 @@ function useSectionNavigation(sections, options) {
8838
8841
  const [activeSection, setActiveSection] = useState20(sections[0]?.id || "");
8839
8842
  const isScrollingFromClick = useRef14(false);
8840
8843
  const { offset: offset2 = 100 } = options || {};
8841
- const handleSectionClick = useCallback8((sectionId) => {
8844
+ const handleSectionClick = useCallback9((sectionId) => {
8842
8845
  const targetElement = document.getElementById(sectionId);
8843
8846
  if (!targetElement) return;
8844
8847
  isScrollingFromClick.current = true;
@@ -8889,7 +8892,7 @@ function useSectionNavigation(sections, options) {
8889
8892
  }
8890
8893
 
8891
8894
  // src/components/navigation/navigation-sidebar.tsx
8892
- import { useCallback as useCallback9, useLayoutEffect as useLayoutEffect4, useMemo as useMemo7, useState as useState21 } from "react";
8895
+ import { useCallback as useCallback10, useLayoutEffect as useLayoutEffect4, useMemo as useMemo7, useState as useState21 } from "react";
8893
8896
 
8894
8897
  // src/components/navigation/navigation-sidebar-header.tsx
8895
8898
  import { jsx as jsx47, jsxs as jsxs40 } from "react/jsx-runtime";
@@ -9042,11 +9045,11 @@ function NavigationSidebar({ config, disabled = false }) {
9042
9045
  const [transitionsEnabled, setTransitionsEnabled] = useState21(false);
9043
9046
  const isMinimized = !isLgUp || minimized;
9044
9047
  const showLabel = isLgUp && !minimized;
9045
- const handleToggle = useCallback9(() => {
9048
+ const handleToggle = useCallback10(() => {
9046
9049
  setMinimized((prev) => !prev);
9047
9050
  config.onToggleMinimized?.();
9048
9051
  }, [setMinimized, config]);
9049
- const handleItemClick = useCallback9((item, event) => {
9052
+ const handleItemClick = useCallback10((item, event) => {
9050
9053
  event?.stopPropagation();
9051
9054
  if (item.onClick) {
9052
9055
  item.onClick();
@@ -9569,7 +9572,7 @@ function NotificationsHeaderButton({
9569
9572
  }
9570
9573
 
9571
9574
  // src/components/navigation/app-layout.tsx
9572
- import { Suspense, useCallback as useCallback12, useState as useState24 } from "react";
9575
+ import { Suspense, useCallback as useCallback13, useState as useState24 } from "react";
9573
9576
 
9574
9577
  // src/components/features/notifications/notification-drawer.tsx
9575
9578
  import * as DialogPrimitive2 from "@radix-ui/react-dialog";
@@ -9949,7 +9952,7 @@ function NotificationsHistoryButton({ onClick }) {
9949
9952
  }
9950
9953
 
9951
9954
  // src/components/navigation/mobile-burger-menu.tsx
9952
- import React29, { useCallback as useCallback11, useEffect as useEffect17 } from "react";
9955
+ import React29, { useCallback as useCallback12, useEffect as useEffect17 } from "react";
9953
9956
  import { Fragment as Fragment8, jsx as jsx60, jsxs as jsxs50 } from "react/jsx-runtime";
9954
9957
  var HEADER_HEIGHT = 48;
9955
9958
  var MobileBurgerMenu = React29.memo(function MobileBurgerMenu2({
@@ -9983,7 +9986,7 @@ var MobileBurgerMenu = React29.memo(function MobileBurgerMenu2({
9983
9986
  return () => document.removeEventListener("keydown", handleKeyDown);
9984
9987
  }
9985
9988
  }, [isOpen, onClose]);
9986
- const handleItemClick = useCallback11((item) => {
9989
+ const handleItemClick = useCallback12((item) => {
9987
9990
  if (item.onClick) {
9988
9991
  item.onClick();
9989
9992
  } else if (item.path) {
@@ -10159,10 +10162,10 @@ function AppLayout({
10159
10162
  disabled = false
10160
10163
  }) {
10161
10164
  const [mobileMenuOpen, setMobileMenuOpen] = useState24(false);
10162
- const handleToggleMobileMenu = useCallback12(() => {
10165
+ const handleToggleMobileMenu = useCallback13(() => {
10163
10166
  setMobileMenuOpen((prev) => !prev);
10164
10167
  }, []);
10165
- const handleCloseMobileMenu = useCallback12(() => {
10168
+ const handleCloseMobileMenu = useCallback13(() => {
10166
10169
  setMobileMenuOpen(false);
10167
10170
  }, []);
10168
10171
  return /* @__PURE__ */ jsxs51("div", { className: cn("flex h-screen bg-ods-bg", className), children: [
@@ -11878,7 +11881,7 @@ function EmptyState2({
11878
11881
  }
11879
11882
 
11880
11883
  // src/components/faq-accordion.tsx
11881
- import { useRef as useRef15, useState as useState26, useEffect as useEffect19, useCallback as useCallback13 } from "react";
11884
+ import { useRef as useRef15, useState as useState26, useEffect as useEffect19, useCallback as useCallback14 } from "react";
11882
11885
 
11883
11886
  // src/components/ui/chevron-button.tsx
11884
11887
  init_cn();
@@ -11920,7 +11923,7 @@ import { jsx as jsx85, jsxs as jsxs70 } from "react/jsx-runtime";
11920
11923
  var useMeasuredHeight = (isOpen) => {
11921
11924
  const ref = useRef15(null);
11922
11925
  const [maxHeight, setMaxHeight] = useState26("0px");
11923
- const measure = useCallback13(() => {
11926
+ const measure = useCallback14(() => {
11924
11927
  if (ref.current) {
11925
11928
  const height = ref.current.scrollHeight;
11926
11929
  setMaxHeight(`${height}px`);
@@ -12506,13 +12509,13 @@ init_unified_pagination();
12506
12509
 
12507
12510
  // src/components/footer-waitlist-button.tsx
12508
12511
  import { usePathname as usePathname2, useRouter as useRouter4 } from "next/navigation";
12509
- import { useCallback as useCallback14 } from "react";
12512
+ import { useCallback as useCallback15 } from "react";
12510
12513
  init_button2();
12511
12514
  import { jsx as jsx91 } from "react/jsx-runtime";
12512
12515
  function FooterWaitlistButton({ className }) {
12513
12516
  const router = useRouter4();
12514
12517
  const pathname = usePathname2();
12515
- const handleClick = useCallback14(() => {
12518
+ const handleClick = useCallback15(() => {
12516
12519
  if (pathname?.startsWith("/waitlist")) {
12517
12520
  const anchor = document.getElementById("waitlist-form");
12518
12521
  if (anchor) {
@@ -12816,7 +12819,7 @@ function ResponsiveIconsBlock({ loading = false }) {
12816
12819
 
12817
12820
  // src/components/image-cropper.tsx
12818
12821
  init_button2();
12819
- import { useCallback as useCallback15, useState as useState29 } from "react";
12822
+ import { useCallback as useCallback16, useState as useState29 } from "react";
12820
12823
  import Cropper from "react-easy-crop";
12821
12824
 
12822
12825
  // src/components/ui/slider.tsx
@@ -12878,11 +12881,11 @@ var ImageCropper = ({
12878
12881
  const [zoom, setZoom] = useState29(1);
12879
12882
  const [rotation, setRotation] = useState29(0);
12880
12883
  const [croppedAreaPixels, setCroppedAreaPixels] = useState29(null);
12881
- const onCropComplete = useCallback15((_, area) => {
12884
+ const onCropComplete = useCallback16((_, area) => {
12882
12885
  setCroppedAreaPixels(area);
12883
12886
  }, []);
12884
12887
  const checkerBg = "bg-[length:16px_16px] bg-[linear-gradient(45deg,transparent_25%,#2a2a2a_25%,#2a2a2a_75%,transparent_75%,transparent),linear-gradient(45deg,#2a2a2a_25%,transparent_25%,transparent_75%,#2a2a2a_75%,#2a2a2a)]";
12885
- const exportCrop = useCallback15(async () => {
12888
+ const exportCrop = useCallback16(async () => {
12886
12889
  if (!croppedAreaPixels) return void 0;
12887
12890
  const img = await loadImage(src);
12888
12891
  const canvas = document.createElement("canvas");
@@ -13045,7 +13048,7 @@ var ImageCropper = ({
13045
13048
 
13046
13049
  // src/components/media-carousel.tsx
13047
13050
  init_cn();
13048
- import { useState as useState30, useRef as useRef19, useEffect as useEffect22, memo as memo3, useCallback as useCallback16 } from "react";
13051
+ import { useState as useState30, useRef as useRef19, useEffect as useEffect22, memo as memo3, useCallback as useCallback17 } from "react";
13049
13052
  import { Fragment as Fragment13, jsx as jsx96, jsxs as jsxs77 } from "react/jsx-runtime";
13050
13053
  var ChevronLeftIcon = () => /* @__PURE__ */ jsx96("svg", { width: "24", height: "24", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx96("polyline", { points: "15,18 9,12 15,6" }) });
13051
13054
  var ChevronRightIcon = () => /* @__PURE__ */ jsx96("svg", { width: "24", height: "24", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx96("polyline", { points: "9,18 15,12 9,6" }) });
@@ -13121,7 +13124,7 @@ var MediaCarousel = memo3(function MediaCarousel2({
13121
13124
  if (!currentItem) {
13122
13125
  return null;
13123
13126
  }
13124
- const handleVideoClick = useCallback16((index) => {
13127
+ const handleVideoClick = useCallback17((index) => {
13125
13128
  const item = media[index];
13126
13129
  if (item.type !== "video") return;
13127
13130
  const videoElements = document.querySelectorAll(`video[data-video-index="${index}"]`);
@@ -13163,7 +13166,7 @@ var MediaCarousel = memo3(function MediaCarousel2({
13163
13166
  }
13164
13167
  }
13165
13168
  }, [media]);
13166
- const nextSlide = useCallback16(() => {
13169
+ const nextSlide = useCallback17(() => {
13167
13170
  const currentVideo = document.querySelector(`[data-video-index="${currentIndex}"]`);
13168
13171
  if (currentVideo && !currentVideo.paused) {
13169
13172
  currentVideo.pause();
@@ -13171,7 +13174,7 @@ var MediaCarousel = memo3(function MediaCarousel2({
13171
13174
  setPlayingVideos(/* @__PURE__ */ new Set());
13172
13175
  setCurrentIndex((prev) => (prev + 1) % media.length);
13173
13176
  }, [currentIndex, media.length]);
13174
- const prevSlide = useCallback16(() => {
13177
+ const prevSlide = useCallback17(() => {
13175
13178
  const currentVideo = document.querySelector(`[data-video-index="${currentIndex}"]`);
13176
13179
  if (currentVideo && !currentVideo.paused) {
13177
13180
  currentVideo.pause();
@@ -13179,7 +13182,7 @@ var MediaCarousel = memo3(function MediaCarousel2({
13179
13182
  setPlayingVideos(/* @__PURE__ */ new Set());
13180
13183
  setCurrentIndex((prev) => (prev - 1 + media.length) % media.length);
13181
13184
  }, [currentIndex, media.length]);
13182
- const selectSlide = useCallback16((index) => {
13185
+ const selectSlide = useCallback17((index) => {
13183
13186
  if (index === currentIndex) return;
13184
13187
  const currentVideo = document.querySelector(`[data-video-index="${currentIndex}"]`);
13185
13188
  if (currentVideo && !currentVideo.paused) {
@@ -13188,7 +13191,7 @@ var MediaCarousel = memo3(function MediaCarousel2({
13188
13191
  setPlayingVideos(/* @__PURE__ */ new Set());
13189
13192
  setCurrentIndex(index);
13190
13193
  }, [currentIndex]);
13191
- const handleKeyDown = useCallback16((e) => {
13194
+ const handleKeyDown = useCallback17((e) => {
13192
13195
  if (media.length <= 1) return;
13193
13196
  if (e.key === "ArrowLeft") {
13194
13197
  e.preventDefault();
@@ -15860,7 +15863,7 @@ function DateTimePicker({
15860
15863
 
15861
15864
  // src/components/shared/onboarding/onboarding-walkthrough.tsx
15862
15865
  init_button2();
15863
- import React41, { useRef as useRef20, useCallback as useCallback17 } from "react";
15866
+ import React41, { useRef as useRef20, useCallback as useCallback18 } from "react";
15864
15867
 
15865
15868
  // src/components/shared/onboarding/onboarding-step-card.tsx
15866
15869
  import React40 from "react";
@@ -16155,7 +16158,7 @@ function OnboardingWalkthrough({
16155
16158
  lastCompletionStatusRef.current = statusKey;
16156
16159
  }
16157
16160
  }, [completionStatus, isLoadingCompletion, state.completedSteps, markMultipleComplete]);
16158
- const handleStepAction = useCallback17(async (step) => {
16161
+ const handleStepAction = useCallback18(async (step) => {
16159
16162
  if (actionInProgressRef.current.has(step.id)) {
16160
16163
  console.log(`\u23F3 Action already in progress for "${step.id}", skipping`);
16161
16164
  return;
@@ -16394,7 +16397,7 @@ function ProductReleaseCardSkeleton({ className, size = "default" }) {
16394
16397
  }
16395
16398
 
16396
16399
  // src/components/shared/product-release/release-detail-page.tsx
16397
- import { useState as useState37, useEffect as useEffect27 } from "react";
16400
+ import { useState as useState37, useEffect as useEffect26 } from "react";
16398
16401
  import Link4 from "next/link";
16399
16402
 
16400
16403
  // src/components/layout/article-detail-layout.tsx
@@ -16613,58 +16616,20 @@ function ImageGalleryModal({
16613
16616
  import { AlertTriangle, ExternalLink, BookMarked } from "lucide-react";
16614
16617
 
16615
16618
  // src/components/features/youtube-embed.tsx
16616
- import { useState as useState34, useEffect as useEffect25 } from "react";
16617
- import ReactPlayer from "react-player/youtube";
16619
+ import { useRef as useRef21, useState as useState34 } from "react";
16618
16620
  import { jsx as jsx138, jsxs as jsxs111 } from "react/jsx-runtime";
16619
- var Play = ({ size = 16, className }) => /* @__PURE__ */ jsx138("svg", { width: size, height: size, fill: "currentColor", viewBox: "0 0 24 24", className, children: /* @__PURE__ */ jsx138("polygon", { points: "5,3 19,12 5,21" }) });
16620
- var Loader = ({ size = 16, className }) => /* @__PURE__ */ jsxs111("svg", { width: size, height: size, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className, children: [
16621
- /* @__PURE__ */ jsx138("line", { x1: "12", y1: "2", x2: "12", y2: "6" }),
16622
- /* @__PURE__ */ jsx138("line", { x1: "12", y1: "18", x2: "12", y2: "22" }),
16623
- /* @__PURE__ */ jsx138("line", { x1: "4.93", y1: "4.93", x2: "7.76", y2: "7.76" }),
16624
- /* @__PURE__ */ jsx138("line", { x1: "16.24", y1: "16.24", x2: "19.07", y2: "19.07" }),
16625
- /* @__PURE__ */ jsx138("line", { x1: "2", y1: "12", x2: "6", y2: "12" }),
16626
- /* @__PURE__ */ jsx138("line", { x1: "18", y1: "12", x2: "22", y2: "12" }),
16627
- /* @__PURE__ */ jsx138("line", { x1: "4.93", y1: "19.07", x2: "7.76", y2: "16.24" }),
16628
- /* @__PURE__ */ jsx138("line", { x1: "16.24", y1: "7.76", x2: "19.07", y2: "4.93" })
16629
- ] });
16630
16621
  var YouTubeEmbed = ({
16631
16622
  videoId,
16632
16623
  title = "YouTube Video",
16633
16624
  className = "",
16634
16625
  showTitle = true,
16635
16626
  showMeta = true,
16636
- minimalControls = false
16627
+ minimalControls = false,
16628
+ aboveTheFold = false
16637
16629
  }) => {
16638
- const [isLoading, setIsLoading] = useState34(true);
16639
- const [hasError, setHasError] = useState34(false);
16640
- const [isPlaying, setIsPlaying] = useState34(false);
16641
- const [useIframe, setUseIframe] = useState34(false);
16642
- const [mounted, setMounted] = useState34(false);
16643
- useEffect25(() => {
16644
- setMounted(true);
16645
- setUseIframe(true);
16646
- setIsLoading(false);
16647
- }, []);
16648
- const handleReady = () => {
16649
- setIsLoading(false);
16650
- };
16651
- const handleError = () => {
16652
- setIsLoading(false);
16653
- setHasError(true);
16654
- setUseIframe(true);
16655
- };
16656
- const handlePlay = () => {
16657
- setIsPlaying(true);
16658
- };
16659
- const handlePause = () => {
16660
- setIsPlaying(false);
16661
- };
16662
- const videoUrl = `https://www.youtube.com/watch?v=${videoId}`;
16663
- const embedParams = new URLSearchParams({
16664
- rel: "0",
16665
- modestbranding: "1",
16666
- playsinline: "1"
16667
- });
16630
+ const [activated, setActivated] = useState34(false);
16631
+ const iframeSlotRef = useRef21(null);
16632
+ const embedParams = new URLSearchParams({ autoplay: "1", rel: "0", modestbranding: "1", playsinline: "1" });
16668
16633
  if (minimalControls) {
16669
16634
  embedParams.set("controls", "0");
16670
16635
  embedParams.set("showinfo", "0");
@@ -16672,96 +16637,60 @@ var YouTubeEmbed = ({
16672
16637
  embedParams.set("iv_load_policy", "3");
16673
16638
  embedParams.set("cc_load_policy", "0");
16674
16639
  embedParams.set("disablekb", "1");
16675
- embedParams.set("rel", "0");
16676
- }
16677
- const embedUrl = `https://www.youtube.com/embed/${videoId}?${embedParams.toString()}`;
16678
- if (!mounted) {
16679
- return /* @__PURE__ */ jsx138("div", { className: `youtube-embed-container my-6 ${className}`, children: /* @__PURE__ */ jsx138("div", { className: "video-wrapper relative w-full", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ jsx138("div", { className: "loading-overlay absolute inset-0 bg-ods-card border border-ods-border rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxs111("div", { className: "loading-content flex flex-col items-center gap-3", children: [
16680
- /* @__PURE__ */ jsx138(Loader, { className: "animate-spin text-ods-accent", size: 32 }),
16681
- /* @__PURE__ */ jsx138("span", { className: "font-sans text-sm text-ods-text-secondary", children: "Loading video..." })
16682
- ] }) }) }) });
16683
- }
16684
- if (hasError) {
16685
- return /* @__PURE__ */ jsx138("div", { className: `youtube-embed-error ${className}`, children: /* @__PURE__ */ jsxs111("div", { className: "error-state bg-ods-card border border-ods-error rounded-lg p-6 text-center my-6", children: [
16686
- /* @__PURE__ */ jsx138("div", { className: "error-icon flex justify-center mb-4", children: /* @__PURE__ */ jsx138("svg", { width: "48", height: "48", fill: "currentColor", viewBox: "0 0 24 24", className: "text-ods-error", children: /* @__PURE__ */ jsx138("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }) }),
16687
- /* @__PURE__ */ jsx138("div", { className: "error-title font-sans font-semibold text-lg text-ods-error mb-2", children: "Video Unavailable" }),
16688
- /* @__PURE__ */ jsx138("div", { className: "error-description font-sans text-sm text-ods-text-secondary mb-4", children: "Unable to load YouTube video. The video may be private or deleted." }),
16689
- /* @__PURE__ */ jsx138(
16690
- "a",
16691
- {
16692
- href: videoUrl,
16693
- target: "_blank",
16694
- rel: "noopener noreferrer",
16695
- className: "error-retry-button bg-ods-error hover:bg-ods-error-hover text-ods-text-on-error border-none rounded px-4 py-2 font-sans font-medium text-sm cursor-pointer transition-colors duration-200",
16696
- children: "Watch on YouTube"
16697
- }
16698
- )
16699
- ] }) });
16700
16640
  }
16641
+ const embedUrl = `https://www.youtube-nocookie.com/embed/${videoId}?${embedParams.toString()}`;
16642
+ const watchUrl = `https://www.youtube.com/watch?v=${videoId}`;
16643
+ const posterJpg = `https://i.ytimg.com/vi/${videoId}/mqdefault.jpg`;
16644
+ const posterWebp = `https://i.ytimg.com/vi_webp/${videoId}/mqdefault.webp`;
16645
+ const handleActivate = () => {
16646
+ const slot = iframeSlotRef.current;
16647
+ if (!slot || activated) return;
16648
+ const iframe = document.createElement("iframe");
16649
+ iframe.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share");
16650
+ iframe.setAttribute("allowfullscreen", "");
16651
+ iframe.setAttribute("title", title);
16652
+ iframe.className = "absolute inset-0 w-full h-full border-0";
16653
+ iframe.src = embedUrl;
16654
+ slot.appendChild(iframe);
16655
+ setActivated(true);
16656
+ };
16701
16657
  return /* @__PURE__ */ jsxs111("div", { className: `youtube-embed-container my-6 ${className}`, children: [
16702
16658
  title && showTitle && /* @__PURE__ */ jsx138("div", { className: "video-title font-sans text-lg font-medium text-ods-text-primary mb-3", children: title }),
16703
- /* @__PURE__ */ jsxs111("div", { className: "video-wrapper relative w-full", style: { paddingBottom: "56.25%" }, children: [
16704
- isLoading && /* @__PURE__ */ jsx138("div", { className: "loading-overlay absolute inset-0 bg-ods-card border border-ods-border rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxs111("div", { className: "loading-content flex flex-col items-center gap-3", children: [
16705
- /* @__PURE__ */ jsx138(Loader, { className: "animate-spin text-ods-accent", size: 32 }),
16706
- /* @__PURE__ */ jsx138("span", { className: "font-sans text-sm text-ods-text-secondary", children: "Loading video..." })
16707
- ] }) }),
16708
- /* @__PURE__ */ jsx138("div", { className: "video-player absolute inset-0 rounded-lg overflow-hidden border border-ods-border bg-ods-bg-inverse", children: useIframe ? (
16709
- // Iframe fallback for mobile and error cases
16710
- /* @__PURE__ */ jsx138(
16711
- "iframe",
16712
- {
16713
- src: embedUrl,
16714
- title,
16715
- className: "w-full h-full border-0",
16716
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
16717
- allowFullScreen: true,
16718
- style: { border: "none" }
16719
- }
16720
- )
16721
- ) : /* @__PURE__ */ jsx138(
16722
- ReactPlayer,
16723
- {
16724
- url: videoUrl,
16725
- width: "100%",
16726
- height: "100%",
16727
- onReady: handleReady,
16728
- onError: handleError,
16729
- onPlay: handlePlay,
16730
- onPause: handlePause,
16731
- config: {
16732
- youtube: {
16733
- playerVars: {
16734
- autoplay: 0,
16735
- controls: 1,
16736
- rel: 0,
16737
- showinfo: 0,
16738
- modestbranding: 1,
16739
- iv_load_policy: 3,
16740
- cc_load_policy: 0,
16741
- playsinline: 1
16742
- }
16743
- }
16744
- },
16745
- light: false,
16746
- playing: false
16747
- }
16748
- ) }),
16749
- !useIframe && !isPlaying && !isLoading && /* @__PURE__ */ jsx138("div", { className: "play-overlay absolute inset-0 flex items-center justify-center bg-ods-bg-inverse bg-opacity-20 rounded-lg transition-opacity duration-300 hover:bg-opacity-30", children: /* @__PURE__ */ jsx138(
16659
+ /* @__PURE__ */ jsx138("div", { className: "video-wrapper relative w-full", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ jsxs111("div", { className: "absolute inset-0 rounded-lg overflow-hidden border border-ods-border bg-ods-card", children: [
16660
+ /* @__PURE__ */ jsx138("div", { ref: iframeSlotRef, className: "absolute inset-0", "aria-hidden": !activated }),
16661
+ !activated && /* @__PURE__ */ jsxs111(
16750
16662
  "button",
16751
16663
  {
16752
- onClick: () => setIsPlaying(true),
16753
- className: "play-button bg-ods-accent hover:bg-ods-accent-hover text-ods-text-on-accent w-16 h-16 rounded-full flex items-center justify-center transition-all duration-200 transform hover:scale-110 shadow-lg",
16754
- "aria-label": "Play video",
16755
- children: /* @__PURE__ */ jsx138(Play, { size: 24, className: "ml-1" })
16664
+ type: "button",
16665
+ "aria-label": `Play: ${title}`,
16666
+ onClick: handleActivate,
16667
+ className: "group absolute inset-0 p-0 m-0 border-0 cursor-pointer bg-transparent",
16668
+ children: [
16669
+ /* @__PURE__ */ jsxs111("picture", { children: [
16670
+ /* @__PURE__ */ jsx138("source", { type: "image/webp", srcSet: posterWebp }),
16671
+ /* @__PURE__ */ jsx138(
16672
+ "img",
16673
+ {
16674
+ src: posterJpg,
16675
+ alt: title,
16676
+ loading: "lazy",
16677
+ fetchPriority: aboveTheFold ? "high" : "low",
16678
+ decoding: aboveTheFold ? "sync" : "async",
16679
+ className: "absolute inset-0 w-full h-full object-cover"
16680
+ }
16681
+ )
16682
+ ] }),
16683
+ /* @__PURE__ */ jsx138("div", { className: "absolute inset-0 flex items-center justify-center bg-ods-bg-inverse bg-opacity-20 transition-opacity duration-200 group-hover:bg-opacity-30", children: /* @__PURE__ */ jsx138("span", { className: "flex items-center justify-center w-16 h-16 rounded-full bg-ods-accent text-ods-text-on-accent shadow-lg transition-transform duration-200 group-hover:scale-110", children: /* @__PURE__ */ jsx138("svg", { width: 24, height: 24, fill: "currentColor", viewBox: "0 0 24 24", className: "ml-1", children: /* @__PURE__ */ jsx138("polygon", { points: "5,3 19,12 5,21" }) }) }) })
16684
+ ]
16756
16685
  }
16757
- ) })
16758
- ] }),
16686
+ )
16687
+ ] }) }),
16759
16688
  showMeta && /* @__PURE__ */ jsxs111("div", { className: "video-meta flex items-center justify-between mt-3 text-sm text-ods-text-secondary", children: [
16760
16689
  /* @__PURE__ */ jsx138("div", { className: "video-platform font-sans", children: "YouTube" }),
16761
16690
  /* @__PURE__ */ jsx138(
16762
16691
  "a",
16763
16692
  {
16764
- href: videoUrl,
16693
+ href: watchUrl,
16765
16694
  target: "_blank",
16766
16695
  rel: "noopener noreferrer",
16767
16696
  className: "video-link font-sans text-ods-accent hover:text-ods-accent-hover transition-colors duration-200",
@@ -16771,111 +16700,37 @@ var YouTubeEmbed = ({
16771
16700
  ] })
16772
16701
  ] });
16773
16702
  };
16703
+ var YT_HOSTS = /* @__PURE__ */ new Set([
16704
+ "youtube.com",
16705
+ "www.youtube.com",
16706
+ "m.youtube.com",
16707
+ "youtu.be",
16708
+ "youtube-nocookie.com",
16709
+ "www.youtube-nocookie.com"
16710
+ ]);
16711
+ var YT_PATH_RE = /^\/(?:embed|v|shorts)\/([^/]+)\/?$/;
16774
16712
  var extractYouTubeId = (url) => {
16775
- const patterns = [
16776
- /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
16777
- /youtube\.com\/v\/([^&\n?#]+)/,
16778
- /youtube\.com\/watch\?.*v=([^&\n?#]+)/
16779
- ];
16780
- for (const pattern of patterns) {
16781
- const match = url.match(pattern);
16782
- if (match) {
16783
- return match[1];
16784
- }
16713
+ let u;
16714
+ try {
16715
+ u = new URL(url);
16716
+ } catch {
16717
+ return null;
16785
16718
  }
16786
- return null;
16787
- };
16788
- var YouTubeLinkParser = ({ href, children }) => {
16789
- const videoId = extractYouTubeId(href);
16790
- if (videoId) {
16791
- return /* @__PURE__ */ jsx138(YouTubeEmbed, { videoId, title: typeof children === "string" ? children : void 0 });
16719
+ if (!YT_HOSTS.has(u.hostname.toLowerCase())) return null;
16720
+ if (u.hostname.toLowerCase().endsWith("youtu.be")) {
16721
+ return u.pathname.split("/").filter(Boolean)[0] ?? null;
16792
16722
  }
16793
- return /* @__PURE__ */ jsx138(
16794
- "a",
16795
- {
16796
- href,
16797
- target: "_blank",
16798
- rel: "noopener noreferrer",
16799
- className: "text-ods-accent hover:text-ods-accent-hover transition-colors duration-200",
16800
- children
16801
- }
16802
- );
16723
+ const v = u.searchParams.get("v");
16724
+ if (v) return v;
16725
+ const m = u.pathname.match(YT_PATH_RE);
16726
+ return m ? m[1] : null;
16803
16727
  };
16804
16728
 
16805
16729
  // src/components/features/video-player.tsx
16806
- import { useState as useState35, useEffect as useEffect26, useRef as useRef21, useMemo as useMemo11, useCallback as useCallback18 } from "react";
16807
- import ReactPlayer2 from "react-player";
16730
+ import { useState as useState35, useEffect as useEffect25, useRef as useRef22, useMemo as useMemo11, useCallback as useCallback19 } from "react";
16731
+ import ReactPlayer from "react-player";
16808
16732
  init_button2();
16809
16733
  import { jsx as jsx139, jsxs as jsxs112 } from "react/jsx-runtime";
16810
- function useVideoFirstFramePoster(url, enabled) {
16811
- const [poster, setPoster] = useState35(null);
16812
- useEffect26(() => {
16813
- if (!enabled || !url) {
16814
- setPoster(null);
16815
- return;
16816
- }
16817
- const isDirectFile = /\.(mp4|webm|mov|m4v)(\?|#|$)/i.test(url);
16818
- if (!isDirectFile) {
16819
- setPoster(null);
16820
- return;
16821
- }
16822
- let cancelled = false;
16823
- const video = document.createElement("video");
16824
- video.crossOrigin = "anonymous";
16825
- video.preload = "metadata";
16826
- video.muted = true;
16827
- video.playsInline = true;
16828
- video.setAttribute("data-poster-extractor", "true");
16829
- const cleanup = () => {
16830
- video.removeAttribute("src");
16831
- try {
16832
- video.load();
16833
- } catch {
16834
- }
16835
- };
16836
- const onLoadedMetadata = () => {
16837
- if (cancelled) return;
16838
- const dur = video.duration || 10;
16839
- const target = Math.max(2, Math.min(dur * 0.1, 30));
16840
- video.currentTime = target;
16841
- };
16842
- const onSeeked = () => {
16843
- if (cancelled) return;
16844
- try {
16845
- const canvas = document.createElement("canvas");
16846
- canvas.width = video.videoWidth;
16847
- canvas.height = video.videoHeight;
16848
- const ctx = canvas.getContext("2d");
16849
- if (!ctx || !canvas.width || !canvas.height) {
16850
- cleanup();
16851
- return;
16852
- }
16853
- ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
16854
- const dataUrl = canvas.toDataURL("image/jpeg", 0.82);
16855
- if (!cancelled) setPoster(dataUrl);
16856
- } catch (err) {
16857
- console.warn("[VideoPlayer] first-frame extraction failed", err);
16858
- } finally {
16859
- cleanup();
16860
- }
16861
- };
16862
- const onError = () => {
16863
- cleanup();
16864
- };
16865
- video.addEventListener("loadedmetadata", onLoadedMetadata);
16866
- video.addEventListener("seeked", onSeeked);
16867
- video.addEventListener("error", onError);
16868
- video.src = url;
16869
- return () => {
16870
- cancelled = true;
16871
- video.removeEventListener("loadedmetadata", onLoadedMetadata);
16872
- video.removeEventListener("seeked", onSeeked);
16873
- video.removeEventListener("error", onError);
16874
- cleanup();
16875
- };
16876
- }, [url, enabled]);
16877
- return poster;
16878
- }
16879
16734
  var webkitCaptionCSSInjected = false;
16880
16735
  function ensureWebkitCaptionCSS() {
16881
16736
  if (webkitCaptionCSSInjected || typeof document === "undefined") return;
@@ -16918,7 +16773,7 @@ function parseSrtTimestamp(ts) {
16918
16773
  function useSubtitleOverlay(srtContent) {
16919
16774
  const cues = useMemo11(() => srtContent ? parseSrt(srtContent) : [], [srtContent]);
16920
16775
  const [activeText, setActiveText] = useState35(null);
16921
- const updateTime = useCallback18((playedSeconds) => {
16776
+ const updateTime = useCallback19((playedSeconds) => {
16922
16777
  const timeMs = playedSeconds * 1e3;
16923
16778
  const active = cues.find((c) => timeMs >= c.from && timeMs <= c.to);
16924
16779
  setActiveText(active?.text ?? null);
@@ -16926,7 +16781,6 @@ function useSubtitleOverlay(srtContent) {
16926
16781
  return { activeText, updateTime, hasCues: cues.length > 0 };
16927
16782
  }
16928
16783
  var SPEED_OPTIONS = [0.5, 0.75, 1, 1.25, 1.5, 2];
16929
- var LAZY_MOUNT_PLAY_FAILURE_GRACE_MS = 2e3;
16930
16784
  function formatTime(secs) {
16931
16785
  if (!secs || !isFinite(secs)) return "0:00";
16932
16786
  const h = Math.floor(secs / 3600);
@@ -16948,14 +16802,14 @@ var VideoPlayer = ({
16948
16802
  srtContent,
16949
16803
  captionsUrl,
16950
16804
  subtitleLabel,
16951
- lazyMount = false
16805
+ preloadStrategy = "metadata"
16952
16806
  }) => {
16953
16807
  const [hasError, setHasError] = useState35(false);
16954
16808
  const [isPlaying, setIsPlaying] = useState35(autoPlay);
16955
16809
  const [mounted, setMounted] = useState35(false);
16956
16810
  const [hasStarted, setHasStarted] = useState35(autoPlay);
16957
- const playerRef = useRef21(null);
16958
- const containerRef = useRef21(null);
16811
+ const playerRef = useRef22(null);
16812
+ const containerRef = useRef22(null);
16959
16813
  const [played, setPlayed] = useState35(0);
16960
16814
  const [loaded, setLoaded] = useState35(0);
16961
16815
  const [duration, setDuration] = useState35(0);
@@ -16964,14 +16818,13 @@ var VideoPlayer = ({
16964
16818
  const [isMuted, setIsMuted] = useState35(muted);
16965
16819
  const [isBuffering, setIsBuffering] = useState35(false);
16966
16820
  const [showControls, setShowControls] = useState35(true);
16967
- const hideTimeoutRef = useRef21(void 0);
16968
- const clickTimerRef = useRef21(void 0);
16969
- const iosFullscreenTimerRef = useRef21(void 0);
16970
- const lazyMountFailureTimerRef = useRef21(void 0);
16821
+ const hideTimeoutRef = useRef22(void 0);
16822
+ const clickTimerRef = useRef22(void 0);
16823
+ const iosFullscreenTimerRef = useRef22(void 0);
16971
16824
  const [captionsEnabled, setCaptionsEnabled] = useState35(true);
16972
16825
  const [isFullscreen, setIsFullscreen] = useState35(false);
16973
16826
  const { activeText, updateTime, hasCues } = useSubtitleOverlay(srtContent);
16974
- useEffect26(() => {
16827
+ useEffect25(() => {
16975
16828
  const onChange = () => {
16976
16829
  const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
16977
16830
  setIsFullscreen(!!fsEl);
@@ -16983,14 +16836,14 @@ var VideoPlayer = ({
16983
16836
  document.removeEventListener("webkitfullscreenchange", onChange);
16984
16837
  };
16985
16838
  }, []);
16986
- const activateCaptionTracks = useCallback18((video) => {
16839
+ const activateCaptionTracks = useCallback19((video) => {
16987
16840
  for (let i = 0; i < video.textTracks.length; i++) {
16988
16841
  if (video.textTracks[i].kind === "captions" || video.textTracks[i].kind === "subtitles") {
16989
16842
  video.textTracks[i].mode = "showing";
16990
16843
  }
16991
16844
  }
16992
16845
  }, []);
16993
- const enterNativeVideoFullscreen = useCallback18(() => {
16846
+ const enterNativeVideoFullscreen = useCallback19(() => {
16994
16847
  const video = playerRef.current?.getInternalPlayer();
16995
16848
  if (!video || !video.webkitEnterFullscreen) return;
16996
16849
  ensureWebkitCaptionCSS();
@@ -17029,7 +16882,7 @@ var VideoPlayer = ({
17029
16882
  doFullscreen();
17030
16883
  }, 500);
17031
16884
  }, [captionsUrl, subtitleLabel, activateCaptionTracks]);
17032
- const toggleFullscreen = useCallback18(() => {
16885
+ const toggleFullscreen = useCallback19(() => {
17033
16886
  const container = containerRef.current;
17034
16887
  if (!container) return;
17035
16888
  if (isFullscreen) {
@@ -17048,7 +16901,7 @@ var VideoPlayer = ({
17048
16901
  enterNativeVideoFullscreen();
17049
16902
  }
17050
16903
  }, [isFullscreen, enterNativeVideoFullscreen]);
17051
- const toggleMute = useCallback18(() => {
16904
+ const toggleMute = useCallback19(() => {
17052
16905
  if (isMuted) {
17053
16906
  setIsMuted(false);
17054
16907
  setVolume(prevVolume || 0.5);
@@ -17058,23 +16911,23 @@ var VideoPlayer = ({
17058
16911
  setVolume(0);
17059
16912
  }
17060
16913
  }, [isMuted, volume, prevVolume]);
17061
- const handleVolumeChange = useCallback18((e) => {
16914
+ const handleVolumeChange = useCallback19((e) => {
17062
16915
  const val = parseFloat(e.target.value);
17063
16916
  setVolume(val);
17064
16917
  setIsMuted(val === 0);
17065
16918
  if (val > 0) setPrevVolume(val);
17066
16919
  }, []);
17067
- const startHideTimer = useCallback18(() => {
16920
+ const startHideTimer = useCallback19(() => {
17068
16921
  clearTimeout(hideTimeoutRef.current);
17069
16922
  if (isPlaying) {
17070
16923
  hideTimeoutRef.current = setTimeout(() => setShowControls(false), 3e3);
17071
16924
  }
17072
16925
  }, [isPlaying]);
17073
- const handleMouseMove = useCallback18(() => {
16926
+ const handleMouseMove = useCallback19(() => {
17074
16927
  setShowControls(true);
17075
16928
  startHideTimer();
17076
16929
  }, [startHideTimer]);
17077
- const handleTouchToggle = useCallback18(() => {
16930
+ const handleTouchToggle = useCallback19(() => {
17078
16931
  if (!hasStarted) return;
17079
16932
  setShowControls((prev) => {
17080
16933
  const next = !prev;
@@ -17085,7 +16938,7 @@ var VideoPlayer = ({
17085
16938
  return next;
17086
16939
  });
17087
16940
  }, [hasStarted, isPlaying]);
17088
- useEffect26(() => {
16941
+ useEffect25(() => {
17089
16942
  if (!hasStarted) return;
17090
16943
  const el = containerRef.current;
17091
16944
  if (!el) return;
@@ -17143,23 +16996,23 @@ var VideoPlayer = ({
17143
16996
  }, [hasStarted, duration, toggleMute, toggleFullscreen]);
17144
16997
  const [seekPreview, setSeekPreview] = useState35(null);
17145
16998
  const [playbackRate, setPlaybackRate] = useState35(1);
17146
- const cycleSpeed = useCallback18(() => {
16999
+ const cycleSpeed = useCallback19(() => {
17147
17000
  setPlaybackRate((prev) => {
17148
17001
  const idx = SPEED_OPTIONS.indexOf(prev);
17149
17002
  return SPEED_OPTIONS[(idx + 1) % SPEED_OPTIONS.length];
17150
17003
  });
17151
17004
  }, []);
17152
- const progressBarRef = useRef21(null);
17153
- const isDraggingRef = useRef21(false);
17154
- const dragListenersRef = useRef21(null);
17155
- const seekToClientX = useCallback18((clientX) => {
17005
+ const progressBarRef = useRef22(null);
17006
+ const isDraggingRef = useRef22(false);
17007
+ const dragListenersRef = useRef22(null);
17008
+ const seekToClientX = useCallback19((clientX) => {
17156
17009
  const rect = progressBarRef.current?.getBoundingClientRect();
17157
17010
  if (!rect) return;
17158
17011
  const fraction = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
17159
17012
  setPlayed(fraction);
17160
17013
  playerRef.current?.seekTo(fraction, "fraction");
17161
17014
  }, []);
17162
- const handleProgressMouseDown = useCallback18((e) => {
17015
+ const handleProgressMouseDown = useCallback19((e) => {
17163
17016
  e.stopPropagation();
17164
17017
  e.preventDefault();
17165
17018
  isDraggingRef.current = true;
@@ -17182,17 +17035,17 @@ var VideoPlayer = ({
17182
17035
  document.addEventListener("mousemove", onMouseMove);
17183
17036
  document.addEventListener("mouseup", onMouseUp);
17184
17037
  }, [seekToClientX]);
17185
- const handleProgressTouchStart = useCallback18((e) => {
17038
+ const handleProgressTouchStart = useCallback19((e) => {
17186
17039
  e.stopPropagation();
17187
17040
  const touch = e.touches[0];
17188
17041
  if (touch) seekToClientX(touch.clientX);
17189
17042
  }, [seekToClientX]);
17190
- const handleProgressTouchMove = useCallback18((e) => {
17043
+ const handleProgressTouchMove = useCallback19((e) => {
17191
17044
  e.stopPropagation();
17192
17045
  const touch = e.touches[0];
17193
17046
  if (touch) seekToClientX(touch.clientX);
17194
17047
  }, [seekToClientX]);
17195
- const handleProgressKeyDown = useCallback18((e) => {
17048
+ const handleProgressKeyDown = useCallback19((e) => {
17196
17049
  if (e.key === "ArrowRight") {
17197
17050
  e.preventDefault();
17198
17051
  e.stopPropagation();
@@ -17214,15 +17067,15 @@ var VideoPlayer = ({
17214
17067
  playerRef.current?.seekTo(duration, "seconds");
17215
17068
  }
17216
17069
  }, [duration]);
17217
- const handleProgressHover = useCallback18((e) => {
17070
+ const handleProgressHover = useCallback19((e) => {
17218
17071
  if (isDraggingRef.current) return;
17219
17072
  const rect = e.currentTarget.getBoundingClientRect();
17220
17073
  const fraction = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
17221
17074
  const x = Math.max(30, Math.min(rect.width - 30, e.clientX - rect.left));
17222
17075
  setSeekPreview({ fraction, x });
17223
17076
  }, []);
17224
- const isTouchRef = useRef21(false);
17225
- const handleContainerClick = useCallback18((e) => {
17077
+ const isTouchRef = useRef22(false);
17078
+ const handleContainerClick = useCallback19((e) => {
17226
17079
  if (isTouchRef.current) {
17227
17080
  isTouchRef.current = false;
17228
17081
  return;
@@ -17240,22 +17093,20 @@ var VideoPlayer = ({
17240
17093
  }, 250);
17241
17094
  }
17242
17095
  }, [hasStarted, toggleFullscreen]);
17243
- const handleContainerTouchEnd = useCallback18((e) => {
17096
+ const handleContainerTouchEnd = useCallback19((e) => {
17244
17097
  if (e.target.closest(".video-controls-bar")) return;
17245
17098
  isTouchRef.current = true;
17246
17099
  if (!hasStarted) return;
17247
17100
  handleTouchToggle();
17248
17101
  }, [hasStarted, handleTouchToggle]);
17249
- const extractedPoster = useVideoFirstFramePoster(url, !lazyMount && !hasStarted && !poster);
17250
- const effectivePoster = poster || extractedPoster || void 0;
17102
+ const effectivePoster = poster || void 0;
17251
17103
  const posterBgColor = useImageEdgeColor(effectivePoster);
17252
- useEffect26(() => {
17104
+ useEffect25(() => {
17253
17105
  setMounted(true);
17254
17106
  return () => {
17255
17107
  clearTimeout(clickTimerRef.current);
17256
17108
  clearTimeout(hideTimeoutRef.current);
17257
17109
  clearTimeout(iosFullscreenTimerRef.current);
17258
- clearTimeout(lazyMountFailureTimerRef.current);
17259
17110
  isDraggingRef.current = false;
17260
17111
  if (dragListenersRef.current) {
17261
17112
  document.removeEventListener("mousemove", dragListenersRef.current.move);
@@ -17264,7 +17115,7 @@ var VideoPlayer = ({
17264
17115
  }
17265
17116
  };
17266
17117
  }, []);
17267
- useEffect26(() => {
17118
+ useEffect25(() => {
17268
17119
  if (!hasStarted) return;
17269
17120
  const video = playerRef.current?.getInternalPlayer();
17270
17121
  if (!video) return;
@@ -17272,37 +17123,31 @@ var VideoPlayer = ({
17272
17123
  video.addEventListener("webkitbeginfullscreen", onBeginFS);
17273
17124
  return () => video.removeEventListener("webkitbeginfullscreen", onBeginFS);
17274
17125
  }, [hasStarted, activateCaptionTracks]);
17275
- const handleError = useCallback18(() => setHasError(true), []);
17276
- const handlePlay = useCallback18(() => {
17126
+ const handleError = useCallback19(() => setHasError(true), []);
17127
+ const handlePlay = useCallback19(() => {
17277
17128
  setIsPlaying(true);
17278
17129
  setHasStarted(true);
17279
17130
  }, []);
17280
- const handlePause = useCallback18(() => setIsPlaying(false), []);
17281
- const handleEnded = useCallback18(() => setIsPlaying(false), []);
17282
- const handlePlayClick = useCallback18(() => {
17283
- if (lazyMount) {
17284
- const native = playerRef.current?.getInternalPlayer();
17285
- if (native instanceof HTMLVideoElement) {
17286
- native.play().catch(() => {
17287
- clearTimeout(lazyMountFailureTimerRef.current);
17288
- lazyMountFailureTimerRef.current = setTimeout(() => {
17289
- if (native.paused && native.error) setHasError(true);
17290
- }, LAZY_MOUNT_PLAY_FAILURE_GRACE_MS);
17291
- });
17292
- } else if (process.env.NODE_ENV !== "production") {
17293
- console.warn("[VideoPlayer] lazyMount sync play(): no native HTMLVideoElement yet");
17294
- }
17131
+ const handlePause = useCallback19(() => setIsPlaying(false), []);
17132
+ const handleEnded = useCallback19(() => setIsPlaying(false), []);
17133
+ const handlePlayClick = useCallback19(() => {
17134
+ const native = playerRef.current?.getInternalPlayer();
17135
+ if (native instanceof HTMLVideoElement) {
17136
+ native.play().catch(() => {
17137
+ });
17138
+ } else if (process.env.NODE_ENV !== "production") {
17139
+ console.warn("[VideoPlayer] sync play(): no native HTMLVideoElement yet");
17295
17140
  }
17296
17141
  setHasStarted(true);
17297
17142
  setIsPlaying(true);
17298
- }, [lazyMount]);
17299
- const handleProgress = useCallback18(({ played: p, loaded: l, playedSeconds }) => {
17143
+ }, []);
17144
+ const handleProgress = useCallback19(({ played: p, loaded: l, playedSeconds }) => {
17300
17145
  setPlayed(p);
17301
17146
  setLoaded(l);
17302
17147
  updateTime(playedSeconds);
17303
17148
  }, [updateTime]);
17304
- const handleBuffer = useCallback18(() => setIsBuffering(true), []);
17305
- const handleBufferEnd = useCallback18(() => setIsBuffering(false), []);
17149
+ const handleBuffer = useCallback19(() => setIsBuffering(true), []);
17150
+ const handleBufferEnd = useCallback19(() => setIsBuffering(false), []);
17306
17151
  if (!mounted) {
17307
17152
  return /* @__PURE__ */ jsx139("div", { className: `video-player-container ${className}`, children: /* @__PURE__ */ jsx139(
17308
17153
  "div",
@@ -17349,7 +17194,7 @@ var VideoPlayer = ({
17349
17194
  /* @__PURE__ */ jsx139("div", { className: `absolute inset-0 ${effectivePoster ? "bg-black/40" : "bg-black/20"} group-hover:bg-black/50 transition-all flex items-center justify-center rounded-md`, children: /* @__PURE__ */ jsx139("div", { className: "w-16 h-16 rounded-full bg-ods-accent hover:bg-ods-accent/90 transition-all flex items-center justify-center shadow-lg", children: /* @__PURE__ */ jsx139(PlayIcon, { size: 24, className: "ml-1 text-ods-text-on-accent" }) }) })
17350
17195
  ] }),
17351
17196
  /* @__PURE__ */ jsx139("div", { className: isFullscreen ? "video-player absolute inset-0" : useNativeAspectRatio ? "video-player rounded-md overflow-hidden border border-ods-border bg-ods-background" : "video-player absolute inset-0 rounded-md overflow-hidden border border-ods-border bg-ods-background", children: /* @__PURE__ */ jsx139(
17352
- ReactPlayer2,
17197
+ ReactPlayer,
17353
17198
  {
17354
17199
  ref: playerRef,
17355
17200
  url,
@@ -17370,7 +17215,7 @@ var VideoPlayer = ({
17370
17215
  onBufferEnd: handleBufferEnd,
17371
17216
  onProgress: handleProgress,
17372
17217
  progressInterval: 200,
17373
- config: { file: { attributes: { controlsList: "nodownload", playsInline: true, preload: lazyMount && !hasStarted ? "none" : hasStarted ? "auto" : "metadata" } } },
17218
+ config: { file: { attributes: { controlsList: "nodownload", playsInline: true, preload: hasStarted ? "auto" : preloadStrategy } } },
17374
17219
  light: false,
17375
17220
  playsinline: true
17376
17221
  }
@@ -17585,7 +17430,7 @@ import React46 from "react";
17585
17430
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
17586
17431
  import { Check as Check2 } from "lucide-react";
17587
17432
  import Link3 from "next/link";
17588
- import React45, { useCallback as useCallback19, useState as useState36 } from "react";
17433
+ import React45, { useCallback as useCallback20, useState as useState36 } from "react";
17589
17434
  init_cn();
17590
17435
  init_button2();
17591
17436
  import { Fragment as Fragment19, jsx as jsx140, jsxs as jsxs113 } from "react/jsx-runtime";
@@ -17593,7 +17438,7 @@ var ROW_CLASSES = "flex flex-1 min-w-0 items-center gap-2 px-3 py-3 cursor-point
17593
17438
  var WRAPPER_CLASSES = "relative flex items-stretch border-b border-ods-border last:border-b-0";
17594
17439
  var SECONDARY_ACTION_CLASSES = "flex w-10 shrink-0 items-center justify-center self-stretch border-l border-ods-border transition-colors hover:bg-ods-bg-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus";
17595
17440
  var SecondaryAction = ({ action }) => {
17596
- const handleClick = useCallback19(
17441
+ const handleClick = useCallback20(
17597
17442
  (e) => {
17598
17443
  e.stopPropagation();
17599
17444
  if (action.disabled) {
@@ -17638,7 +17483,7 @@ var SecondaryAction = ({ action }) => {
17638
17483
  );
17639
17484
  };
17640
17485
  var MenuItem = ({ item, onItemClick }) => {
17641
- const activate = useCallback19(() => {
17486
+ const activate = useCallback20(() => {
17642
17487
  if (item.disabled) return;
17643
17488
  if (item.type === "checkbox") {
17644
17489
  item.onClick?.();
@@ -17649,7 +17494,7 @@ var MenuItem = ({ item, onItemClick }) => {
17649
17494
  item.onClick?.();
17650
17495
  onItemClick?.(item);
17651
17496
  }, [item, onItemClick]);
17652
- const handleClick = useCallback19(
17497
+ const handleClick = useCallback20(
17653
17498
  (e) => {
17654
17499
  e.stopPropagation();
17655
17500
  e.preventDefault();
@@ -17657,7 +17502,7 @@ var MenuItem = ({ item, onItemClick }) => {
17657
17502
  },
17658
17503
  [activate]
17659
17504
  );
17660
- const handleKeyDown = useCallback19(
17505
+ const handleKeyDown = useCallback20(
17661
17506
  (e) => {
17662
17507
  if (e.key !== "Enter" && e.key !== " ") return;
17663
17508
  e.preventDefault();
@@ -17666,7 +17511,7 @@ var MenuItem = ({ item, onItemClick }) => {
17666
17511
  },
17667
17512
  [activate]
17668
17513
  );
17669
- const handleLinkClick = useCallback19(
17514
+ const handleLinkClick = useCallback20(
17670
17515
  (e) => {
17671
17516
  if (item.disabled) {
17672
17517
  e.preventDefault();
@@ -17827,7 +17672,7 @@ var ActionsMenuDropdown = ({
17827
17672
  sideOffset = 6
17828
17673
  }) => {
17829
17674
  const [open, setOpen] = useState36(false);
17830
- const handleItemClick = useCallback19(
17675
+ const handleItemClick = useCallback20(
17831
17676
  (item) => {
17832
17677
  onItemClick?.(item);
17833
17678
  if (item.type !== "checkbox" && item.type !== "submenu") {
@@ -18355,7 +18200,7 @@ function ReleaseDetailPage({
18355
18200
  const [deliveryData, setDeliveryData] = useState37(null);
18356
18201
  const [roadmapLoading, setRoadmapLoading] = useState37(false);
18357
18202
  const [deliveryLoading, setDeliveryLoading] = useState37(false);
18358
- useEffect27(() => {
18203
+ useEffect26(() => {
18359
18204
  async function fetchLinkedTasks() {
18360
18205
  if (!release) return;
18361
18206
  try {
@@ -18910,7 +18755,7 @@ function CompactPageLoader({
18910
18755
  }
18911
18756
 
18912
18757
  // src/components/ui/progress-bar.tsx
18913
- import { useEffect as useEffect29, useRef as useRef22, useState as useState39 } from "react";
18758
+ import { useEffect as useEffect28, useRef as useRef23, useState as useState39 } from "react";
18914
18759
  import { jsx as jsx152 } from "react/jsx-runtime";
18915
18760
  var ProgressBar = ({
18916
18761
  progress,
@@ -18926,9 +18771,9 @@ var ProgressBar = ({
18926
18771
  const isMdUp = useMdUp() ?? true;
18927
18772
  const effectiveSegmentWidth = isMdUp ? segmentWidth : mobileSegmentWidth;
18928
18773
  const effectiveHeight = isMdUp ? height : mobileHeight;
18929
- const containerRef = useRef22(null);
18774
+ const containerRef = useRef23(null);
18930
18775
  const [segmentCount, setSegmentCount] = useState39(0);
18931
- useEffect29(() => {
18776
+ useEffect28(() => {
18932
18777
  if (!containerRef.current) return;
18933
18778
  const resizeObserver = new ResizeObserver(() => {
18934
18779
  if (containerRef.current) {
@@ -19752,11 +19597,11 @@ DialogDescription.displayName = DialogPrimitive3.Description.displayName;
19752
19597
  // src/components/ui/modal.tsx
19753
19598
  init_cn();
19754
19599
  import * as React56 from "react";
19755
- import { useEffect as useEffect30 } from "react";
19600
+ import { useEffect as useEffect29 } from "react";
19756
19601
  import { jsx as jsx158, jsxs as jsxs129 } from "react/jsx-runtime";
19757
19602
  var Modal = React56.forwardRef(
19758
19603
  ({ isOpen, onClose, children, className }, ref) => {
19759
- useEffect30(() => {
19604
+ useEffect29(() => {
19760
19605
  const handleKeyDown = (event) => {
19761
19606
  if (event.key === "Escape") {
19762
19607
  onClose();
@@ -19838,13 +19683,13 @@ ModalFooter.displayName = "ModalFooter";
19838
19683
 
19839
19684
  // src/components/ui/modal-v2.tsx
19840
19685
  import * as React57 from "react";
19841
- import { useEffect as useEffect31 } from "react";
19686
+ import { useEffect as useEffect30 } from "react";
19842
19687
  init_cn();
19843
19688
  import { jsx as jsx159, jsxs as jsxs130 } from "react/jsx-runtime";
19844
19689
  var ModalContext = React57.createContext({});
19845
19690
  var Modal2 = React57.forwardRef(
19846
19691
  ({ isOpen, onClose, children, className }, ref) => {
19847
- useEffect31(() => {
19692
+ useEffect30(() => {
19848
19693
  const handleKeyDown = (event) => {
19849
19694
  if (event.key === "Escape") {
19850
19695
  onClose();
@@ -20518,7 +20363,7 @@ function TabContent({
20518
20363
 
20519
20364
  // src/components/ui/tab-navigation.tsx
20520
20365
  init_cn();
20521
- import { useState as useState42, useEffect as useEffect32, useMemo as useMemo12, useRef as useRef24, useCallback as useCallback21 } from "react";
20366
+ import { useState as useState42, useEffect as useEffect31, useMemo as useMemo12, useRef as useRef25, useCallback as useCallback22 } from "react";
20522
20367
  import { useSearchParams as useSearchParams3, useRouter as useRouter5, usePathname as usePathname3 } from "next/navigation";
20523
20368
  import { Fragment as Fragment22, jsx as jsx168, jsxs as jsxs137 } from "react/jsx-runtime";
20524
20369
  function TabNavigation({
@@ -20551,7 +20396,7 @@ function TabNavigation({
20551
20396
  };
20552
20397
  const [internalActiveTab, setInternalActiveTab] = useState42(getInitialTab);
20553
20398
  const activeTab = isUrlSyncEnabled ? internalActiveTab : controlledActiveTab || "";
20554
- useEffect32(() => {
20399
+ useEffect31(() => {
20555
20400
  if (!isUrlSyncEnabled) return;
20556
20401
  const fromUrl = searchParams?.get(paramName) || "";
20557
20402
  const nextTab = validTabIds.has(fromUrl) ? fromUrl : defaultTab || tabs[0]?.id || "";
@@ -20571,16 +20416,16 @@ function TabNavigation({
20571
20416
  controlledOnTabChange?.(tabId);
20572
20417
  }
20573
20418
  };
20574
- const scrollRef = useRef24(null);
20419
+ const scrollRef = useRef25(null);
20575
20420
  const [canScrollLeft, setCanScrollLeft] = useState42(false);
20576
20421
  const [canScrollRight, setCanScrollRight] = useState42(false);
20577
- const updateScrollShadows = useCallback21(() => {
20422
+ const updateScrollShadows = useCallback22(() => {
20578
20423
  const el = scrollRef.current;
20579
20424
  if (!el) return;
20580
20425
  setCanScrollLeft(el.scrollLeft > 0);
20581
20426
  setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
20582
20427
  }, []);
20583
- useEffect32(() => {
20428
+ useEffect31(() => {
20584
20429
  const el = scrollRef.current;
20585
20430
  if (!el) return;
20586
20431
  updateScrollShadows();
@@ -20769,11 +20614,11 @@ function StatusIndicator({ status, label, href }) {
20769
20614
 
20770
20615
  // src/components/layout/list-page-layout.tsx
20771
20616
  init_cn();
20772
- import { useEffect as useEffect34, useState as useState44 } from "react";
20617
+ import { useEffect as useEffect33, useState as useState44 } from "react";
20773
20618
 
20774
20619
  // src/components/ui/filter-modal.tsx
20775
20620
  init_cn();
20776
- import { useEffect as useEffect33, useState as useState43 } from "react";
20621
+ import { useEffect as useEffect32, useState as useState43 } from "react";
20777
20622
  init_button2();
20778
20623
 
20779
20624
  // src/components/ui/filter-checkbox-item.tsx
@@ -20973,7 +20818,7 @@ function FilterModal({
20973
20818
  return { ...currentFilters };
20974
20819
  });
20975
20820
  const [pendingTags, setPendingTags] = useState43(selectedTags ?? []);
20976
- useEffect33(() => {
20821
+ useEffect32(() => {
20977
20822
  if (isOpen) {
20978
20823
  setSelectedFilters({ ...currentFilters });
20979
20824
  setPendingTags(selectedTags ?? []);
@@ -21119,10 +20964,10 @@ function ListPageLayout({
21119
20964
  const [mobileFilterOpen, setMobileFilterOpen] = useState44(false);
21120
20965
  const [localSearchValue, setLocalSearchValue] = useState44(searchValue);
21121
20966
  const debouncedSearchValue = useDebounce(localSearchValue, 500);
21122
- useEffect34(() => {
20967
+ useEffect33(() => {
21123
20968
  setLocalSearchValue(searchValue);
21124
20969
  }, [searchValue]);
21125
- useEffect34(() => {
20970
+ useEffect33(() => {
21126
20971
  if (debouncedSearchValue !== searchValue) {
21127
20972
  onSearch(debouncedSearchValue);
21128
20973
  }
@@ -23299,7 +23144,7 @@ var ListLoader = (props) => /* @__PURE__ */ jsx206(ContentLoader, { ...props, va
23299
23144
 
23300
23145
  // src/components/ui/table/table.tsx
23301
23146
  init_cn();
23302
- import { useEffect as useEffect35, useRef as useRef27 } from "react";
23147
+ import { useEffect as useEffect34, useRef as useRef28 } from "react";
23303
23148
  init_pagination();
23304
23149
  init_button2();
23305
23150
 
@@ -24050,10 +23895,10 @@ function Table({
24050
23895
  };
24051
23896
  const allSelected = selectedRows.length > 0 && selectedRows.length === data.length;
24052
23897
  const someSelected = selectedRows.length > 0 && selectedRows.length < data.length;
24053
- const sentinelRef = useRef27(null);
24054
- const onLoadMoreRef = useRef27(infiniteScroll?.onLoadMore);
23898
+ const sentinelRef = useRef28(null);
23899
+ const onLoadMoreRef = useRef28(infiniteScroll?.onLoadMore);
24055
23900
  onLoadMoreRef.current = infiniteScroll?.onLoadMore;
24056
- useEffect35(() => {
23901
+ useEffect34(() => {
24057
23902
  if (!infiniteScroll?.hasNextPage || infiniteScroll.isFetchingNextPage) return;
24058
23903
  const sentinel = sentinelRef.current;
24059
23904
  if (!sentinel) return;
@@ -24265,7 +24110,7 @@ import { useMemo as useMemo16 } from "react";
24265
24110
 
24266
24111
  // src/components/ui/query-report-table/query-report-table-header.tsx
24267
24112
  init_cn();
24268
- import { useRef as useRef28, useState as useState47, useCallback as useCallback22 } from "react";
24113
+ import { useRef as useRef29, useState as useState47, useCallback as useCallback23 } from "react";
24269
24114
  import { jsx as jsx217, jsxs as jsxs176 } from "react/jsx-runtime";
24270
24115
  function QueryReportTableHeader({
24271
24116
  columns,
@@ -24294,9 +24139,9 @@ function QueryReportTableHeader({
24294
24139
  );
24295
24140
  }
24296
24141
  function TruncatedHeaderCell({ value, width }) {
24297
- const textRef = useRef28(null);
24142
+ const textRef = useRef29(null);
24298
24143
  const [isTruncated, setIsTruncated] = useState47(false);
24299
- const checkTruncation = useCallback22(() => {
24144
+ const checkTruncation = useCallback23(() => {
24300
24145
  const el = textRef.current;
24301
24146
  if (el) {
24302
24147
  setIsTruncated(el.scrollWidth > el.clientWidth);
@@ -24324,7 +24169,7 @@ function TruncatedHeaderCell({ value, width }) {
24324
24169
 
24325
24170
  // src/components/ui/query-report-table/query-report-table-row.tsx
24326
24171
  init_cn();
24327
- import { useRef as useRef29, useState as useState48, useCallback as useCallback23 } from "react";
24172
+ import { useRef as useRef30, useState as useState48, useCallback as useCallback24 } from "react";
24328
24173
  import { jsx as jsx218, jsxs as jsxs177 } from "react/jsx-runtime";
24329
24174
  function QueryReportTableRow({
24330
24175
  row,
@@ -24370,9 +24215,9 @@ function QueryReportTableRow({
24370
24215
  );
24371
24216
  }
24372
24217
  function TruncatedCell({ value, className }) {
24373
- const textRef = useRef29(null);
24218
+ const textRef = useRef30(null);
24374
24219
  const [isTruncated, setIsTruncated] = useState48(false);
24375
- const checkTruncation = useCallback23(() => {
24220
+ const checkTruncation = useCallback24(() => {
24376
24221
  const el = textRef.current;
24377
24222
  if (el) {
24378
24223
  setIsTruncated(el.scrollWidth > el.clientWidth);
@@ -24635,7 +24480,7 @@ init_cn();
24635
24480
 
24636
24481
  // src/components/ui/data-table/data-table-column-filter.tsx
24637
24482
  init_cn();
24638
- import { useCallback as useCallback24, useMemo as useMemo17 } from "react";
24483
+ import { useCallback as useCallback25, useMemo as useMemo17 } from "react";
24639
24484
 
24640
24485
  // src/components/ui/data-table/utils.ts
24641
24486
  function getHideClasses2(hideAt) {
@@ -24695,14 +24540,14 @@ function DataTableColumnFilter({
24695
24540
  () => ({ [column.id]: currentValue ?? EMPTY_ARRAY }),
24696
24541
  [column.id, currentValue]
24697
24542
  );
24698
- const handleApply = useCallback24(
24543
+ const handleApply = useCallback25(
24699
24544
  (applied) => {
24700
24545
  const next = applied[column.id] ?? [];
24701
24546
  column.setFilterValue(next.length > 0 ? next : void 0);
24702
24547
  },
24703
24548
  [column]
24704
24549
  );
24705
- const handleReset = useCallback24(() => {
24550
+ const handleReset = useCallback25(() => {
24706
24551
  column.setFilterValue(void 0);
24707
24552
  }, [column]);
24708
24553
  return /* @__PURE__ */ jsx222(
@@ -24889,7 +24734,7 @@ function DataTableEmpty({
24889
24734
  // src/components/ui/data-table/data-table-row.tsx
24890
24735
  init_cn();
24891
24736
  import Link10 from "next/link";
24892
- import { memo as memo4, useCallback as useCallback25 } from "react";
24737
+ import { memo as memo4, useCallback as useCallback26 } from "react";
24893
24738
  import { flexRender as flexRender2 } from "@tanstack/react-table";
24894
24739
 
24895
24740
  // src/components/ui/data-table/data-table-skeleton.tsx
@@ -24970,7 +24815,7 @@ function DataTableRowImpl({
24970
24815
  className
24971
24816
  }) {
24972
24817
  const isLinkMode = Boolean(href) && !onClick;
24973
- const handleClick = useCallback25(
24818
+ const handleClick = useCallback26(
24974
24819
  (e) => {
24975
24820
  const target = e.target;
24976
24821
  if (target.closest("[data-no-row-click]")) return;
@@ -25107,7 +24952,7 @@ function DataTableBody({
25107
24952
  }
25108
24953
 
25109
24954
  // src/components/ui/data-table/data-table-infinite-footer.tsx
25110
- import { useEffect as useEffect36, useRef as useRef30 } from "react";
24955
+ import { useEffect as useEffect35, useRef as useRef31 } from "react";
25111
24956
  import { Fragment as Fragment34, jsx as jsx228, jsxs as jsxs186 } from "react/jsx-runtime";
25112
24957
  function DataTableInfiniteFooter({
25113
24958
  hasNextPage,
@@ -25116,10 +24961,10 @@ function DataTableInfiniteFooter({
25116
24961
  skeletonRows = 3,
25117
24962
  rootMargin = "200px"
25118
24963
  }) {
25119
- const sentinelRef = useRef30(null);
25120
- const onLoadMoreRef = useRef30(onLoadMore);
24964
+ const sentinelRef = useRef31(null);
24965
+ const onLoadMoreRef = useRef31(onLoadMore);
25121
24966
  onLoadMoreRef.current = onLoadMore;
25122
- useEffect36(() => {
24967
+ useEffect35(() => {
25123
24968
  if (!hasNextPage || isFetchingNextPage) return;
25124
24969
  const sentinel = sentinelRef.current;
25125
24970
  if (!sentinel) return;
@@ -25244,7 +25089,7 @@ var DataTable = Object.assign(DataTableRoot, {
25244
25089
  });
25245
25090
 
25246
25091
  // src/components/ui/phone-input.tsx
25247
- import { useCallback as useCallback26, useEffect as useEffect37, useMemo as useMemo18, useRef as useRef31, useState as useState49 } from "react";
25092
+ import { useCallback as useCallback27, useEffect as useEffect36, useMemo as useMemo18, useRef as useRef32, useState as useState49 } from "react";
25248
25093
  import { jsx as jsx230, jsxs as jsxs188 } from "react/jsx-runtime";
25249
25094
  function PhoneInput({
25250
25095
  value,
@@ -25262,9 +25107,9 @@ function PhoneInput({
25262
25107
  [countryCode, priority, others]
25263
25108
  );
25264
25109
  const [isInvalid, setIsInvalid] = useState49(false);
25265
- const debounceRef = useRef31(null);
25266
- const digitCount = useCallback26((val) => val.replace(/[^0-9]/g, "").length, []);
25267
- const runValidation = useCallback26((phone) => {
25110
+ const debounceRef = useRef32(null);
25111
+ const digitCount = useCallback27((val) => val.replace(/[^0-9]/g, "").length, []);
25112
+ const runValidation = useCallback27((phone) => {
25268
25113
  if (!phone || digitCount(phone) === 0) {
25269
25114
  setIsInvalid(false);
25270
25115
  onValidationChange?.(false);
@@ -25274,11 +25119,11 @@ function PhoneInput({
25274
25119
  setIsInvalid(invalid);
25275
25120
  onValidationChange?.(invalid);
25276
25121
  }, [countryCode, digitCount, onValidationChange]);
25277
- const debouncedValidation = useCallback26((phone) => {
25122
+ const debouncedValidation = useCallback27((phone) => {
25278
25123
  if (debounceRef.current) clearTimeout(debounceRef.current);
25279
25124
  debounceRef.current = setTimeout(() => runValidation(phone), 300);
25280
25125
  }, [runValidation]);
25281
- useEffect37(() => {
25126
+ useEffect36(() => {
25282
25127
  return () => {
25283
25128
  if (debounceRef.current) clearTimeout(debounceRef.current);
25284
25129
  };
@@ -25840,8 +25685,8 @@ function FilterList({
25840
25685
 
25841
25686
  // src/components/ui/tag-search-input.tsx
25842
25687
  import {
25843
- useEffect as useEffect39,
25844
- useRef as useRef33,
25688
+ useEffect as useEffect38,
25689
+ useRef as useRef34,
25845
25690
  useState as useState51
25846
25691
  } from "react";
25847
25692
  init_cn();
@@ -25876,11 +25721,11 @@ function TagSearchInput({
25876
25721
  limitTags,
25877
25722
  placeholder: currentPlaceholder
25878
25723
  });
25879
- const wrapperRef = useRef33(null);
25880
- const hiddenTagsRef = useRef33(null);
25881
- const hiddenTagsPopupRef = useRef33(null);
25724
+ const wrapperRef = useRef34(null);
25725
+ const hiddenTagsRef = useRef34(null);
25726
+ const hiddenTagsPopupRef = useRef34(null);
25882
25727
  const [showHiddenTags, setShowHiddenTags] = useState51(false);
25883
- useEffect39(() => {
25728
+ useEffect38(() => {
25884
25729
  if (!showHiddenTags) return;
25885
25730
  const handleClick = (e) => {
25886
25731
  const target = e.target;
@@ -26036,7 +25881,7 @@ function TagSearchInput({
26036
25881
 
26037
25882
  // src/components/ui/markdown-editor.tsx
26038
25883
  init_cn();
26039
- import { useRef as useRef34, useCallback as useCallback27, useState as useState52, useEffect as useEffect40 } from "react";
25884
+ import { useRef as useRef35, useCallback as useCallback28, useState as useState52, useEffect as useEffect39 } from "react";
26040
25885
  import dynamic from "next/dynamic";
26041
25886
  import { Loader2 as Loader23, Upload as Upload2 } from "lucide-react";
26042
25887
  import { jsx as jsx234, jsxs as jsxs192 } from "react/jsx-runtime";
@@ -26067,7 +25912,7 @@ body .w-md-editor .w-md-editor-bar::after { content: '' !important; display: blo
26067
25912
  body .w-md-editor .w-md-editor-bar:hover::after { border-color: var(--color-text-secondary) !important; }
26068
25913
  `;
26069
25914
  function MarkdownEditorStyles() {
26070
- useEffect40(() => {
25915
+ useEffect39(() => {
26071
25916
  if (document.getElementById(MARKDOWN_EDITOR_STYLE_ID)) return;
26072
25917
  const style = document.createElement("style");
26073
25918
  style.id = MARKDOWN_EDITOR_STYLE_ID;
@@ -26091,11 +25936,11 @@ function MarkdownEditor({
26091
25936
  onFileUploaded,
26092
25937
  renderPreview
26093
25938
  }) {
26094
- const fileInputRef = useRef34(null);
25939
+ const fileInputRef = useRef35(null);
26095
25940
  const [isUploading, setIsUploading] = useState52(false);
26096
25941
  const [uploadProgress, setUploadProgress] = useState52("");
26097
25942
  const [defaultExtraCommands, setDefaultExtraCommands] = useState52([]);
26098
- useEffect40(() => {
25943
+ useEffect39(() => {
26099
25944
  import("@uiw/react-md-editor").then((mod) => {
26100
25945
  if (mod.commands?.getExtraCommands) {
26101
25946
  setDefaultExtraCommands(mod.commands.getExtraCommands());
@@ -26105,7 +25950,7 @@ function MarkdownEditor({
26105
25950
  const handleChange = (val) => {
26106
25951
  onChange(val || "");
26107
25952
  };
26108
- const insertTextAtCursor = useCallback27(
25953
+ const insertTextAtCursor = useCallback28(
26109
25954
  (text) => {
26110
25955
  const textarea = document.querySelector(
26111
25956
  ".w-md-editor-text-textarea"
@@ -26121,7 +25966,7 @@ function MarkdownEditor({
26121
25966
  },
26122
25967
  [value, onChange]
26123
25968
  );
26124
- const handleFileUpload = useCallback27(
25969
+ const handleFileUpload = useCallback28(
26125
25970
  async (file) => {
26126
25971
  if (!onUploadFile) return;
26127
25972
  setIsUploading(true);
@@ -26142,7 +25987,7 @@ function MarkdownEditor({
26142
25987
  },
26143
25988
  [onUploadFile, insertTextAtCursor, onFileUploaded]
26144
25989
  );
26145
- const handleFileInputChange = useCallback27(
25990
+ const handleFileInputChange = useCallback28(
26146
25991
  (e) => {
26147
25992
  const file = e.target.files?.[0];
26148
25993
  if (file) {
@@ -26152,7 +25997,7 @@ function MarkdownEditor({
26152
25997
  },
26153
25998
  [handleFileUpload]
26154
25999
  );
26155
- const handlePaste = useCallback27(
26000
+ const handlePaste = useCallback28(
26156
26001
  (e) => {
26157
26002
  if (!onUploadFile) return;
26158
26003
  const items = e.clipboardData?.items;
@@ -26184,14 +26029,14 @@ function MarkdownEditor({
26184
26029
  }
26185
26030
  } : null;
26186
26031
  const extraCommands = uploadCommand ? [...defaultExtraCommands, uploadCommand] : defaultExtraCommands;
26187
- const wrapperRef = useRef34(null);
26188
- const isDraggingRef = useRef34(false);
26189
- const mouseYRef = useRef34(0);
26190
- const rafRef = useRef34(0);
26191
- const scrollParentRef = useRef34(window);
26032
+ const wrapperRef = useRef35(null);
26033
+ const isDraggingRef = useRef35(false);
26034
+ const mouseYRef = useRef35(0);
26035
+ const rafRef = useRef35(0);
26036
+ const scrollParentRef = useRef35(window);
26192
26037
  const EDGE_ZONE = 60;
26193
26038
  const MAX_SCROLL_SPEED = 15;
26194
- const findScrollParent = useCallback27((el) => {
26039
+ const findScrollParent = useCallback28((el) => {
26195
26040
  let node = el?.parentElement;
26196
26041
  while (node && node !== document.documentElement) {
26197
26042
  const { overflowY } = window.getComputedStyle(node);
@@ -26202,7 +26047,7 @@ function MarkdownEditor({
26202
26047
  }
26203
26048
  return window;
26204
26049
  }, []);
26205
- const scrollLoop = useCallback27(() => {
26050
+ const scrollLoop = useCallback28(() => {
26206
26051
  if (!isDraggingRef.current) return;
26207
26052
  const parent = scrollParentRef.current;
26208
26053
  const isWindow = parent === window;
@@ -26218,7 +26063,7 @@ function MarkdownEditor({
26218
26063
  }
26219
26064
  rafRef.current = requestAnimationFrame(scrollLoop);
26220
26065
  }, []);
26221
- useEffect40(() => {
26066
+ useEffect39(() => {
26222
26067
  const wrapper = wrapperRef.current;
26223
26068
  if (!wrapper) return;
26224
26069
  const onMouseMove = (e) => {
@@ -27500,12 +27345,12 @@ function ArrayEntryManager({
27500
27345
  }) {
27501
27346
  const [draftItems, setDraftItems] = useState58(items);
27502
27347
  const [isDirty, setIsDirty] = useState58(false);
27503
- useEffect43(() => {
27348
+ useEffect42(() => {
27504
27349
  if (!isDirty && !isSaving) {
27505
27350
  setDraftItems(items);
27506
27351
  }
27507
27352
  }, [items, isDirty, isSaving]);
27508
- useEffect43(() => {
27353
+ useEffect42(() => {
27509
27354
  if (onDirtyChange) {
27510
27355
  onDirtyChange(isDirty);
27511
27356
  }
@@ -27720,7 +27565,7 @@ function AuthProvidersList({
27720
27565
 
27721
27566
  // src/components/features/changelog-manager.tsx
27722
27567
  import { Trash2 as Trash23, Plus as Plus3, ChevronDown as ChevronDown7, ChevronUp as ChevronUp3, Eye, EyeOff } from "lucide-react";
27723
- import { useState as useState60, useEffect as useEffect44 } from "react";
27568
+ import { useState as useState60, useEffect as useEffect43 } from "react";
27724
27569
  import { jsx as jsx247, jsxs as jsxs204 } from "react/jsx-runtime";
27725
27570
  function ChangelogManager({
27726
27571
  title,
@@ -27731,7 +27576,7 @@ function ChangelogManager({
27731
27576
  showVisibilityToggle = false
27732
27577
  }) {
27733
27578
  const [expandedIndices, setExpandedIndices] = useState60(/* @__PURE__ */ new Set());
27734
- useEffect44(() => {
27579
+ useEffect43(() => {
27735
27580
  if (expandAll && entries.length > 0) {
27736
27581
  setExpandedIndices(new Set(entries.map((_, i) => i)));
27737
27582
  }
@@ -28043,7 +27888,7 @@ var ErrorBoundary = class extends Component {
28043
27888
 
28044
27889
  // src/components/features/figma-prototype-viewer.tsx
28045
27890
  init_cn();
28046
- import { useState as useState61, useRef as useRef37, useEffect as useEffect45, useCallback as useCallback29, useMemo as useMemo22 } from "react";
27891
+ import { useState as useState61, useRef as useRef38, useEffect as useEffect44, useCallback as useCallback30, useMemo as useMemo22 } from "react";
28047
27892
 
28048
27893
  // src/components/features/section-selector.tsx
28049
27894
  init_cn();
@@ -28412,10 +28257,10 @@ var FigmaPrototypeViewer = ({
28412
28257
  }) => {
28413
28258
  const clientId = process.env.NEXT_PUBLIC_FIGMA_CLIENT_ID || "UTQPwZHR9OZp68TTGPFFi5";
28414
28259
  const showDebugPanel = process.env.NEXT_PUBLIC_FIGMA_DEBUG === "true";
28415
- const iframeRef = useRef37(null);
28416
- const containerRef = useRef37(null);
28417
- const navTimerRef = useRef37(null);
28418
- const touchTimerRef = useRef37(null);
28260
+ const iframeRef = useRef38(null);
28261
+ const containerRef = useRef38(null);
28262
+ const navTimerRef = useRef38(null);
28263
+ const touchTimerRef = useRef38(null);
28419
28264
  const [screenWidth, setScreenWidth] = useState61(
28420
28265
  typeof window !== "undefined" ? window.innerWidth : DESKTOP_BREAKPOINT
28421
28266
  );
@@ -28481,7 +28326,7 @@ var FigmaPrototypeViewer = ({
28481
28326
  embedUrl,
28482
28327
  iframeKey
28483
28328
  ]);
28484
- useEffect45(() => {
28329
+ useEffect44(() => {
28485
28330
  const handleResize = () => {
28486
28331
  const newWidth = window.innerWidth;
28487
28332
  setScreenWidth(newWidth);
@@ -28495,7 +28340,7 @@ var FigmaPrototypeViewer = ({
28495
28340
  return () => window.removeEventListener("resize", handleResize);
28496
28341
  }, []);
28497
28342
  const [lastViewMode, setLastViewMode] = useState61(viewMode);
28498
- useEffect45(() => {
28343
+ useEffect44(() => {
28499
28344
  if (lastViewMode !== viewMode && iframeState === "READY") {
28500
28345
  console.log("[ViewMode Change]", lastViewMode, "\u2192", viewMode);
28501
28346
  setIframeState("RELOADING");
@@ -28503,7 +28348,7 @@ var FigmaPrototypeViewer = ({
28503
28348
  }
28504
28349
  setLastViewMode(viewMode);
28505
28350
  }, [viewMode, lastViewMode, iframeState]);
28506
- useEffect45(() => {
28351
+ useEffect44(() => {
28507
28352
  const handleVisibilityChange = () => {
28508
28353
  if (document.visibilityState === "visible" && iframeState === "READY") {
28509
28354
  console.log("[Sleep Recovery] Reloading iframe after sleep");
@@ -28514,7 +28359,7 @@ var FigmaPrototypeViewer = ({
28514
28359
  document.addEventListener("visibilitychange", handleVisibilityChange);
28515
28360
  return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
28516
28361
  }, [iframeState]);
28517
- useEffect45(() => {
28362
+ useEffect44(() => {
28518
28363
  const handleMessage = (event) => {
28519
28364
  if (event.origin !== "https://www.figma.com") return;
28520
28365
  const validEvents = ["INITIAL_LOAD", "NEW_STATE", "PRESENTED_NODE_CHANGED"];
@@ -28551,7 +28396,7 @@ var FigmaPrototypeViewer = ({
28551
28396
  window.addEventListener("message", handleMessage);
28552
28397
  return () => window.removeEventListener("message", handleMessage);
28553
28398
  }, [config.sections, activeSection, isNavigating, externalActiveSection, config.onSectionChange, viewMode]);
28554
- const navigateToSection = useCallback29((sectionId) => {
28399
+ const navigateToSection = useCallback30((sectionId) => {
28555
28400
  const section = config.sections.find((s) => s.id === sectionId);
28556
28401
  if (!section || !iframeRef.current?.contentWindow || !isInitialized) {
28557
28402
  return;
@@ -28575,7 +28420,7 @@ var FigmaPrototypeViewer = ({
28575
28420
  if (navTimerRef.current) clearTimeout(navTimerRef.current);
28576
28421
  navTimerRef.current = setTimeout(() => setIsNavigating(false), 500);
28577
28422
  }, [config, isInitialized, viewMode, externalActiveSection]);
28578
- const handleSectionClick = useCallback29((sectionId) => {
28423
+ const handleSectionClick = useCallback30((sectionId) => {
28579
28424
  const sectionsDisabled = iframeState !== "READY" || isNavigating;
28580
28425
  if (sectionId === activeSection || sectionsDisabled) {
28581
28426
  return;
@@ -28586,7 +28431,7 @@ var FigmaPrototypeViewer = ({
28586
28431
  navigateToSection(sectionId);
28587
28432
  }
28588
28433
  }, [activeSection, iframeState, isNavigating, externalOnSectionClick, navigateToSection]);
28589
- const handleTouchStart = useCallback29((e) => {
28434
+ const handleTouchStart = useCallback30((e) => {
28590
28435
  const overlayElement = e.currentTarget;
28591
28436
  console.log("[Touch] Touch detected, allowing iframe interaction");
28592
28437
  overlayElement.style.pointerEvents = "none";
@@ -28598,12 +28443,12 @@ var FigmaPrototypeViewer = ({
28598
28443
  }
28599
28444
  }, 500);
28600
28445
  }, []);
28601
- useEffect45(() => {
28446
+ useEffect44(() => {
28602
28447
  if (externalActiveSection && externalActiveSection !== activeSection && isInitialized) {
28603
28448
  navigateToSection(externalActiveSection);
28604
28449
  }
28605
28450
  }, [externalActiveSection, activeSection, isInitialized, navigateToSection]);
28606
- useEffect45(() => {
28451
+ useEffect44(() => {
28607
28452
  return () => {
28608
28453
  if (navTimerRef.current) clearTimeout(navTimerRef.current);
28609
28454
  if (touchTimerRef.current) clearTimeout(touchTimerRef.current);
@@ -28706,7 +28551,7 @@ var FigmaPrototypeViewer = ({
28706
28551
 
28707
28552
  // src/components/features/filters-dropdown.tsx
28708
28553
  init_cn();
28709
- import { useEffect as useEffect46, useRef as useRef38, useState as useState62 } from "react";
28554
+ import { useEffect as useEffect45, useRef as useRef39, useState as useState62 } from "react";
28710
28555
  import { jsx as jsx253, jsxs as jsxs209 } from "react/jsx-runtime";
28711
28556
  var FilterCheckbox = ({ checked, disabled = false, className }) => {
28712
28557
  return /* @__PURE__ */ jsx253(
@@ -28743,10 +28588,10 @@ var FiltersDropdown = ({
28743
28588
  const [isVisible, setIsVisible] = useState62(false);
28744
28589
  const [isMobile, setIsMobile] = useState62(false);
28745
28590
  const [actualPlacement, setActualPlacement] = useState62(placement);
28746
- const dropdownRef = useRef38(null);
28747
- const triggerRef = useRef38(null);
28748
- const containerRef = useRef38(null);
28749
- useEffect46(() => {
28591
+ const dropdownRef = useRef39(null);
28592
+ const triggerRef = useRef39(null);
28593
+ const containerRef = useRef39(null);
28594
+ useEffect45(() => {
28750
28595
  if (isOpen) {
28751
28596
  setShouldRender(true);
28752
28597
  let id2 = 0;
@@ -28762,7 +28607,7 @@ var FiltersDropdown = ({
28762
28607
  const t = setTimeout(() => setShouldRender(false), ANIMATION_MS);
28763
28608
  return () => clearTimeout(t);
28764
28609
  }, [isOpen]);
28765
- useEffect46(() => {
28610
+ useEffect45(() => {
28766
28611
  if (!responsive) {
28767
28612
  setIsMobile(false);
28768
28613
  return;
@@ -28774,7 +28619,7 @@ var FiltersDropdown = ({
28774
28619
  window.addEventListener("resize", checkMobile);
28775
28620
  return () => window.removeEventListener("resize", checkMobile);
28776
28621
  }, [responsive]);
28777
- useEffect46(() => {
28622
+ useEffect45(() => {
28778
28623
  if (!isOpen || isMobile || !triggerRef.current) return;
28779
28624
  const calculateOptimalPlacement = () => {
28780
28625
  const trigger = triggerRef.current;
@@ -28811,12 +28656,12 @@ var FiltersDropdown = ({
28811
28656
  return initial;
28812
28657
  });
28813
28658
  const currentFiltersStr = currentFilters ? JSON.stringify(currentFilters) : "";
28814
- useEffect46(() => {
28659
+ useEffect45(() => {
28815
28660
  if (currentFilters) {
28816
28661
  setSelectedFilters({ ...currentFilters });
28817
28662
  }
28818
28663
  }, [currentFiltersStr]);
28819
- useEffect46(() => {
28664
+ useEffect45(() => {
28820
28665
  const handleClickOutside = (event) => {
28821
28666
  if (containerRef.current && !containerRef.current.contains(event.target)) {
28822
28667
  setIsOpen(false);
@@ -28833,7 +28678,7 @@ var FiltersDropdown = ({
28833
28678
  };
28834
28679
  }
28835
28680
  }, [isOpen, placement]);
28836
- useEffect46(() => {
28681
+ useEffect45(() => {
28837
28682
  const handleEscape = (e) => {
28838
28683
  if (e.key === "Escape" && isOpen) {
28839
28684
  setIsOpen(false);
@@ -29099,13 +28944,13 @@ function KnowledgeBaseLinksManager({
29099
28944
  }
29100
28945
 
29101
28946
  // src/components/features/loading-provider.tsx
29102
- import { createContext as createContext7, useContext as useContext7, useState as useState63, useEffect as useEffect47 } from "react";
28947
+ import { createContext as createContext7, useContext as useContext7, useState as useState63, useEffect as useEffect46 } from "react";
29103
28948
  import { jsx as jsx256, jsxs as jsxs210 } from "react/jsx-runtime";
29104
28949
  var LoadingContext = createContext7(void 0);
29105
28950
  function LoadingProvider({ children }) {
29106
28951
  const [isLoading, setIsLoading] = useState63(false);
29107
28952
  const [progress, setProgress] = useState63(0);
29108
- useEffect47(() => {
28953
+ useEffect46(() => {
29109
28954
  let interval;
29110
28955
  if (isLoading) {
29111
28956
  setProgress(10);
@@ -29150,7 +28995,7 @@ function useLoading() {
29150
28995
  }
29151
28996
 
29152
28997
  // src/components/features/media-gallery-manager.tsx
29153
- import { useState as useState64, useRef as useRef39, useCallback as useCallback30 } from "react";
28998
+ import { useState as useState64, useRef as useRef40, useCallback as useCallback31 } from "react";
29154
28999
  import {
29155
29000
  Upload as Upload3,
29156
29001
  Image as ImageIcon2,
@@ -29171,10 +29016,10 @@ function MediaGalleryManager({
29171
29016
  modalTitle = "Media Gallery",
29172
29017
  className = ""
29173
29018
  }) {
29174
- const fileInputRef = useRef39(null);
29019
+ const fileInputRef = useRef40(null);
29175
29020
  const [deletingIndex, setDeletingIndex] = useState64(null);
29176
29021
  const [draggedIndex, setDraggedIndex] = useState64(null);
29177
- const handleFileSelect = useCallback30(async (event) => {
29022
+ const handleFileSelect = useCallback31(async (event) => {
29178
29023
  const file = event.target.files?.[0];
29179
29024
  if (!file) return;
29180
29025
  let mediaType;
@@ -29200,18 +29045,18 @@ function MediaGalleryManager({
29200
29045
  console.error("Upload failed:", error);
29201
29046
  }
29202
29047
  }, [media, onChange, onUpload]);
29203
- const handleDeleteMedia = useCallback30((index) => {
29048
+ const handleDeleteMedia = useCallback31((index) => {
29204
29049
  setDeletingIndex(index);
29205
29050
  onChange(media.filter((_, i) => i !== index));
29206
29051
  setDeletingIndex(null);
29207
29052
  }, [media, onChange]);
29208
- const handleDragStart = useCallback30((index) => {
29053
+ const handleDragStart = useCallback31((index) => {
29209
29054
  setDraggedIndex(index);
29210
29055
  }, []);
29211
- const handleDragOver = useCallback30((e) => {
29056
+ const handleDragOver = useCallback31((e) => {
29212
29057
  e.preventDefault();
29213
29058
  }, []);
29214
- const handleDrop = useCallback30((e, targetIndex) => {
29059
+ const handleDrop = useCallback31((e, targetIndex) => {
29215
29060
  e.preventDefault();
29216
29061
  if (draggedIndex === null || draggedIndex === targetIndex) {
29217
29062
  setDraggedIndex(null);
@@ -29223,7 +29068,7 @@ function MediaGalleryManager({
29223
29068
  onChange(newMedia.map((item, i) => ({ ...item, display_order: i })));
29224
29069
  setDraggedIndex(null);
29225
29070
  }, [media, draggedIndex, onChange]);
29226
- const renderMediaItem = useCallback30((mediaItem, index) => {
29071
+ const renderMediaItem = useCallback31((mediaItem, index) => {
29227
29072
  const isDeleting = deletingIndex === index;
29228
29073
  return /* @__PURE__ */ jsxs211(
29229
29074
  Card,
@@ -29383,7 +29228,7 @@ function OSTypeBadgeGroup({
29383
29228
  }
29384
29229
 
29385
29230
  // src/components/features/parallax-image-showcase.tsx
29386
- import { useEffect as useEffect48, useState as useState65, useRef as useRef40 } from "react";
29231
+ import { useEffect as useEffect47, useState as useState65, useRef as useRef41 } from "react";
29387
29232
  import Image12 from "next/image";
29388
29233
  import { motion as motion2, useScroll, useTransform, useMotionValue, useSpring } from "framer-motion";
29389
29234
  import { jsx as jsx260, jsxs as jsxs213 } from "react/jsx-runtime";
@@ -29403,8 +29248,8 @@ var ParallaxImageShowcase = ({
29403
29248
  const mouseXSpring = useSpring(mouseX, springConfig);
29404
29249
  const mouseYSpring = useSpring(mouseY, springConfig);
29405
29250
  const [componentRect, setComponentRect] = useState65(null);
29406
- const componentRef = useRef40(null);
29407
- useEffect48(() => {
29251
+ const componentRef = useRef41(null);
29252
+ useEffect47(() => {
29408
29253
  const updateRect = () => {
29409
29254
  if (componentRef.current) {
29410
29255
  setComponentRect(componentRef.current.getBoundingClientRect());
@@ -29418,7 +29263,7 @@ var ParallaxImageShowcase = ({
29418
29263
  window.removeEventListener("scroll", updateRect);
29419
29264
  };
29420
29265
  }, []);
29421
- useEffect48(() => {
29266
+ useEffect47(() => {
29422
29267
  const handleGlobalMouseMove = (e) => {
29423
29268
  if (!componentRect) return;
29424
29269
  const centerX = componentRect.left + componentRect.width / 2;
@@ -30062,7 +29907,7 @@ function PushButtonSelector({
30062
29907
  }
30063
29908
 
30064
29909
  // src/components/features/release-media-manager.tsx
30065
- import { useState as useState66, useRef as useRef41 } from "react";
29910
+ import { useState as useState66, useRef as useRef42 } from "react";
30066
29911
  import { Trash2 as Trash25, Plus as Plus5, Image as ImageIcon3, Video as Video4, Upload as Upload4, Loader2 as Loader28, GripVertical as GripVertical2 } from "lucide-react";
30067
29912
  import Image13 from "next/image";
30068
29913
  import { jsx as jsx265, jsxs as jsxs218 } from "react/jsx-runtime";
@@ -30072,7 +29917,7 @@ function ReleaseMediaManager({
30072
29917
  onUpload,
30073
29918
  className = ""
30074
29919
  }) {
30075
- const fileInputRef = useRef41(null);
29920
+ const fileInputRef = useRef42(null);
30076
29921
  const [uploadingIndex, setUploadingIndex] = useState66(null);
30077
29922
  const handleFileSelect = async (event) => {
30078
29923
  const file = event.target.files?.[0];
@@ -30986,7 +30831,7 @@ function TagsSelector({
30986
30831
 
30987
30832
  // src/components/features/video-source-selector.tsx
30988
30833
  init_button2();
30989
- import { useState as useState69, useCallback as useCallback31 } from "react";
30834
+ import { useState as useState69, useCallback as useCallback32 } from "react";
30990
30835
  import { Upload as Upload6, Sparkles as Sparkles3, X as X13, Video as Video5 } from "lucide-react";
30991
30836
  import { jsx as jsx272, jsxs as jsxs224 } from "react/jsx-runtime";
30992
30837
  function VideoSourceSelector({
@@ -31015,7 +30860,7 @@ function VideoSourceSelector({
31015
30860
  const [uploadProgress, setUploadProgress] = useState69(0);
31016
30861
  const [uploadMessage, setUploadMessage] = useState69("");
31017
30862
  const [uploadError, setUploadError] = useState69(null);
31018
- const handleUploadClick = useCallback31(() => {
30863
+ const handleUploadClick = useCallback32(() => {
31019
30864
  const input = document.createElement("input");
31020
30865
  input.type = "file";
31021
30866
  input.accept = "video/*";
@@ -31046,7 +30891,7 @@ function VideoSourceSelector({
31046
30891
  };
31047
30892
  input.click();
31048
30893
  }, [onUploadVideo, onUploadedVideoUrlChange]);
31049
- const handleDeleteVideo = useCallback31(() => {
30894
+ const handleDeleteVideo = useCallback32(() => {
31050
30895
  onUploadedVideoUrlChange("");
31051
30896
  }, [onUploadedVideoUrlChange]);
31052
30897
  return /* @__PURE__ */ jsxs224("div", { className: `space-y-4 p-6 bg-ods-card border border-ods-border rounded-lg ${className}`, children: [
@@ -32508,7 +32353,7 @@ function ViewToggle({
32508
32353
 
32509
32354
  // src/components/features/policy-configuration-panel.tsx
32510
32355
  init_cn();
32511
- import { useRef as useRef42, useEffect as useEffect49, useState as useState71 } from "react";
32356
+ import { useRef as useRef43, useEffect as useEffect48, useState as useState71 } from "react";
32512
32357
  import { ChevronDown as ChevronDown8 } from "lucide-react";
32513
32358
  init_button2();
32514
32359
 
@@ -32690,8 +32535,8 @@ var PolicyRow = ({ policy, categoryId, editMode, onPermissionChange }) => {
32690
32535
  };
32691
32536
  var useAnimatedHeight = (isExpanded) => {
32692
32537
  const [height, setHeight] = useState71(0);
32693
- const contentRef = useRef42(null);
32694
- useEffect49(() => {
32538
+ const contentRef = useRef43(null);
32539
+ useEffect48(() => {
32695
32540
  if (contentRef.current) {
32696
32541
  const contentHeight = contentRef.current.scrollHeight;
32697
32542
  setHeight(isExpanded ? contentHeight : 0);
@@ -32847,7 +32692,7 @@ PolicyConfigurationPanel.displayName = "PolicyConfigurationPanel";
32847
32692
  init_button2();
32848
32693
  init_cn();
32849
32694
  import { getCountries as getCountries2 } from "libphonenumber-js";
32850
- import { useEffect as useEffect50, useState as useState72 } from "react";
32695
+ import { useEffect as useEffect49, useState as useState72 } from "react";
32851
32696
  import { Fragment as Fragment41, jsx as jsx292, jsxs as jsxs240 } from "react/jsx-runtime";
32852
32697
  function WaitlistForm({
32853
32698
  id = "waitlist-form",
@@ -32876,12 +32721,12 @@ function WaitlistForm({
32876
32721
  const [isPhoneInvalid, setIsPhoneInvalid] = useState72(false);
32877
32722
  const [showConsentError, setShowConsentError] = useState72(false);
32878
32723
  const isMailDomainGeneric = hasGenericEmailDomain(email);
32879
- useEffect50(() => {
32724
+ useEffect49(() => {
32880
32725
  if (defaultEmail) {
32881
32726
  setEmail(defaultEmail);
32882
32727
  }
32883
32728
  }, [defaultEmail]);
32884
- useEffect50(() => {
32729
+ useEffect49(() => {
32885
32730
  setIsClient(true);
32886
32731
  if (!geoApiUrl) return;
32887
32732
  const supportedCountries = new Set(getCountries2());
@@ -33454,7 +33299,7 @@ function EmptyState3() {
33454
33299
  }
33455
33300
 
33456
33301
  // src/components/features/board/use-board-collapse.ts
33457
- import { useCallback as useCallback33, useState as useState73 } from "react";
33302
+ import { useCallback as useCallback34, useState as useState73 } from "react";
33458
33303
  function useBoardCollapse(storageKey) {
33459
33304
  const [persisted, setPersisted] = useLocalStorage(
33460
33305
  storageKey ?? "__board_collapse_unused__",
@@ -33463,13 +33308,13 @@ function useBoardCollapse(storageKey) {
33463
33308
  const [memory, setMemory] = useState73({});
33464
33309
  const collapsed = storageKey ? persisted : memory;
33465
33310
  const setMap = storageKey ? setPersisted : setMemory;
33466
- const toggle = useCallback33(
33311
+ const toggle = useCallback34(
33467
33312
  (columnId) => {
33468
33313
  setMap((prev) => ({ ...prev, [columnId]: !prev[columnId] }));
33469
33314
  },
33470
33315
  [setMap]
33471
33316
  );
33472
- const setCollapsed = useCallback33(
33317
+ const setCollapsed = useCallback34(
33473
33318
  (columnId, value) => {
33474
33319
  setMap((prev) => ({ ...prev, [columnId]: value }));
33475
33320
  },
@@ -33947,7 +33792,6 @@ export {
33947
33792
  ViewToggle,
33948
33793
  YouTubeEmbed,
33949
33794
  extractYouTubeId,
33950
- YouTubeLinkParser,
33951
33795
  PolicyConfigurationPanel,
33952
33796
  PhoneInput,
33953
33797
  WaitlistForm,
@@ -34342,4 +34186,4 @@ export {
34342
34186
  TMCG_SOCIAL_PLATFORMS,
34343
34187
  assets
34344
34188
  };
34345
- //# sourceMappingURL=chunk-VY6SYM2L.js.map
34189
+ //# sourceMappingURL=chunk-AAX27BCR.js.map