@flamingo-stack/openframe-frontend-core 0.0.589 → 0.0.590-2020.5606.1

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 (101) hide show
  1. package/dist/{chunk-EGUU3QCU.cjs → chunk-2564HPMD.cjs} +3 -3
  2. package/dist/{chunk-EGUU3QCU.cjs.map → chunk-2564HPMD.cjs.map} +1 -1
  3. package/dist/{chunk-JDINUWND.cjs → chunk-2MY6BT6P.cjs} +69 -69
  4. package/dist/{chunk-JDINUWND.cjs.map → chunk-2MY6BT6P.cjs.map} +1 -1
  5. package/dist/{chunk-G45RGWHF.cjs → chunk-353GRCTE.cjs} +37 -10
  6. package/dist/chunk-353GRCTE.cjs.map +1 -0
  7. package/dist/{chunk-5CHW7AMP.cjs → chunk-3BQESV5G.cjs} +10 -10
  8. package/dist/{chunk-5CHW7AMP.cjs.map → chunk-3BQESV5G.cjs.map} +1 -1
  9. package/dist/{chunk-KK3XU6YJ.cjs → chunk-3WZQ5RXS.cjs} +4 -4
  10. package/dist/{chunk-KK3XU6YJ.cjs.map → chunk-3WZQ5RXS.cjs.map} +1 -1
  11. package/dist/{chunk-A6X7EXP6.cjs → chunk-5KFIUNKN.cjs} +10 -10
  12. package/dist/{chunk-A6X7EXP6.cjs.map → chunk-5KFIUNKN.cjs.map} +1 -1
  13. package/dist/{chunk-CJOWLRUU.js → chunk-6BPIDRBI.js} +2 -2
  14. package/dist/{chunk-FVRRYJ6P.cjs → chunk-7H4RUNIL.cjs} +22 -22
  15. package/dist/{chunk-FVRRYJ6P.cjs.map → chunk-7H4RUNIL.cjs.map} +1 -1
  16. package/dist/{chunk-CN36E4PK.js → chunk-7JPKCUF7.js} +2 -2
  17. package/dist/{chunk-IYDHV2CS.cjs → chunk-7O7CAZYG.cjs} +43 -43
  18. package/dist/{chunk-IYDHV2CS.cjs.map → chunk-7O7CAZYG.cjs.map} +1 -1
  19. package/dist/{chunk-LGBNHWDN.js → chunk-ACUXSU6J.js} +3 -3
  20. package/dist/{chunk-KVNGYFFP.js → chunk-AV4UXMOH.js} +3 -3
  21. package/dist/{chunk-4ZKAMPBX.js → chunk-BKOCXNAP.js} +2 -2
  22. package/dist/{chunk-MENQLD57.cjs → chunk-CQHFRJSG.cjs} +5 -5
  23. package/dist/{chunk-MENQLD57.cjs.map → chunk-CQHFRJSG.cjs.map} +1 -1
  24. package/dist/{chunk-3OCYNMZ5.js → chunk-CT6I3HOP.js} +3 -3
  25. package/dist/{chunk-C6RJRSIM.cjs → chunk-DAUDWRE4.cjs} +3 -3
  26. package/dist/{chunk-C6RJRSIM.cjs.map → chunk-DAUDWRE4.cjs.map} +1 -1
  27. package/dist/{chunk-NXZC6UTN.js → chunk-DFUO7J3W.js} +2 -2
  28. package/dist/{chunk-TOYHZHTK.js → chunk-E5NSDLYJ.js} +2 -2
  29. package/dist/{chunk-77Y7R243.js → chunk-GAXC43J4.js} +5 -5
  30. package/dist/{chunk-EGYX55HT.cjs → chunk-I3HBFKKM.cjs} +159 -159
  31. package/dist/{chunk-EGYX55HT.cjs.map → chunk-I3HBFKKM.cjs.map} +1 -1
  32. package/dist/{chunk-ADANP3ZA.cjs → chunk-JIIA5BIJ.cjs} +33 -33
  33. package/dist/{chunk-ADANP3ZA.cjs.map → chunk-JIIA5BIJ.cjs.map} +1 -1
  34. package/dist/{chunk-PAUJQV3C.cjs → chunk-KIMRNY7A.cjs} +15 -15
  35. package/dist/{chunk-PAUJQV3C.cjs.map → chunk-KIMRNY7A.cjs.map} +1 -1
  36. package/dist/{chunk-FQBR6SCA.js → chunk-KLNHD4TC.js} +3 -3
  37. package/dist/{chunk-CNKVEVUN.js → chunk-LDNRL62P.js} +5 -5
  38. package/dist/{chunk-I5CJJFEJ.js → chunk-LKMRJ2CP.js} +3 -3
  39. package/dist/{chunk-KWTV3KGY.cjs → chunk-QEV5HPDQ.cjs} +9 -9
  40. package/dist/{chunk-KWTV3KGY.cjs.map → chunk-QEV5HPDQ.cjs.map} +1 -1
  41. package/dist/{chunk-WUCYI3BC.cjs → chunk-RLABO5PY.cjs} +24 -24
  42. package/dist/{chunk-WUCYI3BC.cjs.map → chunk-RLABO5PY.cjs.map} +1 -1
  43. package/dist/{chunk-5FNWOF46.js → chunk-RLC5IISG.js} +6 -6
  44. package/dist/{chunk-GKPY7VLK.js → chunk-RM3PTDSI.js} +4 -4
  45. package/dist/{chunk-NIDPX52C.js → chunk-T3WAHAMH.js} +5 -5
  46. package/dist/{chunk-D7YISHXC.js → chunk-V7RB3EUW.js} +37 -10
  47. package/dist/{chunk-D7YISHXC.js.map → chunk-V7RB3EUW.js.map} +1 -1
  48. package/dist/{chunk-BONXSRHZ.cjs → chunk-WIAEFA2K.cjs} +21 -21
  49. package/dist/{chunk-BONXSRHZ.cjs.map → chunk-WIAEFA2K.cjs.map} +1 -1
  50. package/dist/components/case-studies/index.cjs +9 -9
  51. package/dist/components/case-studies/index.js +3 -3
  52. package/dist/components/chat/index.cjs +2 -2
  53. package/dist/components/chat/index.js +1 -1
  54. package/dist/components/chat/stream/message-mutations.d.ts.map +1 -1
  55. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  56. package/dist/components/contact/index.cjs +4 -4
  57. package/dist/components/contact/index.js +3 -3
  58. package/dist/components/docs/index.cjs +7 -7
  59. package/dist/components/docs/index.js +6 -6
  60. package/dist/components/embeds/index.cjs +4 -4
  61. package/dist/components/embeds/index.js +3 -3
  62. package/dist/components/faq/index.cjs +4 -4
  63. package/dist/components/faq/index.js +3 -3
  64. package/dist/components/features/index.cjs +3 -3
  65. package/dist/components/features/index.js +2 -2
  66. package/dist/components/help-center-pages/index.cjs +23 -23
  67. package/dist/components/help-center-pages/index.js +14 -14
  68. package/dist/components/index.cjs +36 -36
  69. package/dist/components/index.js +13 -13
  70. package/dist/components/meeting-scheduler/index.cjs +21 -21
  71. package/dist/components/meeting-scheduler/index.js +2 -2
  72. package/dist/components/navigation/index.cjs +6 -6
  73. package/dist/components/navigation/index.js +5 -5
  74. package/dist/components/onboarding-guides/index.cjs +6 -6
  75. package/dist/components/onboarding-guides/index.js +5 -5
  76. package/dist/components/tickets/index.cjs +7 -7
  77. package/dist/components/tickets/index.js +6 -6
  78. package/dist/components/ui/index.cjs +3 -3
  79. package/dist/components/ui/index.js +2 -2
  80. package/dist/index.cjs +7 -7
  81. package/dist/index.js +6 -6
  82. package/package.json +1 -1
  83. package/src/components/chat/__tests__/ticket-event.test.ts +107 -0
  84. package/src/components/chat/stream/message-mutations.ts +47 -4
  85. package/src/components/chat/utils/process-historical-messages.ts +18 -6
  86. package/dist/chunk-G45RGWHF.cjs.map +0 -1
  87. /package/dist/{chunk-CJOWLRUU.js.map → chunk-6BPIDRBI.js.map} +0 -0
  88. /package/dist/{chunk-CN36E4PK.js.map → chunk-7JPKCUF7.js.map} +0 -0
  89. /package/dist/{chunk-LGBNHWDN.js.map → chunk-ACUXSU6J.js.map} +0 -0
  90. /package/dist/{chunk-KVNGYFFP.js.map → chunk-AV4UXMOH.js.map} +0 -0
  91. /package/dist/{chunk-4ZKAMPBX.js.map → chunk-BKOCXNAP.js.map} +0 -0
  92. /package/dist/{chunk-3OCYNMZ5.js.map → chunk-CT6I3HOP.js.map} +0 -0
  93. /package/dist/{chunk-NXZC6UTN.js.map → chunk-DFUO7J3W.js.map} +0 -0
  94. /package/dist/{chunk-TOYHZHTK.js.map → chunk-E5NSDLYJ.js.map} +0 -0
  95. /package/dist/{chunk-77Y7R243.js.map → chunk-GAXC43J4.js.map} +0 -0
  96. /package/dist/{chunk-FQBR6SCA.js.map → chunk-KLNHD4TC.js.map} +0 -0
  97. /package/dist/{chunk-CNKVEVUN.js.map → chunk-LDNRL62P.js.map} +0 -0
  98. /package/dist/{chunk-I5CJJFEJ.js.map → chunk-LKMRJ2CP.js.map} +0 -0
  99. /package/dist/{chunk-5FNWOF46.js.map → chunk-RLC5IISG.js.map} +0 -0
  100. /package/dist/{chunk-GKPY7VLK.js.map → chunk-RM3PTDSI.js.map} +0 -0
  101. /package/dist/{chunk-NIDPX52C.js.map → chunk-T3WAHAMH.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
2
 
3
3
 
4
- var _chunkEGYX55HTcjs = require('./chunk-EGYX55HT.cjs');
4
+ var _chunkI3HBFKKMcjs = require('./chunk-I3HBFKKM.cjs');
5
5
 
6
6
 
7
7
  var _chunkZI27ALYXcjs = require('./chunk-ZI27ALYX.cjs');
@@ -129,7 +129,7 @@ function useSectionNavigation(sections, options) {
129
129
  // src/components/navigation/multi-level-navigation.tsx
130
130
  var _lucidereact = require('lucide-react');
131
131
 
132
- var DEFAULT_FOLDER_INDEX_FILE2 = _chunkEGYX55HTcjs.DEFAULT_FOLDER_INDEX_FILE;
132
+ var DEFAULT_FOLDER_INDEX_FILE2 = _chunkI3HBFKKMcjs.DEFAULT_FOLDER_INDEX_FILE;
133
133
  function isNodeVisuallySelected(node, selectedPath, folderIndexFile = DEFAULT_FOLDER_INDEX_FILE2) {
134
134
  const FOLDER_INDEX_FILE = folderIndexFile.toLowerCase();
135
135
  if (selectedPath === node.path) {
@@ -357,4 +357,4 @@ function MobileNavigationItem({
357
357
 
358
358
 
359
359
  exports.StickySectionNav = StickySectionNav; exports.useSectionNavigation = useSectionNavigation; exports.MultiLevelNavigation = MultiLevelNavigation; exports.MobileNavigationDropdown = MobileNavigationDropdown;
360
- //# sourceMappingURL=chunk-EGUU3QCU.cjs.map
360
+ //# sourceMappingURL=chunk-2564HPMD.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-EGUU3QCU.cjs","../src/components/navigation/sticky-section-nav.tsx","../src/components/navigation/multi-level-navigation.tsx"],"names":["jsx","DEFAULT_FOLDER_INDEX_FILE"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-EGUU3QCU.cjs","sourcesContent":[null,"'use client';\n\nimport type React from 'react';\nimport { useEffect, useState, useCallback, useRef } from 'react';\nimport { cn } from '../../utils';\nimport { scrollElementIntoView } from '../../utils/scroll-into-view';\n\nexport interface StickyNavSection {\n id: string;\n label: string;\n}\n\ninterface StickySectionNavProps {\n sections: StickyNavSection[];\n activeSection: string;\n onSectionClick: (sectionId: string) => void;\n className?: string;\n ribbonPosition?: 'left' | 'right';\n ribbonColor?: string;\n}\n\n/**\n * Reusable sticky navigation component for section-based navigation\n * Used in vendor detail pages, knowledge base, documentation, etc.\n */\nexport function StickySectionNav({\n sections,\n activeSection,\n onSectionClick,\n className,\n ribbonPosition = 'left',\n ribbonColor = 'var(--color-accent-primary)',\n}: StickySectionNavProps) {\n const navHeight = sections.length * 40; // 40px per item (h-10)\n\n return (\n <nav className={cn('relative bg-ods-bg', className)}>\n {/* Background gray vertical line for all nav items */}\n <div\n className=\"absolute bg-ods-border\"\n style={{\n width: '1px',\n height: `${navHeight}px`,\n [ribbonPosition === 'left' ? 'left' : 'right']: '-2px',\n top: '0px',\n }}\n />\n\n {sections.map(section => (\n <div key={section.id} className=\"relative flex h-10 w-full items-stretch transition-all duration-200\">\n {/* Yellow ribbon for active state */}\n {activeSection === section.id && (\n <div\n className=\"absolute z-10 transition-all duration-200\"\n style={{\n backgroundColor: ribbonColor,\n width: '4px',\n height: '24px',\n [ribbonPosition === 'left' ? 'left' : 'right']: '-2px',\n top: '8px',\n borderRadius: '2px',\n }}\n />\n )}\n\n {/* Navigation button */}\n <button\n onClick={() => onSectionClick(section.id)}\n className=\"relative flex flex-1 cursor-pointer items-center gap-2 px-3 py-2\"\n >\n <span\n className={cn(\n 'text-left transition-all duration-200 text-h6',\n activeSection === section.id\n ? 'text-ods-text-primary'\n : 'text-ods-text-secondary hover:text-ods-text-primary',\n )}\n >\n {section.label}\n </span>\n </button>\n </div>\n ))}\n </nav>\n );\n}\n\n/**\n * SIMPLEST POSSIBLE IMPLEMENTATION - Just make it work\n */\nexport function useSectionNavigation(\n sections: { id: string; ref: React.RefObject<HTMLElement> }[],\n options?: {\n offset?: number;\n },\n) {\n const [activeSection, setActiveSection] = useState(sections[0]?.id || '');\n const isScrollingFromClick = useRef(false);\n const { offset = 100 } = options || {};\n\n // Handle click - scroll to the element via the canonical helper.\n // The `offset` prop maps to `headerOffset` (sticky chrome above the\n // section nav); same smooth-scroll mechanics every other anchor\n // surface in the app uses.\n const handleSectionClick = useCallback(\n (sectionId: string) => {\n const targetElement = document.getElementById(sectionId);\n if (!targetElement) return;\n\n // Prevent scroll spy while we're scrolling\n isScrollingFromClick.current = true;\n setActiveSection(sectionId);\n\n scrollElementIntoView(targetElement, { headerOffset: offset });\n\n // Allow scroll spy again after scroll completes\n setTimeout(() => {\n isScrollingFromClick.current = false;\n }, 500);\n },\n [offset],\n );\n\n // Make sure elements have IDs\n useEffect(() => {\n sections.forEach(section => {\n const el = section.ref.current;\n if (el && !el.id) {\n el.id = section.id;\n }\n });\n }, [sections]);\n\n // Simple scroll spy\n useEffect(() => {\n const handleScroll = () => {\n if (isScrollingFromClick.current) return;\n\n const scrollPosition = window.scrollY + offset + 50;\n\n // Find which section we're in\n let currentSection = sections[0]?.id || '';\n\n for (let i = sections.length - 1; i >= 0; i--) {\n const element = document.getElementById(sections[i].id);\n if (element && scrollPosition >= element.offsetTop) {\n currentSection = sections[i].id;\n break;\n }\n }\n\n setActiveSection(currentSection);\n };\n\n // Throttle the scroll handler\n let scrollTimer: NodeJS.Timeout;\n const throttledScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(handleScroll, 100);\n };\n\n window.addEventListener('scroll', throttledScroll);\n handleScroll(); // Check initial position\n\n return () => {\n window.removeEventListener('scroll', throttledScroll);\n clearTimeout(scrollTimer);\n };\n }, [sections, offset]);\n\n return {\n activeSection,\n handleSectionClick,\n };\n}\n","'use client';\n\nimport { ChevronDown, ChevronUp, FileText, Folder, FolderOpen } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { DEFAULT_FOLDER_INDEX_FILE as CANONICAL_FOLDER_INDEX_FILE } from '../../utils/doc-tree-nav';\n\nexport interface NavigationNode {\n id: string;\n name: string;\n path: string;\n type: 'file' | 'folder';\n hasReadme?: boolean;\n children?: NavigationNode[];\n slug?: string;\n // Mirror DocNode's extra optional fields so a DocNode tree is structurally\n // assignable to NavigationNode[] without an `as` cast. NavigationNode\n // intentionally never reads these — they're carried for type-compat only.\n documentType?: 'markdown' | 'pdf' | 'google_sheet' | 'figma' | 'file';\n sortOrder?: number;\n}\n\ninterface MultiLevelNavigationProps {\n nodes: NavigationNode[];\n selectedPath: string;\n expandedNodes: Set<string>;\n onNodeClick: (node: NavigationNode) => void;\n onToggleExpand?: (nodeId: string) => void;\n isLoading?: boolean;\n className?: string;\n /** Folder-index filename (default `'README.md'`, case-insensitive). When the\n * selectedPath is a folder with this file, the visual ribbon moves to the\n * child file. */\n folderIndexFile?: string;\n}\n\n// SSOT lives in `doc-tree-nav` (canonical case `'README.md'`). The visual\n// comparator below lowercases both sides, so re-exporting the canonical\n// constant under the same local name preserves call-site syntax without\n// drifting from the SSOT.\nconst DEFAULT_FOLDER_INDEX_FILE = CANONICAL_FOLDER_INDEX_FILE;\n\n/**\n * Compute the visual \"selected\" state for a navigation node.\n *\n * Folder-with-README convention: when `selectedPath` is a folder that has a\n * README, the FOLDER doesn't get the ribbon — its README child does. The folder\n * is just a container; the README is the actual document being viewed.\n *\n * Mirror case: a README file whose parent folder is the `selectedPath` gets the\n * visual selection ribbon (implicit). This handles both the auto-select-first-\n * folder landing path AND the user-clicks-folder case.\n */\nfunction isNodeVisuallySelected(\n node: NavigationNode,\n selectedPath: string,\n folderIndexFile: string = DEFAULT_FOLDER_INDEX_FILE,\n): boolean {\n const FOLDER_INDEX_FILE = folderIndexFile.toLowerCase();\n // Path comparisons keyed on `node.path` (raw, includes `.md`). Do NOT use\n // `node.name` — the tree-builder runs it through `formatDocName` which strips\n // the `.md` extension, so `node.name.toLowerCase() === 'readme.md'` is always\n // false.\n if (selectedPath === node.path) {\n // Explicit match — but folder-with-README defers to its README child.\n return !(node.type === 'folder' && node.hasReadme);\n }\n if (node.type !== 'file') return false;\n const pathLower = node.path.toLowerCase();\n // Implicit: README child whose parent folder is the selectedPath.\n if (selectedPath !== '' && pathLower === `${selectedPath.toLowerCase()}/${FOLDER_INDEX_FILE}`) {\n return true;\n }\n // Implicit: ROOT README on the landing page (selectedPath === '' means\n // \"no explicit doc selected\" — the viewer falls back to the root folder-\n // index file, so that file IS the active document).\n if (selectedPath === '' && pathLower === FOLDER_INDEX_FILE) {\n return true;\n }\n return false;\n}\n\nexport function MultiLevelNavigation({\n nodes,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n isLoading,\n className,\n folderIndexFile = DEFAULT_FOLDER_INDEX_FILE,\n}: MultiLevelNavigationProps) {\n if (isLoading) {\n return (\n <div className={cn('space-y-2', className)}>\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"h-12 animate-pulse rounded-lg bg-ods-skeleton p-3\" />\n ))}\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-2', className)} role=\"list\" aria-label=\"Navigation list\">\n {nodes.map(node => (\n <NavigationItem\n key={node.id}\n node={node}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={0}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n );\n}\n\ninterface NavigationItemProps {\n node: NavigationNode;\n selectedPath: string;\n expandedNodes: Set<string>;\n onNodeClick: (node: NavigationNode) => void;\n onToggleExpand?: (nodeId: string) => void;\n level: number;\n folderIndexFile: string;\n}\n\nfunction NavigationItem({\n node,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n level,\n folderIndexFile,\n}: NavigationItemProps) {\n const isExpanded = expandedNodes.has(node.id);\n const isSelected = isNodeVisuallySelected(node, selectedPath, folderIndexFile);\n // Bind the (optional) child list once so the render below maps a real array\n // rather than re-deriving `hasChildren` and asserting it away.\n const children = node.children ?? [];\n const hasChildren = children.length > 0;\n\n return (\n <div className=\"space-y-1\" role=\"listitem\">\n <div className={cn('px-2', level > 0 && 'ml-4')}>\n <div\n className={cn(\n 'relative w-full rounded-lg border transition-all duration-150',\n isSelected ? 'border-ods-border bg-ods-border' : 'border-ods-border bg-ods-card',\n )}\n >\n <div className=\"relative flex items-center\">\n <button\n className={cn(\n 'flex h-12 w-full items-center rounded-lg px-2 text-ods-text-primary transition-all duration-150 text-h6',\n !isSelected && 'hover:bg-ods-bg-hover',\n hasChildren && 'pr-12',\n )}\n onClick={() => onNodeClick(node)}\n aria-label={`${isSelected ? 'Selected' : 'Select'} ${node.name}`}\n >\n <span className=\"mr-2 flex-shrink-0\">\n {node.type === 'folder' ? (\n isExpanded ? (\n <FolderOpen className=\"h-4 w-4\" />\n ) : (\n <Folder className=\"h-4 w-4\" />\n )\n ) : (\n <FileText className=\"h-4 w-4\" />\n )}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-left\">\n {node.name.endsWith('.md') ? node.name.replace('.md', '') : node.name}\n </span>\n {node.type === 'folder' && node.hasReadme && (\n <span className=\"mr-2 rounded bg-ods-bg-surface px-1.5 py-0.5 text-ods-text-secondary text-h6\">\n README\n </span>\n )}\n </button>\n\n {hasChildren && (\n <button\n className=\"absolute right-0 top-0 flex h-12 w-12 items-center justify-center text-ods-text-secondary transition-colors duration-150 hover:text-ods-text-primary\"\n onClick={e => {\n e.stopPropagation();\n if (onToggleExpand) {\n onToggleExpand(node.id);\n } else {\n onNodeClick(node);\n }\n }}\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.name}`}\n >\n {isExpanded ? <ChevronUp className=\"h-4 w-4\" /> : <ChevronDown className=\"h-4 w-4\" />}\n </button>\n )}\n </div>\n\n {isSelected && (\n <div className=\"absolute right-0 top-1/2 h-[calc(100%-8px)] w-1 -translate-y-1/2 rounded-l bg-ods-accent\" />\n )}\n </div>\n </div>\n\n {hasChildren && isExpanded && (\n <div className=\"space-y-1\">\n {children.map(child => (\n <NavigationItem\n key={child.id}\n node={child}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={level + 1}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function MobileNavigationDropdown({\n nodes,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n isLoading,\n className,\n folderIndexFile = DEFAULT_FOLDER_INDEX_FILE,\n}: MultiLevelNavigationProps) {\n if (isLoading) {\n return (\n <div className={cn('space-y-2', className)}>\n {[1, 2, 3].map(i => (\n <div key={i} className=\"h-10 animate-pulse rounded-lg bg-ods-skeleton p-3\" />\n ))}\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n {nodes.map(node => (\n <MobileNavigationItem\n key={node.id}\n node={node}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={0}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n );\n}\n\nfunction MobileNavigationItem({\n node,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n level,\n folderIndexFile,\n}: NavigationItemProps) {\n const isExpanded = expandedNodes.has(node.id);\n const isSelected = isNodeVisuallySelected(node, selectedPath, folderIndexFile);\n // Same binding as the desktop item above — a real array to map, no assertion.\n const children = node.children ?? [];\n const hasChildren = children.length > 0;\n\n return (\n <div className=\"space-y-1\">\n <div className={cn('px-2', level > 0 && 'ml-3')}>\n <div\n className={cn(\n 'relative w-full rounded-lg border transition-all duration-150',\n isSelected ? 'border-ods-border bg-ods-border' : 'border-ods-border bg-ods-card',\n )}\n >\n <div className=\"relative flex items-center\">\n <button\n className={cn(\n 'flex h-11 w-full items-center rounded-lg px-2 text-ods-text-primary transition-all duration-150 text-h6',\n !isSelected && 'hover:bg-ods-bg-hover',\n hasChildren && 'pr-11',\n )}\n onClick={() => onNodeClick(node)}\n >\n <span className=\"mr-2 flex-shrink-0\">\n {node.type === 'folder' ? (\n isExpanded ? (\n <FolderOpen className=\"h-4 w-4\" />\n ) : (\n <Folder className=\"h-4 w-4\" />\n )\n ) : (\n <FileText className=\"h-4 w-4\" />\n )}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-left\">\n {node.name.endsWith('.md') ? node.name.replace('.md', '') : node.name}\n </span>\n {node.type === 'folder' && node.hasReadme && (\n <span className=\"mr-2 rounded bg-ods-bg-surface px-1.5 py-0.5 text-ods-text-secondary text-h6\">\n README\n </span>\n )}\n </button>\n\n {hasChildren && (\n <button\n className=\"absolute right-0 top-0 flex h-11 w-11 items-center justify-center text-ods-text-secondary transition-colors duration-150 hover:text-ods-text-primary\"\n onClick={e => {\n e.stopPropagation();\n if (onToggleExpand) {\n onToggleExpand(node.id);\n } else {\n onNodeClick(node);\n }\n }}\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.name}`}\n >\n {isExpanded ? <ChevronUp className=\"h-3.5 w-3.5\" /> : <ChevronDown className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n </div>\n\n {isSelected && (\n <div className=\"absolute right-0 top-1/2 h-[calc(100%-8px)] w-1 -translate-y-1/2 rounded-l bg-ods-accent\" />\n )}\n </div>\n </div>\n\n {hasChildren && isExpanded && (\n <div className=\"space-y-1\">\n {children.map(child => (\n <MobileNavigationItem\n key={child.id}\n node={child}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={level + 1}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-2564HPMD.cjs","../src/components/navigation/sticky-section-nav.tsx","../src/components/navigation/multi-level-navigation.tsx"],"names":["jsx","DEFAULT_FOLDER_INDEX_FILE"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-2564HPMD.cjs","sourcesContent":[null,"'use client';\n\nimport type React from 'react';\nimport { useEffect, useState, useCallback, useRef } from 'react';\nimport { cn } from '../../utils';\nimport { scrollElementIntoView } from '../../utils/scroll-into-view';\n\nexport interface StickyNavSection {\n id: string;\n label: string;\n}\n\ninterface StickySectionNavProps {\n sections: StickyNavSection[];\n activeSection: string;\n onSectionClick: (sectionId: string) => void;\n className?: string;\n ribbonPosition?: 'left' | 'right';\n ribbonColor?: string;\n}\n\n/**\n * Reusable sticky navigation component for section-based navigation\n * Used in vendor detail pages, knowledge base, documentation, etc.\n */\nexport function StickySectionNav({\n sections,\n activeSection,\n onSectionClick,\n className,\n ribbonPosition = 'left',\n ribbonColor = 'var(--color-accent-primary)',\n}: StickySectionNavProps) {\n const navHeight = sections.length * 40; // 40px per item (h-10)\n\n return (\n <nav className={cn('relative bg-ods-bg', className)}>\n {/* Background gray vertical line for all nav items */}\n <div\n className=\"absolute bg-ods-border\"\n style={{\n width: '1px',\n height: `${navHeight}px`,\n [ribbonPosition === 'left' ? 'left' : 'right']: '-2px',\n top: '0px',\n }}\n />\n\n {sections.map(section => (\n <div key={section.id} className=\"relative flex h-10 w-full items-stretch transition-all duration-200\">\n {/* Yellow ribbon for active state */}\n {activeSection === section.id && (\n <div\n className=\"absolute z-10 transition-all duration-200\"\n style={{\n backgroundColor: ribbonColor,\n width: '4px',\n height: '24px',\n [ribbonPosition === 'left' ? 'left' : 'right']: '-2px',\n top: '8px',\n borderRadius: '2px',\n }}\n />\n )}\n\n {/* Navigation button */}\n <button\n onClick={() => onSectionClick(section.id)}\n className=\"relative flex flex-1 cursor-pointer items-center gap-2 px-3 py-2\"\n >\n <span\n className={cn(\n 'text-left transition-all duration-200 text-h6',\n activeSection === section.id\n ? 'text-ods-text-primary'\n : 'text-ods-text-secondary hover:text-ods-text-primary',\n )}\n >\n {section.label}\n </span>\n </button>\n </div>\n ))}\n </nav>\n );\n}\n\n/**\n * SIMPLEST POSSIBLE IMPLEMENTATION - Just make it work\n */\nexport function useSectionNavigation(\n sections: { id: string; ref: React.RefObject<HTMLElement> }[],\n options?: {\n offset?: number;\n },\n) {\n const [activeSection, setActiveSection] = useState(sections[0]?.id || '');\n const isScrollingFromClick = useRef(false);\n const { offset = 100 } = options || {};\n\n // Handle click - scroll to the element via the canonical helper.\n // The `offset` prop maps to `headerOffset` (sticky chrome above the\n // section nav); same smooth-scroll mechanics every other anchor\n // surface in the app uses.\n const handleSectionClick = useCallback(\n (sectionId: string) => {\n const targetElement = document.getElementById(sectionId);\n if (!targetElement) return;\n\n // Prevent scroll spy while we're scrolling\n isScrollingFromClick.current = true;\n setActiveSection(sectionId);\n\n scrollElementIntoView(targetElement, { headerOffset: offset });\n\n // Allow scroll spy again after scroll completes\n setTimeout(() => {\n isScrollingFromClick.current = false;\n }, 500);\n },\n [offset],\n );\n\n // Make sure elements have IDs\n useEffect(() => {\n sections.forEach(section => {\n const el = section.ref.current;\n if (el && !el.id) {\n el.id = section.id;\n }\n });\n }, [sections]);\n\n // Simple scroll spy\n useEffect(() => {\n const handleScroll = () => {\n if (isScrollingFromClick.current) return;\n\n const scrollPosition = window.scrollY + offset + 50;\n\n // Find which section we're in\n let currentSection = sections[0]?.id || '';\n\n for (let i = sections.length - 1; i >= 0; i--) {\n const element = document.getElementById(sections[i].id);\n if (element && scrollPosition >= element.offsetTop) {\n currentSection = sections[i].id;\n break;\n }\n }\n\n setActiveSection(currentSection);\n };\n\n // Throttle the scroll handler\n let scrollTimer: NodeJS.Timeout;\n const throttledScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(handleScroll, 100);\n };\n\n window.addEventListener('scroll', throttledScroll);\n handleScroll(); // Check initial position\n\n return () => {\n window.removeEventListener('scroll', throttledScroll);\n clearTimeout(scrollTimer);\n };\n }, [sections, offset]);\n\n return {\n activeSection,\n handleSectionClick,\n };\n}\n","'use client';\n\nimport { ChevronDown, ChevronUp, FileText, Folder, FolderOpen } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { DEFAULT_FOLDER_INDEX_FILE as CANONICAL_FOLDER_INDEX_FILE } from '../../utils/doc-tree-nav';\n\nexport interface NavigationNode {\n id: string;\n name: string;\n path: string;\n type: 'file' | 'folder';\n hasReadme?: boolean;\n children?: NavigationNode[];\n slug?: string;\n // Mirror DocNode's extra optional fields so a DocNode tree is structurally\n // assignable to NavigationNode[] without an `as` cast. NavigationNode\n // intentionally never reads these — they're carried for type-compat only.\n documentType?: 'markdown' | 'pdf' | 'google_sheet' | 'figma' | 'file';\n sortOrder?: number;\n}\n\ninterface MultiLevelNavigationProps {\n nodes: NavigationNode[];\n selectedPath: string;\n expandedNodes: Set<string>;\n onNodeClick: (node: NavigationNode) => void;\n onToggleExpand?: (nodeId: string) => void;\n isLoading?: boolean;\n className?: string;\n /** Folder-index filename (default `'README.md'`, case-insensitive). When the\n * selectedPath is a folder with this file, the visual ribbon moves to the\n * child file. */\n folderIndexFile?: string;\n}\n\n// SSOT lives in `doc-tree-nav` (canonical case `'README.md'`). The visual\n// comparator below lowercases both sides, so re-exporting the canonical\n// constant under the same local name preserves call-site syntax without\n// drifting from the SSOT.\nconst DEFAULT_FOLDER_INDEX_FILE = CANONICAL_FOLDER_INDEX_FILE;\n\n/**\n * Compute the visual \"selected\" state for a navigation node.\n *\n * Folder-with-README convention: when `selectedPath` is a folder that has a\n * README, the FOLDER doesn't get the ribbon — its README child does. The folder\n * is just a container; the README is the actual document being viewed.\n *\n * Mirror case: a README file whose parent folder is the `selectedPath` gets the\n * visual selection ribbon (implicit). This handles both the auto-select-first-\n * folder landing path AND the user-clicks-folder case.\n */\nfunction isNodeVisuallySelected(\n node: NavigationNode,\n selectedPath: string,\n folderIndexFile: string = DEFAULT_FOLDER_INDEX_FILE,\n): boolean {\n const FOLDER_INDEX_FILE = folderIndexFile.toLowerCase();\n // Path comparisons keyed on `node.path` (raw, includes `.md`). Do NOT use\n // `node.name` — the tree-builder runs it through `formatDocName` which strips\n // the `.md` extension, so `node.name.toLowerCase() === 'readme.md'` is always\n // false.\n if (selectedPath === node.path) {\n // Explicit match — but folder-with-README defers to its README child.\n return !(node.type === 'folder' && node.hasReadme);\n }\n if (node.type !== 'file') return false;\n const pathLower = node.path.toLowerCase();\n // Implicit: README child whose parent folder is the selectedPath.\n if (selectedPath !== '' && pathLower === `${selectedPath.toLowerCase()}/${FOLDER_INDEX_FILE}`) {\n return true;\n }\n // Implicit: ROOT README on the landing page (selectedPath === '' means\n // \"no explicit doc selected\" — the viewer falls back to the root folder-\n // index file, so that file IS the active document).\n if (selectedPath === '' && pathLower === FOLDER_INDEX_FILE) {\n return true;\n }\n return false;\n}\n\nexport function MultiLevelNavigation({\n nodes,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n isLoading,\n className,\n folderIndexFile = DEFAULT_FOLDER_INDEX_FILE,\n}: MultiLevelNavigationProps) {\n if (isLoading) {\n return (\n <div className={cn('space-y-2', className)}>\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"h-12 animate-pulse rounded-lg bg-ods-skeleton p-3\" />\n ))}\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-2', className)} role=\"list\" aria-label=\"Navigation list\">\n {nodes.map(node => (\n <NavigationItem\n key={node.id}\n node={node}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={0}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n );\n}\n\ninterface NavigationItemProps {\n node: NavigationNode;\n selectedPath: string;\n expandedNodes: Set<string>;\n onNodeClick: (node: NavigationNode) => void;\n onToggleExpand?: (nodeId: string) => void;\n level: number;\n folderIndexFile: string;\n}\n\nfunction NavigationItem({\n node,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n level,\n folderIndexFile,\n}: NavigationItemProps) {\n const isExpanded = expandedNodes.has(node.id);\n const isSelected = isNodeVisuallySelected(node, selectedPath, folderIndexFile);\n // Bind the (optional) child list once so the render below maps a real array\n // rather than re-deriving `hasChildren` and asserting it away.\n const children = node.children ?? [];\n const hasChildren = children.length > 0;\n\n return (\n <div className=\"space-y-1\" role=\"listitem\">\n <div className={cn('px-2', level > 0 && 'ml-4')}>\n <div\n className={cn(\n 'relative w-full rounded-lg border transition-all duration-150',\n isSelected ? 'border-ods-border bg-ods-border' : 'border-ods-border bg-ods-card',\n )}\n >\n <div className=\"relative flex items-center\">\n <button\n className={cn(\n 'flex h-12 w-full items-center rounded-lg px-2 text-ods-text-primary transition-all duration-150 text-h6',\n !isSelected && 'hover:bg-ods-bg-hover',\n hasChildren && 'pr-12',\n )}\n onClick={() => onNodeClick(node)}\n aria-label={`${isSelected ? 'Selected' : 'Select'} ${node.name}`}\n >\n <span className=\"mr-2 flex-shrink-0\">\n {node.type === 'folder' ? (\n isExpanded ? (\n <FolderOpen className=\"h-4 w-4\" />\n ) : (\n <Folder className=\"h-4 w-4\" />\n )\n ) : (\n <FileText className=\"h-4 w-4\" />\n )}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-left\">\n {node.name.endsWith('.md') ? node.name.replace('.md', '') : node.name}\n </span>\n {node.type === 'folder' && node.hasReadme && (\n <span className=\"mr-2 rounded bg-ods-bg-surface px-1.5 py-0.5 text-ods-text-secondary text-h6\">\n README\n </span>\n )}\n </button>\n\n {hasChildren && (\n <button\n className=\"absolute right-0 top-0 flex h-12 w-12 items-center justify-center text-ods-text-secondary transition-colors duration-150 hover:text-ods-text-primary\"\n onClick={e => {\n e.stopPropagation();\n if (onToggleExpand) {\n onToggleExpand(node.id);\n } else {\n onNodeClick(node);\n }\n }}\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.name}`}\n >\n {isExpanded ? <ChevronUp className=\"h-4 w-4\" /> : <ChevronDown className=\"h-4 w-4\" />}\n </button>\n )}\n </div>\n\n {isSelected && (\n <div className=\"absolute right-0 top-1/2 h-[calc(100%-8px)] w-1 -translate-y-1/2 rounded-l bg-ods-accent\" />\n )}\n </div>\n </div>\n\n {hasChildren && isExpanded && (\n <div className=\"space-y-1\">\n {children.map(child => (\n <NavigationItem\n key={child.id}\n node={child}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={level + 1}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function MobileNavigationDropdown({\n nodes,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n isLoading,\n className,\n folderIndexFile = DEFAULT_FOLDER_INDEX_FILE,\n}: MultiLevelNavigationProps) {\n if (isLoading) {\n return (\n <div className={cn('space-y-2', className)}>\n {[1, 2, 3].map(i => (\n <div key={i} className=\"h-10 animate-pulse rounded-lg bg-ods-skeleton p-3\" />\n ))}\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n {nodes.map(node => (\n <MobileNavigationItem\n key={node.id}\n node={node}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={0}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n );\n}\n\nfunction MobileNavigationItem({\n node,\n selectedPath,\n expandedNodes,\n onNodeClick,\n onToggleExpand,\n level,\n folderIndexFile,\n}: NavigationItemProps) {\n const isExpanded = expandedNodes.has(node.id);\n const isSelected = isNodeVisuallySelected(node, selectedPath, folderIndexFile);\n // Same binding as the desktop item above — a real array to map, no assertion.\n const children = node.children ?? [];\n const hasChildren = children.length > 0;\n\n return (\n <div className=\"space-y-1\">\n <div className={cn('px-2', level > 0 && 'ml-3')}>\n <div\n className={cn(\n 'relative w-full rounded-lg border transition-all duration-150',\n isSelected ? 'border-ods-border bg-ods-border' : 'border-ods-border bg-ods-card',\n )}\n >\n <div className=\"relative flex items-center\">\n <button\n className={cn(\n 'flex h-11 w-full items-center rounded-lg px-2 text-ods-text-primary transition-all duration-150 text-h6',\n !isSelected && 'hover:bg-ods-bg-hover',\n hasChildren && 'pr-11',\n )}\n onClick={() => onNodeClick(node)}\n >\n <span className=\"mr-2 flex-shrink-0\">\n {node.type === 'folder' ? (\n isExpanded ? (\n <FolderOpen className=\"h-4 w-4\" />\n ) : (\n <Folder className=\"h-4 w-4\" />\n )\n ) : (\n <FileText className=\"h-4 w-4\" />\n )}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-left\">\n {node.name.endsWith('.md') ? node.name.replace('.md', '') : node.name}\n </span>\n {node.type === 'folder' && node.hasReadme && (\n <span className=\"mr-2 rounded bg-ods-bg-surface px-1.5 py-0.5 text-ods-text-secondary text-h6\">\n README\n </span>\n )}\n </button>\n\n {hasChildren && (\n <button\n className=\"absolute right-0 top-0 flex h-11 w-11 items-center justify-center text-ods-text-secondary transition-colors duration-150 hover:text-ods-text-primary\"\n onClick={e => {\n e.stopPropagation();\n if (onToggleExpand) {\n onToggleExpand(node.id);\n } else {\n onNodeClick(node);\n }\n }}\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.name}`}\n >\n {isExpanded ? <ChevronUp className=\"h-3.5 w-3.5\" /> : <ChevronDown className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n </div>\n\n {isSelected && (\n <div className=\"absolute right-0 top-1/2 h-[calc(100%-8px)] w-1 -translate-y-1/2 rounded-l bg-ods-accent\" />\n )}\n </div>\n </div>\n\n {hasChildren && isExpanded && (\n <div className=\"space-y-1\">\n {children.map(child => (\n <MobileNavigationItem\n key={child.id}\n node={child}\n selectedPath={selectedPath}\n expandedNodes={expandedNodes}\n onNodeClick={onNodeClick}\n onToggleExpand={onToggleExpand}\n level={level + 1}\n folderIndexFile={folderIndexFile}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1,13 +1,13 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
2
 
3
3
 
4
- var _chunkBONXSRHZcjs = require('./chunk-BONXSRHZ.cjs');
4
+ var _chunkWIAEFA2Kcjs = require('./chunk-WIAEFA2K.cjs');
5
5
 
6
6
 
7
7
 
8
8
 
9
9
 
10
- var _chunk5CHW7AMPcjs = require('./chunk-5CHW7AMP.cjs');
10
+ var _chunk3BQESV5Gcjs = require('./chunk-3BQESV5G.cjs');
11
11
 
12
12
 
13
13
 
@@ -18,7 +18,7 @@ var _chunkS4CLML75cjs = require('./chunk-S4CLML75.cjs');
18
18
 
19
19
 
20
20
 
21
- var _chunkMENQLD57cjs = require('./chunk-MENQLD57.cjs');
21
+ var _chunkCQHFRJSGcjs = require('./chunk-CQHFRJSG.cjs');
22
22
 
23
23
 
24
24
 
@@ -33,7 +33,7 @@ var _chunkMENQLD57cjs = require('./chunk-MENQLD57.cjs');
33
33
 
34
34
 
35
35
 
36
- var _chunkEGYX55HTcjs = require('./chunk-EGYX55HT.cjs');
36
+ var _chunkI3HBFKKMcjs = require('./chunk-I3HBFKKM.cjs');
37
37
 
38
38
 
39
39
 
@@ -51,7 +51,7 @@ var _chunkIKDC3R7Vcjs = require('./chunk-IKDC3R7V.cjs');
51
51
 
52
52
 
53
53
 
54
- var _chunkG45RGWHFcjs = require('./chunk-G45RGWHF.cjs');
54
+ var _chunk353GRCTEcjs = require('./chunk-353GRCTE.cjs');
55
55
 
56
56
 
57
57
 
@@ -107,7 +107,7 @@ var TicketActionFailure = class extends Error {
107
107
  function useTicketActions(options) {
108
108
  const queryClient = _reactquery.useQueryClient.call(void 0, );
109
109
  const ticketActionEndpoint = _nullishCoalesce(_chunkRDTOMWDNcjs.useRequiredChatRuntime.call(void 0, ).endpoints.ticketActionUrl, () => ( TICKET_ACTION_ENDPOINT));
110
- const ticketLive = _chunkMENQLD57cjs.useOptionalTicketLive.call(void 0, );
110
+ const ticketLive = _chunkCQHFRJSGcjs.useOptionalTicketLive.call(void 0, );
111
111
  const notifyTicketCreated = _optionalChain([ticketLive, 'optionalAccess', _2 => _2.notifyTicketCreated]);
112
112
  const { prependOptimistic, removeOptimistic, removeTicketFromCache, toast: toast2, onSupportSystemDown } = options;
113
113
  const formInFlightRef = _react.useRef.call(void 0, null);
@@ -268,10 +268,10 @@ function useTicketActions(options) {
268
268
  ..._optionalChain([input, 'access', _3 => _3.attachments, 'optionalAccess', _4 => _4.length]) ? { attachments: input.attachments } : {}
269
269
  });
270
270
  if (result.mirror_synced === false) {
271
- toast2(_chunkMENQLD57cjs.TOAST_COPY.open_mirror_pending);
271
+ toast2(_chunkCQHFRJSGcjs.TOAST_COPY.open_mirror_pending);
272
272
  watchMirrorSync(placeholderId, result.ticket_id);
273
273
  } else {
274
- toast2(_chunkMENQLD57cjs.TOAST_COPY.open_success);
274
+ toast2(_chunkCQHFRJSGcjs.TOAST_COPY.open_success);
275
275
  await queryClient.invalidateQueries({ queryKey: ["tickets"] });
276
276
  removeOptimistic(placeholderId);
277
277
  }
@@ -357,7 +357,7 @@ function useTicketActions(options) {
357
357
  ...hasText ? { content_addendum: trimmed } : {},
358
358
  ...hasFiles ? { attachments } : {}
359
359
  },
360
- _chunkMENQLD57cjs.TOAST_COPY.comment_success,
360
+ _chunkCQHFRJSGcjs.TOAST_COPY.comment_success,
361
361
  "send message"
362
362
  );
363
363
  if (ok) {
@@ -380,13 +380,13 @@ function useTicketActions(options) {
380
380
  status: "CLOSED",
381
381
  ..._optionalChain([resolution, 'optionalAccess', _6 => _6.trim, 'call', _7 => _7()]) ? { resolution: resolution.trim() } : {}
382
382
  },
383
- _chunkMENQLD57cjs.TOAST_COPY.close_success,
383
+ _chunkCQHFRJSGcjs.TOAST_COPY.close_success,
384
384
  "close ticket"
385
385
  ),
386
386
  [updateTicket]
387
387
  );
388
388
  const reopenTicket = _react.useCallback.call(void 0,
389
- (ticket) => updateTicket(ticket, { status: "OPEN" }, _chunkMENQLD57cjs.TOAST_COPY.reopen_success, "reopen ticket"),
389
+ (ticket) => updateTicket(ticket, { status: "OPEN" }, _chunkCQHFRJSGcjs.TOAST_COPY.reopen_success, "reopen ticket"),
390
390
  [updateTicket]
391
391
  );
392
392
  return _react.useMemo.call(void 0,
@@ -611,14 +611,14 @@ function useTicketsList(filters) {
611
611
  // src/components/tickets/ticket-open-form.tsx
612
612
 
613
613
  var _jsxruntime = require('react/jsx-runtime');
614
- var COUNTER_VISIBLE_AT = Math.floor(_chunkMENQLD57cjs.TICKET_TEXT_MAX_CHARS * 0.8);
614
+ var COUNTER_VISIBLE_AT = Math.floor(_chunkCQHFRJSGcjs.TICKET_TEXT_MAX_CHARS * 0.8);
615
615
  function TicketOpenForm({ onSubmit, isSubmitting, supportSystemDown }) {
616
616
  const [subject, setSubject] = _react.useState.call(void 0, "");
617
617
  const [content, setContent] = _react.useState.call(void 0, "");
618
- const { attachments, readyAttachments, hasInflightUploads, addFiles, removeAttachment, clear } = _chunkG45RGWHFcjs.useChatAttachments.call(void 0, );
618
+ const { attachments, readyAttachments, hasInflightUploads, addFiles, removeAttachment, clear } = _chunk353GRCTEcjs.useChatAttachments.call(void 0, );
619
619
  const trimmedSubject = subject.trim();
620
620
  const trimmedContent = content.trim();
621
- const overCap = content.length > _chunkMENQLD57cjs.TICKET_TEXT_MAX_CHARS;
621
+ const overCap = content.length > _chunkCQHFRJSGcjs.TICKET_TEXT_MAX_CHARS;
622
622
  const showCounter = content.length >= COUNTER_VISIBLE_AT;
623
623
  const canSubmit = !isSubmitting && !supportSystemDown && !hasInflightUploads && trimmedSubject.length > 0 && trimmedContent.length > 0 && !overCap;
624
624
  const handleSubmit = async (e) => {
@@ -660,7 +660,7 @@ function TicketOpenForm({ onSubmit, isSubmitting, supportSystemDown }) {
660
660
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
661
661
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: "ticket-content", className: "mb-1 block text-ods-text-primary text-h6", children: "Your Message" }),
662
662
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
663
- _chunkEGYX55HTcjs.Textarea,
663
+ _chunkI3HBFKKMcjs.Textarea,
664
664
  {
665
665
  id: "ticket-content",
666
666
  placeholder: "Describe your issue or question in detail...",
@@ -674,11 +674,11 @@ function TicketOpenForm({ onSubmit, isSubmitting, supportSystemDown }) {
674
674
  showCounter && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: `mt-1 text-right text-h6 ${overCap ? "text-ods-error" : "text-ods-text-secondary"}`, children: [
675
675
  content.length,
676
676
  "/",
677
- _chunkMENQLD57cjs.TICKET_TEXT_MAX_CHARS
677
+ _chunkCQHFRJSGcjs.TICKET_TEXT_MAX_CHARS
678
678
  ] })
679
679
  ] }),
680
680
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
681
- _chunkG45RGWHFcjs.ChatAttachmentChipStrip,
681
+ _chunk353GRCTEcjs.ChatAttachmentChipStrip,
682
682
  {
683
683
  attachments,
684
684
  onRemove: removeAttachment,
@@ -687,7 +687,7 @@ function TicketOpenForm({ onSubmit, isSubmitting, supportSystemDown }) {
687
687
  ),
688
688
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-3", children: [
689
689
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
690
- _chunkG45RGWHFcjs.ChatAttachmentAddButton,
690
+ _chunk353GRCTEcjs.ChatAttachmentAddButton,
691
691
  {
692
692
  attachmentsEnabled: !supportSystemDown,
693
693
  attachmentsCount: attachments.length,
@@ -717,7 +717,7 @@ var _usesticktobottom = require('use-stick-to-bottom');
717
717
 
718
718
  var LIST_ENGAGEMENTS_ENDPOINT = "/api/chat/agent/list-engagements";
719
719
  function useTicketEngagements(externalTicketId, enabled = true) {
720
- const identity = _chunkG45RGWHFcjs.useChatIdentity.call(void 0, );
720
+ const identity = _chunk353GRCTEcjs.useChatIdentity.call(void 0, );
721
721
  const identityKey = _nullishCoalesce(_optionalChain([identity, 'access', _21 => _21.user, 'optionalAccess', _22 => _22.email]), () => ( "anon"));
722
722
  const listEngagementsEndpoint = _nullishCoalesce(_chunkRDTOMWDNcjs.useRequiredChatRuntime.call(void 0, ).endpoints.listEngagementsUrl, () => ( LIST_ENGAGEMENTS_ENDPOINT));
723
723
  const fetchable = enabled && !!externalTicketId && !externalTicketId.startsWith("temp-");
@@ -790,7 +790,7 @@ function TicketLinkedDeliveryCard({ clickup, className }) {
790
790
  dateClosed: clickup.date_closed,
791
791
  clickupUrl: _nullishCoalesce(clickup.clickup_url, () => ( ""))
792
792
  };
793
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `overflow-hidden rounded-md border border-ods-border bg-ods-bg ${_nullishCoalesce(className, () => ( ""))}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DeliveryRow, { item, href: clickup.delivery_href, caption: "Linked delivery" }) });
793
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `overflow-hidden rounded-md border border-ods-border bg-ods-bg ${_nullishCoalesce(className, () => ( ""))}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DeliveryRow, { item, href: clickup.delivery_href, caption: "Linked delivery" }) });
794
794
  }
795
795
 
796
796
  // src/components/tickets/ticket-reply-composer.tsx
@@ -805,7 +805,7 @@ function TicketReplyComposer({
805
805
  }) {
806
806
  const [resolution, setResolution] = _react.useState.call(void 0, "");
807
807
  const [closeDialogOpen, setCloseDialogOpen] = _react.useState.call(void 0, false);
808
- const attachments = _chunkG45RGWHFcjs.useChatAttachments.call(void 0, );
808
+ const attachments = _chunk353GRCTEcjs.useChatAttachments.call(void 0, );
809
809
  const { readyAttachments, clear: clearAttachments } = attachments;
810
810
  const ticketRef = { id: ticket.id, external_id: ticket.external_id };
811
811
  const hasReadyFiles = readyAttachments.length > 0;
@@ -826,7 +826,7 @@ function TicketReplyComposer({
826
826
  const disabled = busy || supportSystemDown;
827
827
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
828
828
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
829
- _chunkG45RGWHFcjs.ChatAttachmentChipStrip,
829
+ _chunk353GRCTEcjs.ChatAttachmentChipStrip,
830
830
  {
831
831
  attachments: attachments.attachments,
832
832
  onRemove: attachments.removeAttachment,
@@ -835,7 +835,7 @@ function TicketReplyComposer({
835
835
  }
836
836
  ),
837
837
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
838
- _chunkG45RGWHFcjs.ChatInput,
838
+ _chunk353GRCTEcjs.ChatInput,
839
839
  {
840
840
  fullWidth: true,
841
841
  autoFocus: true,
@@ -843,13 +843,13 @@ function TicketReplyComposer({
843
843
  sending: busy || attachments.hasInflightUploads,
844
844
  disabled: supportSystemDown,
845
845
  allowEmptySend: hasReadyFiles,
846
- maxLength: _chunkMENQLD57cjs.TICKET_TEXT_MAX_CHARS,
846
+ maxLength: _chunkCQHFRJSGcjs.TICKET_TEXT_MAX_CHARS,
847
847
  onSend: handleSend
848
848
  }
849
849
  ),
850
850
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full items-center gap-2", children: [
851
851
  !supportSystemDown && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
852
- _chunkG45RGWHFcjs.ChatAttachmentAddButton,
852
+ _chunk353GRCTEcjs.ChatAttachmentAddButton,
853
853
  {
854
854
  attachmentsEnabled: true,
855
855
  attachmentsCount: attachments.attachments.length,
@@ -872,25 +872,25 @@ function TicketReplyComposer({
872
872
  }
873
873
  )
874
874
  ] }),
875
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEGYX55HTcjs.AlertDialog, { open: closeDialogOpen, onOpenChange: setCloseDialogOpen, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkEGYX55HTcjs.AlertDialogContent, { className: "border-ods-border bg-ods-card", children: [
876
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkEGYX55HTcjs.AlertDialogHeader, { children: [
877
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEGYX55HTcjs.AlertDialogTitle, { className: "text-ods-text-primary", children: "Close this ticket?" }),
878
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEGYX55HTcjs.AlertDialogDescription, { className: "text-ods-text-secondary", children: "Add an optional resolution note below. You can reopen the ticket later if needed." })
875
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkI3HBFKKMcjs.AlertDialog, { open: closeDialogOpen, onOpenChange: setCloseDialogOpen, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkI3HBFKKMcjs.AlertDialogContent, { className: "border-ods-border bg-ods-card", children: [
876
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkI3HBFKKMcjs.AlertDialogHeader, { children: [
877
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkI3HBFKKMcjs.AlertDialogTitle, { className: "text-ods-text-primary", children: "Close this ticket?" }),
878
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkI3HBFKKMcjs.AlertDialogDescription, { className: "text-ods-text-secondary", children: "Add an optional resolution note below. You can reopen the ticket later if needed." })
879
879
  ] }),
880
880
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
881
- _chunkEGYX55HTcjs.Textarea,
881
+ _chunkI3HBFKKMcjs.Textarea,
882
882
  {
883
883
  value: resolution,
884
884
  onChange: (e) => setResolution(e.target.value),
885
885
  placeholder: "Resolution (optional)",
886
886
  rows: 3,
887
- maxLength: _chunkMENQLD57cjs.TICKET_TEXT_MAX_CHARS,
887
+ maxLength: _chunkCQHFRJSGcjs.TICKET_TEXT_MAX_CHARS,
888
888
  className: "mt-2"
889
889
  }
890
890
  ),
891
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkEGYX55HTcjs.AlertDialogFooter, { children: [
891
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkI3HBFKKMcjs.AlertDialogFooter, { children: [
892
892
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
893
- _chunkEGYX55HTcjs.AlertDialogCancel,
893
+ _chunkI3HBFKKMcjs.AlertDialogCancel,
894
894
  {
895
895
  disabled: busy,
896
896
  className: "border-ods-border bg-transparent text-ods-text-primary hover:bg-ods-border",
@@ -898,7 +898,7 @@ function TicketReplyComposer({
898
898
  }
899
899
  ),
900
900
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
901
- _chunkEGYX55HTcjs.AlertDialogAction,
901
+ _chunkI3HBFKKMcjs.AlertDialogAction,
902
902
  {
903
903
  onClick: () => void confirmClose(),
904
904
  disabled: busy,
@@ -960,10 +960,10 @@ var TICKET_FEED_HEIGHT = "h-[60vh] md:h-[420px]";
960
960
  var TICKET_FEED_INNER = "flex flex-col gap-4 md:gap-6 px-4 md:px-6 py-4 md:py-6";
961
961
  var TICKET_FEED_SKELETON_ROWS = 6;
962
962
  function TicketTimelinePanel({ ticket }) {
963
- const identity = _chunkG45RGWHFcjs.useChatIdentity.call(void 0, );
964
- const externalId = _chunkMENQLD57cjs.isOptimistic.call(void 0, ticket) ? null : ticket.external_id;
963
+ const identity = _chunk353GRCTEcjs.useChatIdentity.call(void 0, );
964
+ const externalId = _chunkCQHFRJSGcjs.isOptimistic.call(void 0, ticket) ? null : ticket.external_id;
965
965
  const { engagements, isLoading } = useTicketEngagements(externalId, !!externalId);
966
- const live = _chunkMENQLD57cjs.useOptionalTicketLive.call(void 0, );
966
+ const live = _chunkCQHFRJSGcjs.useOptionalTicketLive.call(void 0, );
967
967
  const setOpenTicketId = _optionalChain([live, 'optionalAccess', _25 => _25.setOpenTicketId]);
968
968
  const markRead = _optionalChain([live, 'optionalAccess', _26 => _26.markRead]);
969
969
  const markReadDebounceRef = _react.useRef.call(void 0, null);
@@ -987,7 +987,7 @@ function TicketTimelinePanel({ ticket }) {
987
987
  markReadDebounceRef.current = setTimeout(() => {
988
988
  markReadDebounceRef.current = null;
989
989
  void markRead(externalId);
990
- }, _chunkMENQLD57cjs.TICKET_MARK_READ_DEBOUNCE_MS);
990
+ }, _chunkCQHFRJSGcjs.TICKET_MARK_READ_DEBOUNCE_MS);
991
991
  }, [engagementsCount, externalId, markRead]);
992
992
  const { scrollRef, contentRef } = _usesticktobottom.useStickToBottom.call(void 0, { initial: "instant", resize: "smooth" });
993
993
  const bodyTurns = ticket.body ? ticket.body.split(TURN_SEPARATOR_RE).map((t) => t.trim()).filter(Boolean) : [];
@@ -1002,7 +1002,7 @@ function TicketTimelinePanel({ ticket }) {
1002
1002
  const customerName = (isViewerTheCustomer ? viewerName : null) || ticketCustomerName || viewerName || _optionalChain([identity, 'access', _40 => _40.user, 'optionalAccess', _41 => _41.email]) || "You";
1003
1003
  const customerAvatar = isViewerTheCustomer ? _nullishCoalesce(_optionalChain([identity, 'access', _42 => _42.user, 'optionalAccess', _43 => _43.avatarUrl]), () => ( void 0)) : void 0;
1004
1004
  if (isLoading) {
1005
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `${TICKET_FEED_FRAME} ${TICKET_FEED_HEIGHT}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: TICKET_FEED_INNER, children: Array.from({ length: TICKET_FEED_SKELETON_ROWS }, (_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkG45RGWHFcjs.ChatMessageRowSkeleton, {}, i)) }) });
1005
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `${TICKET_FEED_FRAME} ${TICKET_FEED_HEIGHT}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: TICKET_FEED_INNER, children: Array.from({ length: TICKET_FEED_SKELETON_ROWS }, (_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk353GRCTEcjs.ChatMessageRowSkeleton, {}, i)) }) });
1006
1006
  }
1007
1007
  if (bodyTurns.length === 0 && engagements.length === 0) {
1008
1008
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -1021,7 +1021,7 @@ function TicketTimelinePanel({ ticket }) {
1021
1021
  const isResolution = turn.startsWith("[Resolution]");
1022
1022
  const text = isResolution ? turn.replace(/^\[Resolution\]\s*/, "") : turn;
1023
1023
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1024
- _chunkG45RGWHFcjs.ChatMessageRow,
1024
+ _chunk353GRCTEcjs.ChatMessageRow,
1025
1025
  {
1026
1026
  displayName: customerName,
1027
1027
  avatarUrl: customerAvatar,
@@ -1050,13 +1050,13 @@ function TicketTimelinePanel({ ticket }) {
1050
1050
  }
1051
1051
  const engAttachments = mapEngagementAttachments(eng.attachments);
1052
1052
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1053
- _chunkG45RGWHFcjs.ChatMessageRow,
1053
+ _chunk353GRCTEcjs.ChatMessageRow,
1054
1054
  {
1055
1055
  displayName: author,
1056
1056
  avatarUrl: avatarSrc,
1057
- timeLabel: eng.createdAt ? _chunkG45RGWHFcjs.formatRelativeTime.call(void 0, eng.createdAt) : null,
1057
+ timeLabel: eng.createdAt ? _chunk353GRCTEcjs.formatRelativeTime.call(void 0, eng.createdAt) : null,
1058
1058
  body: stripAttachmentsPreamble(_nullishCoalesce(eng.body, () => ( ""))),
1059
- footer: engAttachments.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEGYX55HTcjs.TicketAttachmentsList, { attachments: engAttachments, size: "compact" }) }) : null
1059
+ footer: engAttachments.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkI3HBFKKMcjs.TicketAttachmentsList, { attachments: engAttachments, size: "compact" }) }) : null
1060
1060
  },
1061
1061
  eng.id
1062
1062
  );
@@ -1169,7 +1169,7 @@ function TicketRow({
1169
1169
  onActionCollapsed,
1170
1170
  id
1171
1171
  }) {
1172
- const optimistic = _chunkMENQLD57cjs.isOptimistic.call(void 0, ticket);
1172
+ const optimistic = _chunkCQHFRJSGcjs.isOptimistic.call(void 0, ticket);
1173
1173
  const rowRef = _react.useRef.call(void 0, null);
1174
1174
  const handleClick = _react.useCallback.call(void 0, () => {
1175
1175
  onToggle(ticket.id);
@@ -1197,7 +1197,7 @@ function TicketRow({
1197
1197
  // so the badge accurately reflects "Closed" with a checkmark.
1198
1198
  statusLabel: _nullishCoalesce(ticket.pipeline_stage_label, () => ( void 0)),
1199
1199
  category: _nullishCoalesce(ticket.customer_company, () => ( void 0)),
1200
- timeAgo: ticket.hubspot_updated_at ? _chunkG45RGWHFcjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : void 0,
1200
+ timeAgo: ticket.hubspot_updated_at ? _chunk353GRCTEcjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : void 0,
1201
1201
  // Linked-work chip: surfaced whenever the ticket has a linked
1202
1202
  // ClickUp task. Uses the linked task's own status so the chip text
1203
1203
  // reads "Working" / "Waiting on version release" / etc. — useful
@@ -1207,7 +1207,7 @@ function TicketRow({
1207
1207
  };
1208
1208
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: rowRef, id, className: "scroll-mt-24", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Collapsible, { open: expanded && !optimistic, className: "border-b border-ods-border last:border-b-0", children: [
1209
1209
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1210
- _chunkG45RGWHFcjs.ChatTicketItem,
1210
+ _chunk353GRCTEcjs.ChatTicketItem,
1211
1211
  {
1212
1212
  ticket: tileData,
1213
1213
  onClick: optimistic ? void 0 : handleClick,
@@ -1240,7 +1240,7 @@ function TicketRow({
1240
1240
  // src/components/tickets/ticket-center.tsx
1241
1241
 
1242
1242
  function TicketCenter({ toast: toast2 = _chunkLEISUAHFcjs.toast } = {}) {
1243
- const identity = _chunkG45RGWHFcjs.useChatIdentity.call(void 0, );
1243
+ const identity = _chunk353GRCTEcjs.useChatIdentity.call(void 0, );
1244
1244
  if (identity.isLoading) {
1245
1245
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketCenterSkeleton, {});
1246
1246
  }
@@ -1311,7 +1311,7 @@ function TicketCenterAuthed({
1311
1311
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3 text-ods-text-secondary text-h6", children: [
1312
1312
  lastUpdatedAt && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
1313
1313
  "Updated ",
1314
- _chunkG45RGWHFcjs.formatRelativeTime.call(void 0, new Date(lastUpdatedAt))
1314
+ _chunk353GRCTEcjs.formatRelativeTime.call(void 0, new Date(lastUpdatedAt))
1315
1315
  ] }),
1316
1316
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1317
1317
  _chunkYHNIPSG6cjs.Button,
@@ -1338,11 +1338,11 @@ function TicketCenterAuthed({
1338
1338
  ) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEMF64FWAcjs.Card, { className: "overflow-hidden", children: merged.map((ticket) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1339
1339
  TicketRow,
1340
1340
  {
1341
- id: _chunkEGYX55HTcjs.devSectionAnchorId.call(void 0, "ticket", ticket.external_id),
1341
+ id: _chunkI3HBFKKMcjs.devSectionAnchorId.call(void 0, "ticket", ticket.external_id),
1342
1342
  ticket,
1343
1343
  expanded: expandedTicketId === ticket.id,
1344
1344
  onToggle: toggleRow,
1345
- busy: _chunkMENQLD57cjs.isOptimistic.call(void 0, ticket) ? false : actions.isRowBusy(ticket.id),
1345
+ busy: _chunkCQHFRJSGcjs.isOptimistic.call(void 0, ticket) ? false : actions.isRowBusy(ticket.id),
1346
1346
  supportSystemDown,
1347
1347
  onSendMessage: actions.sendMessage,
1348
1348
  onClose: actions.closeTicket,
@@ -1396,10 +1396,10 @@ function HelpCenterCard({
1396
1396
  onClearReplyError,
1397
1397
  id
1398
1398
  }) {
1399
- const optimistic = _chunkMENQLD57cjs.isOptimistic.call(void 0, ticket);
1399
+ const optimistic = _chunkCQHFRJSGcjs.isOptimistic.call(void 0, ticket);
1400
1400
  const rawStatus = (_nullishCoalesce(ticket.status, () => ( "OPEN"))).toUpperCase();
1401
1401
  const priority = (_nullishCoalesce(ticket.priority, () => ( ""))).toUpperCase();
1402
- const relativeUpdated = ticket.hubspot_updated_at ? _chunkG45RGWHFcjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : "recently";
1402
+ const relativeUpdated = ticket.hubspot_updated_at ? _chunk353GRCTEcjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : "recently";
1403
1403
  const title = (ticket.subject || "").trim() || "(untitled)";
1404
1404
  const subtitle = `UPDATED ${relativeUpdated}, #${ticket.external_id || "\u2014"}${ticket.pipeline_stage_label ? `, ${ticket.pipeline_stage_label}` : ""}`;
1405
1405
  const description = _nullishCoalesce(_nullishCoalesce(ticket.preview, () => ( ticket.body)), () => ( ""));
@@ -1418,7 +1418,7 @@ function HelpCenterCard({
1418
1418
  });
1419
1419
  return () => cancelAnimationFrame(raf);
1420
1420
  }, [isExpanded]);
1421
- const live = _chunkMENQLD57cjs.useOptionalTicketLive.call(void 0, );
1421
+ const live = _chunkCQHFRJSGcjs.useOptionalTicketLive.call(void 0, );
1422
1422
  const unreadCount = !optimistic && ticket.external_id && _optionalChain([live, 'optionalAccess', _64 => _64.unreadByTicket, 'access', _65 => _65[ticket.external_id]]) || 0;
1423
1423
  const rightBadges = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1424
1424
  unreadCount > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -1468,7 +1468,7 @@ function HelpCenterCard({
1468
1468
  "aria-controls": isExpanded ? `help-center-drawer-${ticket.id}` : void 0,
1469
1469
  className: "w-full p-[12px] text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-accent disabled:cursor-default md:p-[16px]",
1470
1470
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1471
- _chunk5CHW7AMPcjs.DevCardRowContent,
1471
+ _chunk3BQESV5Gcjs.DevCardRowContent,
1472
1472
  {
1473
1473
  title,
1474
1474
  subtitle,
@@ -1568,7 +1568,7 @@ function HelpCenterCreateForm({
1568
1568
  subjectError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { id: "help-center-subject-error", className: "mt-1 text-ods-error text-h6", children: subjectError })
1569
1569
  ] });
1570
1570
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1571
- _chunkBONXSRHZcjs.ContactForm,
1571
+ _chunkWIAEFA2Kcjs.ContactForm,
1572
1572
  {
1573
1573
  title: "Open a new ticket",
1574
1574
  footerText: "The support team typically responds within one business day.",
@@ -1606,30 +1606,30 @@ function HelpCenterCreateForm({
1606
1606
  // src/components/tickets/help-center-list.tsx
1607
1607
 
1608
1608
  function HelpCenterList({ toast: toast2 = _chunkLEISUAHFcjs.toast, backButton, title, shell } = {}) {
1609
- const identity = _chunkG45RGWHFcjs.useChatIdentity.call(void 0, );
1609
+ const identity = _chunk353GRCTEcjs.useChatIdentity.call(void 0, );
1610
1610
  const searchParams = _chunkSADRZ4YIcjs.useSearchParams.call(void 0, );
1611
1611
  const router = _chunkSADRZ4YIcjs.useRouter.call(void 0, );
1612
1612
  const pathname = _chunkSADRZ4YIcjs.usePathname.call(void 0, );
1613
- const search = searchParams.get(_chunkEGYX55HTcjs.DEV_SECTION_PARAM_KEYS.search) || "";
1613
+ const search = searchParams.get(_chunkI3HBFKKMcjs.DEV_SECTION_PARAM_KEYS.search) || "";
1614
1614
  const status = searchParams.get("status") || "all";
1615
- const ticketParam = searchParams.get(_chunkEGYX55HTcjs.TICKET_OPEN_PARAM) || "";
1615
+ const ticketParam = searchParams.get(_chunkI3HBFKKMcjs.TICKET_OPEN_PARAM) || "";
1616
1616
  const rawPage = Number(searchParams.get("page"));
1617
1617
  const page = Number.isFinite(rawPage) && rawPage > 0 ? Math.floor(rawPage) : 1;
1618
1618
  if (identity.isLoading) {
1619
1619
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1620
- _chunk5CHW7AMPcjs.DevSectionPage,
1620
+ _chunk3BQESV5Gcjs.DevSectionPage,
1621
1621
  {
1622
1622
  sectionKey: "tickets",
1623
1623
  backButton,
1624
1624
  title,
1625
1625
  shell,
1626
1626
  preControls: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpCenterCreateFormSkeleton, {}),
1627
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DevCardRowSkeletonList, {})
1627
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DevCardRowSkeletonList, {})
1628
1628
  }
1629
1629
  );
1630
1630
  }
1631
1631
  if (identity.authTier === "anon" || !_optionalChain([identity, 'access', _66 => _66.user, 'optionalAccess', _67 => _67.email])) {
1632
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DevSectionPage, { sectionKey: "tickets", backButton, title, shell, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1632
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DevSectionPage, { sectionKey: "tickets", backButton, title, shell, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1633
1633
  _chunkS4CLML75cjs.EmptyState,
1634
1634
  {
1635
1635
  type: "generic",
@@ -1681,8 +1681,8 @@ function HelpCenterListAuthed({
1681
1681
  const setOpenTicket = _react.useCallback.call(void 0,
1682
1682
  (externalId) => {
1683
1683
  const params = new URLSearchParams(searchParams.toString());
1684
- if (externalId) params.set(_chunkEGYX55HTcjs.TICKET_OPEN_PARAM, externalId);
1685
- else params.delete(_chunkEGYX55HTcjs.TICKET_OPEN_PARAM);
1684
+ if (externalId) params.set(_chunkI3HBFKKMcjs.TICKET_OPEN_PARAM, externalId);
1685
+ else params.delete(_chunkI3HBFKKMcjs.TICKET_OPEN_PARAM);
1686
1686
  const qs = params.toString();
1687
1687
  router.replace(qs ? `${pathname}?${qs}` : pathname, { scroll: false });
1688
1688
  },
@@ -1759,13 +1759,13 @@ function HelpCenterListAuthed({
1759
1759
  ] }),
1760
1760
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYHNIPSG6cjs.Button, { type: "button", variant: "accent", onClick: () => refetch(), children: "Retry" })
1761
1761
  ] }),
1762
- !error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DevCardRowSkeletonList, {}) : !hasResults && isFetching ? (
1762
+ !error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DevCardRowSkeletonList, {}) : !hasResults && isFetching ? (
1763
1763
  // Bridge state — background refetch in flight and the
1764
1764
  // optimistic placeholder was just removed by the mutation
1765
1765
  // callback. Without this branch "No tickets yet" would flash
1766
1766
  // for ~50ms between `removeOptimistic` and the server
1767
1767
  // response landing.
1768
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DevCardRowSkeletonList, { rows: 1 })
1768
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DevCardRowSkeletonList, { rows: 1 })
1769
1769
  ) : !hasResults ? hasActiveFilters ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1770
1770
  _chunkS4CLML75cjs.EmptyState,
1771
1771
  {
@@ -1801,11 +1801,11 @@ function HelpCenterListAuthed({
1801
1801
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full overflow-clip rounded-[6px] border border-ods-border bg-ods-card", children: merged.map((ticket) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1802
1802
  HelpCenterCard,
1803
1803
  {
1804
- id: _chunkEGYX55HTcjs.devSectionAnchorId.call(void 0, "ticket", ticket.external_id),
1804
+ id: _chunkI3HBFKKMcjs.devSectionAnchorId.call(void 0, "ticket", ticket.external_id),
1805
1805
  ticket,
1806
1806
  expanded: expandedTicketId === ticket.id,
1807
1807
  onToggle: toggleRow,
1808
- busy: _chunkMENQLD57cjs.isOptimistic.call(void 0, ticket) ? false : actions.isRowBusy(ticket.id),
1808
+ busy: _chunkCQHFRJSGcjs.isOptimistic.call(void 0, ticket) ? false : actions.isRowBusy(ticket.id),
1809
1809
  supportSystemDown,
1810
1810
  onSendMessage: actions.sendMessage,
1811
1811
  onClose: actions.closeTicket,
@@ -1819,7 +1819,7 @@ function HelpCenterListAuthed({
1819
1819
  ) }),
1820
1820
  !error && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS4CLML75cjs.UnifiedPagination, { currentPage: page, totalPages })
1821
1821
  ] });
1822
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk5CHW7AMPcjs.DevSectionPage, { sectionKey: "tickets", backButton, title, shell, preControls: form, children: body });
1822
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3BQESV5Gcjs.DevSectionPage, { sectionKey: "tickets", backButton, title, shell, preControls: form, children: body });
1823
1823
  }
1824
1824
 
1825
1825
 
@@ -1838,4 +1838,4 @@ function HelpCenterListAuthed({
1838
1838
 
1839
1839
 
1840
1840
  exports.useTicketActions = useTicketActions; exports.mapTicketActionError = mapTicketActionError; exports.useTicketsList = useTicketsList; exports.TicketOpenForm = TicketOpenForm; exports.useTicketEngagements = useTicketEngagements; exports.TicketLinkedDeliveryCard = TicketLinkedDeliveryCard; exports.TicketReplyComposer = TicketReplyComposer; exports.TicketDetailDrawer = TicketDetailDrawer; exports.TicketRow = TicketRow; exports.TicketCenter = TicketCenter; exports.HelpCenterCard = HelpCenterCard; exports.HelpCenterCreateFormSkeleton = HelpCenterCreateFormSkeleton; exports.HelpCenterCreateForm = HelpCenterCreateForm; exports.HelpCenterList = HelpCenterList;
1841
- //# sourceMappingURL=chunk-JDINUWND.cjs.map
1841
+ //# sourceMappingURL=chunk-2MY6BT6P.cjs.map