@flamingo-stack/openframe-frontend-core 0.0.315 → 0.0.316

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 (163) hide show
  1. package/dist/{chunk-7U4YFQX2.js → chunk-2Y4DLBFO.js} +96 -92
  2. package/dist/{chunk-7U4YFQX2.js.map → chunk-2Y4DLBFO.js.map} +1 -1
  3. package/dist/{chunk-HATCNFQL.cjs → chunk-4MCMPYEM.cjs} +12 -12
  4. package/dist/{chunk-HATCNFQL.cjs.map → chunk-4MCMPYEM.cjs.map} +1 -1
  5. package/dist/{chunk-VY5YF4B7.js → chunk-4NVA6W3J.js} +27 -22
  6. package/dist/chunk-4NVA6W3J.js.map +1 -0
  7. package/dist/chunk-4V3TCOFC.cjs +394 -0
  8. package/dist/chunk-4V3TCOFC.cjs.map +1 -0
  9. package/dist/{chunk-A2H6TFS4.cjs → chunk-63A53WQN.cjs} +33 -33
  10. package/dist/{chunk-A2H6TFS4.cjs.map → chunk-63A53WQN.cjs.map} +1 -1
  11. package/dist/{chunk-6W54MBU2.js → chunk-64DZ2J7Q.js} +5 -5
  12. package/dist/{chunk-47JZOP7Y.js → chunk-6KERXOFE.js} +3 -3
  13. package/dist/{chunk-JALO4TAZ.js → chunk-AI5X5JTD.js} +4 -4
  14. package/dist/chunk-CSLMCBZV.js +1464 -0
  15. package/dist/chunk-CSLMCBZV.js.map +1 -0
  16. package/dist/{chunk-BSAFGQVW.cjs → chunk-CUNMBP3A.cjs} +13 -13
  17. package/dist/{chunk-BSAFGQVW.cjs.map → chunk-CUNMBP3A.cjs.map} +1 -1
  18. package/dist/{chunk-TVNILN2F.cjs → chunk-DHVL36CA.cjs} +40 -40
  19. package/dist/{chunk-TVNILN2F.cjs.map → chunk-DHVL36CA.cjs.map} +1 -1
  20. package/dist/chunk-FCEVVNWY.cjs +1916 -0
  21. package/dist/chunk-FCEVVNWY.cjs.map +1 -0
  22. package/dist/chunk-FOVX3W3C.cjs +1464 -0
  23. package/dist/chunk-FOVX3W3C.cjs.map +1 -0
  24. package/dist/{chunk-4D37W55K.js → chunk-GHVVOST5.js} +95 -116
  25. package/dist/chunk-GHVVOST5.js.map +1 -0
  26. package/dist/{chunk-TRSDXD23.js → chunk-JAZM3A7E.js} +2 -2
  27. package/dist/{chunk-TK6OABYF.js → chunk-JEBL5PQK.js} +21 -35
  28. package/dist/{chunk-TK6OABYF.js.map → chunk-JEBL5PQK.js.map} +1 -1
  29. package/dist/{chunk-5ATH263N.cjs → chunk-L5JSGNT3.cjs} +35 -35
  30. package/dist/{chunk-5ATH263N.cjs.map → chunk-L5JSGNT3.cjs.map} +1 -1
  31. package/dist/{chunk-TQ7CMFSY.cjs → chunk-LAMDFGE3.cjs} +41 -36
  32. package/dist/chunk-LAMDFGE3.cjs.map +1 -0
  33. package/dist/{chunk-V4IIBNTA.js → chunk-LQHMXPOJ.js} +5 -5
  34. package/dist/{chunk-LGLPNWS6.cjs → chunk-LWNPMLIH.cjs} +3 -3
  35. package/dist/{chunk-LGLPNWS6.cjs.map → chunk-LWNPMLIH.cjs.map} +1 -1
  36. package/dist/chunk-M3NULYCR.js +1916 -0
  37. package/dist/chunk-M3NULYCR.js.map +1 -0
  38. package/dist/{chunk-MOOV4ORG.js → chunk-OKGZK6TT.js} +3 -3
  39. package/dist/{chunk-WFHNXCI3.cjs → chunk-OLEW7FYZ.cjs} +123 -144
  40. package/dist/chunk-OLEW7FYZ.cjs.map +1 -0
  41. package/dist/chunk-PIJ4JLJU.js +394 -0
  42. package/dist/chunk-PIJ4JLJU.js.map +1 -0
  43. package/dist/{chunk-E4CQ4RUG.js → chunk-Q4AMYLKX.js} +11 -11
  44. package/dist/{chunk-FQOTC3UU.cjs → chunk-QJGRP2YE.cjs} +4 -4
  45. package/dist/{chunk-FQOTC3UU.cjs.map → chunk-QJGRP2YE.cjs.map} +1 -1
  46. package/dist/{chunk-ZPK5HW7B.cjs → chunk-UGDGUO26.cjs} +3 -3
  47. package/dist/{chunk-ZPK5HW7B.cjs.map → chunk-UGDGUO26.cjs.map} +1 -1
  48. package/dist/{chunk-QW6OL4NY.cjs → chunk-VCE3ZEN3.cjs} +5 -5
  49. package/dist/{chunk-QW6OL4NY.cjs.map → chunk-VCE3ZEN3.cjs.map} +1 -1
  50. package/dist/{chunk-2JPSWDSM.cjs → chunk-XAQJ4ZLY.cjs} +447 -443
  51. package/dist/{chunk-2JPSWDSM.cjs.map → chunk-XAQJ4ZLY.cjs.map} +1 -1
  52. package/dist/{chunk-2MLMZAK4.js → chunk-YFGDZFUG.js} +4 -4
  53. package/dist/{chunk-VFIWQGJZ.js → chunk-Z3YORGG4.js} +2 -2
  54. package/dist/{chunk-OSEKWT6X.cjs → chunk-ZYGVJXJ5.cjs} +33 -47
  55. package/dist/chunk-ZYGVJXJ5.cjs.map +1 -0
  56. package/dist/components/case-studies/index.cjs +18 -18
  57. package/dist/components/case-studies/index.cjs.map +1 -1
  58. package/dist/components/case-studies/index.js +8 -8
  59. package/dist/components/chat/index.cjs +8 -8
  60. package/dist/components/chat/index.js +7 -7
  61. package/dist/components/contact/index.cjs +9 -9
  62. package/dist/components/contact/index.js +8 -8
  63. package/dist/components/docs/doc-viewer.d.ts +4 -0
  64. package/dist/components/docs/doc-viewer.d.ts.map +1 -1
  65. package/dist/components/docs/index.cjs +11 -11
  66. package/dist/components/docs/index.js +10 -10
  67. package/dist/components/embeds/index.cjs +9 -9
  68. package/dist/components/embeds/index.js +8 -8
  69. package/dist/components/faq/faq-document-page.d.ts +18 -20
  70. package/dist/components/faq/faq-document-page.d.ts.map +1 -1
  71. package/dist/components/faq/index.cjs +10 -10
  72. package/dist/components/faq/index.js +9 -9
  73. package/dist/components/features/index.cjs +8 -8
  74. package/dist/components/features/index.js +7 -7
  75. package/dist/components/help-center-pages/delivery-page.d.ts +27 -0
  76. package/dist/components/help-center-pages/delivery-page.d.ts.map +1 -0
  77. package/dist/components/help-center-pages/index.cjs +164 -0
  78. package/dist/components/help-center-pages/index.cjs.map +1 -0
  79. package/dist/components/help-center-pages/index.d.ts +25 -0
  80. package/dist/components/help-center-pages/index.d.ts.map +1 -0
  81. package/dist/components/help-center-pages/index.js +164 -0
  82. package/dist/components/help-center-pages/index.js.map +1 -0
  83. package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts +41 -0
  84. package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts.map +1 -0
  85. package/dist/components/help-center-pages/product-releases-list-page.d.ts +34 -0
  86. package/dist/components/help-center-pages/product-releases-list-page.d.ts.map +1 -0
  87. package/dist/components/help-center-pages/roadmap-page.d.ts +40 -0
  88. package/dist/components/help-center-pages/roadmap-page.d.ts.map +1 -0
  89. package/dist/components/icons/index.cjs +3 -3
  90. package/dist/components/icons/index.js +2 -2
  91. package/dist/components/index.cjs +177 -1555
  92. package/dist/components/index.cjs.map +1 -1
  93. package/dist/components/index.js +348 -1726
  94. package/dist/components/index.js.map +1 -1
  95. package/dist/components/layout/page-layout.d.ts +4 -1
  96. package/dist/components/layout/page-layout.d.ts.map +1 -1
  97. package/dist/components/layout/title-block.d.ts +5 -1
  98. package/dist/components/layout/title-block.d.ts.map +1 -1
  99. package/dist/components/navigation/index.cjs +8 -8
  100. package/dist/components/navigation/index.js +7 -7
  101. package/dist/components/onboarding-guides/index.cjs +15 -364
  102. package/dist/components/onboarding-guides/index.cjs.map +1 -1
  103. package/dist/components/onboarding-guides/index.js +20 -369
  104. package/dist/components/onboarding-guides/index.js.map +1 -1
  105. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +9 -1
  106. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  107. package/dist/components/related-content/index.cjs +10 -10
  108. package/dist/components/related-content/index.js +9 -9
  109. package/dist/components/shared/dev-section/dev-section-page.d.ts +7 -1
  110. package/dist/components/shared/dev-section/dev-section-page.d.ts.map +1 -1
  111. package/dist/components/shared/dev-section/dev-section-view.d.ts +7 -1
  112. package/dist/components/shared/dev-section/dev-section-view.d.ts.map +1 -1
  113. package/dist/components/shared/legal-document/legal-document-page.d.ts +5 -1
  114. package/dist/components/shared/legal-document/legal-document-page.d.ts.map +1 -1
  115. package/dist/components/shared/product-release/release-detail-page.d.ts +11 -2
  116. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  117. package/dist/components/tickets/help-center-list.d.ts +5 -1
  118. package/dist/components/tickets/help-center-list.d.ts.map +1 -1
  119. package/dist/components/tickets/index.cjs +15 -1882
  120. package/dist/components/tickets/index.cjs.map +1 -1
  121. package/dist/components/tickets/index.js +28 -1895
  122. package/dist/components/tickets/index.js.map +1 -1
  123. package/dist/components/ui/file-manager/index.cjs +53 -53
  124. package/dist/components/ui/file-manager/index.cjs.map +1 -1
  125. package/dist/components/ui/file-manager/index.js +4 -4
  126. package/dist/components/ui/index.cjs +8 -8
  127. package/dist/components/ui/index.cjs.map +1 -1
  128. package/dist/components/ui/index.js +7 -7
  129. package/dist/hooks/index.cjs +5 -5
  130. package/dist/hooks/index.js +4 -4
  131. package/dist/index.cjs +10 -10
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.js +9 -9
  134. package/package.json +7 -1
  135. package/src/components/docs/doc-viewer.tsx +21 -34
  136. package/src/components/faq/faq-document-page.tsx +33 -60
  137. package/src/components/help-center-pages/delivery-page.tsx +45 -0
  138. package/src/components/help-center-pages/index.ts +41 -0
  139. package/src/components/help-center-pages/onboarding-guides-catalog-page.tsx +66 -0
  140. package/src/components/help-center-pages/product-releases-list-page.tsx +58 -0
  141. package/src/components/help-center-pages/roadmap-page.tsx +68 -0
  142. package/src/components/layout/page-layout.tsx +11 -0
  143. package/src/components/layout/title-block.tsx +15 -2
  144. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +30 -19
  145. package/src/components/shared/dev-section/dev-section-page.tsx +29 -19
  146. package/src/components/shared/dev-section/dev-section-view.tsx +26 -19
  147. package/src/components/shared/legal-document/legal-document-page.tsx +19 -23
  148. package/src/components/shared/product-release/release-detail-page.tsx +36 -36
  149. package/src/components/tickets/help-center-list.tsx +11 -3
  150. package/dist/chunk-4D37W55K.js.map +0 -1
  151. package/dist/chunk-OSEKWT6X.cjs.map +0 -1
  152. package/dist/chunk-TQ7CMFSY.cjs.map +0 -1
  153. package/dist/chunk-VY5YF4B7.js.map +0 -1
  154. package/dist/chunk-WFHNXCI3.cjs.map +0 -1
  155. /package/dist/{chunk-6W54MBU2.js.map → chunk-64DZ2J7Q.js.map} +0 -0
  156. /package/dist/{chunk-47JZOP7Y.js.map → chunk-6KERXOFE.js.map} +0 -0
  157. /package/dist/{chunk-JALO4TAZ.js.map → chunk-AI5X5JTD.js.map} +0 -0
  158. /package/dist/{chunk-TRSDXD23.js.map → chunk-JAZM3A7E.js.map} +0 -0
  159. /package/dist/{chunk-V4IIBNTA.js.map → chunk-LQHMXPOJ.js.map} +0 -0
  160. /package/dist/{chunk-MOOV4ORG.js.map → chunk-OKGZK6TT.js.map} +0 -0
  161. /package/dist/{chunk-E4CQ4RUG.js.map → chunk-Q4AMYLKX.js.map} +0 -0
  162. /package/dist/{chunk-2MLMZAK4.js.map → chunk-YFGDZFUG.js.map} +0 -0
  163. /package/dist/{chunk-VFIWQGJZ.js.map → chunk-Z3YORGG4.js.map} +0 -0
@@ -0,0 +1,1464 @@
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
+
3
+
4
+
5
+
6
+
7
+ var _chunkLAMDFGE3cjs = require('./chunk-LAMDFGE3.cjs');
8
+
9
+
10
+ var _chunkVCE3ZEN3cjs = require('./chunk-VCE3ZEN3.cjs');
11
+
12
+
13
+ var _chunkUGDGUO26cjs = require('./chunk-UGDGUO26.cjs');
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ var _chunkXAQJ4ZLYcjs = require('./chunk-XAQJ4ZLY.cjs');
43
+
44
+
45
+
46
+
47
+ var _chunkL5JSGNT3cjs = require('./chunk-L5JSGNT3.cjs');
48
+
49
+
50
+ var _chunkN2DVKXN4cjs = require('./chunk-N2DVKXN4.cjs');
51
+
52
+
53
+
54
+
55
+
56
+ var _chunkG7UE6RKVcjs = require('./chunk-G7UE6RKV.cjs');
57
+
58
+
59
+
60
+ var _chunkWBR7H6E3cjs = require('./chunk-WBR7H6E3.cjs');
61
+
62
+
63
+ var _chunkLWNPMLIHcjs = require('./chunk-LWNPMLIH.cjs');
64
+
65
+
66
+
67
+ var _chunkFIG2RKZFcjs = require('./chunk-FIG2RKZF.cjs');
68
+
69
+
70
+ var _chunkVRHGVLSLcjs = require('./chunk-VRHGVLSL.cjs');
71
+
72
+ // src/components/persistent-pagination.tsx
73
+ _chunkFIG2RKZFcjs.init_cn.call(void 0, );
74
+ var _jsxruntime = require('react/jsx-runtime');
75
+ function PersistentPagination({
76
+ isLoading,
77
+ children,
78
+ currentPage,
79
+ totalPages,
80
+ className,
81
+ disabledOpacity = 0.5,
82
+ transitionDuration = 300,
83
+ showLoadingState = true
84
+ }) {
85
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
86
+ "div",
87
+ {
88
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
89
+ "relative transition-all ease-in-out",
90
+ "flex justify-center items-center",
91
+ isLoading && "pointer-events-none",
92
+ className
93
+ ),
94
+ style: {
95
+ opacity: isLoading ? disabledOpacity : 1,
96
+ transitionDuration: `${transitionDuration}ms`
97
+ },
98
+ role: "navigation",
99
+ "aria-label": "Pagination",
100
+ "aria-busy": isLoading,
101
+ "data-loading": isLoading,
102
+ children: [
103
+ isLoading && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
104
+ "div",
105
+ {
106
+ className: "sr-only",
107
+ role: "status",
108
+ "aria-live": "polite",
109
+ children: [
110
+ "Pagination temporarily disabled while loading page ",
111
+ currentPage,
112
+ " of ",
113
+ totalPages
114
+ ]
115
+ }
116
+ ),
117
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
118
+ "div",
119
+ {
120
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
121
+ "relative transition-all ease-in-out",
122
+ isLoading && "cursor-not-allowed"
123
+ ),
124
+ style: {
125
+ transitionDuration: `${transitionDuration}ms`
126
+ },
127
+ "aria-hidden": isLoading,
128
+ children
129
+ }
130
+ )
131
+ ]
132
+ }
133
+ );
134
+ }
135
+ function usePaginationLoading(isLoading, currentPage, totalPages) {
136
+ const shouldShowPagination = totalPages > 1 || isLoading;
137
+ const paginationProps = {
138
+ "aria-busy": isLoading,
139
+ "data-loading": isLoading,
140
+ "data-current-page": currentPage,
141
+ "data-total-pages": totalPages
142
+ };
143
+ const getLoadingMessage = () => {
144
+ if (isLoading) {
145
+ return `Loading page ${currentPage} of ${totalPages}`;
146
+ }
147
+ return `Page ${currentPage} of ${totalPages}`;
148
+ };
149
+ return {
150
+ shouldShowPagination,
151
+ paginationProps,
152
+ getLoadingMessage
153
+ };
154
+ }
155
+ function PersistentPaginationWrapper({
156
+ isLoading,
157
+ currentPage,
158
+ totalPages,
159
+ onPageChange,
160
+ className,
161
+ variant = "vendor"
162
+ }) {
163
+ const { getLoadingMessage } = usePaginationLoading(
164
+ isLoading,
165
+ currentPage,
166
+ totalPages
167
+ );
168
+ const hasResults = totalPages > 0;
169
+ const displayTotalPages = hasResults ? totalPages : 1;
170
+ const displayCurrentPage = hasResults ? currentPage : 1;
171
+ const isPaginationDisabled = isLoading;
172
+ const hasNoResults = !hasResults && !isLoading;
173
+ const PaginationComponent = (_chunkLAMDFGE3cjs.init_unified_pagination.call(void 0, ), _chunkVRHGVLSLcjs.__toCommonJS.call(void 0, _chunkLAMDFGE3cjs.unified_pagination_exports)).UnifiedPagination;
174
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
175
+ "div",
176
+ {
177
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
178
+ "relative transition-all ease-in-out flex justify-center items-center",
179
+ (isPaginationDisabled || hasNoResults) && "pointer-events-none",
180
+ className
181
+ ),
182
+ style: {
183
+ opacity: isPaginationDisabled ? 0.3 : hasNoResults ? 0.5 : 1,
184
+ transitionDuration: "300ms"
185
+ },
186
+ role: "navigation",
187
+ "aria-label": "Pagination",
188
+ "aria-busy": isLoading,
189
+ "data-loading": isLoading,
190
+ "data-has-results": hasResults,
191
+ children: [
192
+ (isLoading || !hasResults) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
193
+ "div",
194
+ {
195
+ className: "sr-only",
196
+ role: "status",
197
+ "aria-live": "polite",
198
+ children: isLoading ? `Pagination temporarily disabled while loading page ${displayCurrentPage} of ${displayTotalPages}` : `No results available - pagination disabled`
199
+ }
200
+ ),
201
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
202
+ "div",
203
+ {
204
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
205
+ "relative transition-all ease-in-out",
206
+ isPaginationDisabled && "cursor-not-allowed"
207
+ ),
208
+ style: {
209
+ transitionDuration: "300ms"
210
+ },
211
+ "aria-hidden": isPaginationDisabled,
212
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
213
+ PaginationComponent,
214
+ {
215
+ currentPage: displayCurrentPage,
216
+ totalPages: displayTotalPages,
217
+ onPageChange: hasResults ? onPageChange : () => {
218
+ }
219
+ }
220
+ )
221
+ }
222
+ )
223
+ ]
224
+ }
225
+ );
226
+ }
227
+
228
+ // src/components/shared/product-release/product-releases-view.tsx
229
+ _chunkFIG2RKZFcjs.init_cn.call(void 0, );
230
+
231
+ var DEFAULT_ENDPOINT = "/api/releases";
232
+ var DEFAULT_SEARCH_PARAM_KEY = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.search;
233
+ var DEFAULT_STATUS_PARAM_KEY = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.releaseStatus;
234
+ var DEFAULT_PAGE_PARAM_KEY = "page";
235
+ function ReleaseRow({
236
+ release,
237
+ basePath,
238
+ buildCardProps
239
+ }) {
240
+ const runtime = _chunkN2DVKXN4cjs.useChatRuntime.call(void 0, );
241
+ const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
242
+ const cta = _chunkXAQJ4ZLYcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _2 => _2.composeContentUrl]), {
243
+ type: "product_release",
244
+ slug: release.slug,
245
+ basePath,
246
+ platforms: release.product_release_platforms
247
+ });
248
+ const { target, rel } = _chunkXAQJ4ZLYcjs.useEntityCardLink.call(void 0, { href: cta.href, targetPlatform: cta.targetPlatform });
249
+ const onClick = (e) => {
250
+ if (e.defaultPrevented || _chunkXAQJ4ZLYcjs.isModifierClick.call(void 0, e) || target === "_blank") return;
251
+ e.preventDefault();
252
+ _chunkXAQJ4ZLYcjs.executeNavigationImperative.call(void 0, {
253
+ runtime,
254
+ href: cta.href,
255
+ targetPlatform: cta.targetPlatform,
256
+ fallbackNavigate: router.push
257
+ });
258
+ };
259
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
260
+ _chunkXAQJ4ZLYcjs.ProductReleaseCard,
261
+ {
262
+ size: "lg",
263
+ title: release.title,
264
+ summary: release.summary,
265
+ version: release.version,
266
+ ...buildCardProps(release),
267
+ anchorProps: { href: cta.href, target, rel, onClick }
268
+ }
269
+ );
270
+ }
271
+ function ProductReleasesView({
272
+ endpoint = DEFAULT_ENDPOINT,
273
+ initialData,
274
+ itemsPerPage = 5,
275
+ basePath = "/releases",
276
+ buildCardProps = _chunkXAQJ4ZLYcjs.buildProductReleaseCardProps,
277
+ searchParamKey = DEFAULT_SEARCH_PARAM_KEY,
278
+ statusParamKey = DEFAULT_STATUS_PARAM_KEY,
279
+ pageParamKey = DEFAULT_PAGE_PARAM_KEY,
280
+ className
281
+ } = {}) {
282
+ const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
283
+ const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
284
+ const pathname = _chunkG7UE6RKVcjs.usePathname.call(void 0, );
285
+ const search = searchParams.get(searchParamKey) || "";
286
+ const status = searchParams.get(statusParamKey) || "all";
287
+ const currentPage = Math.max(1, parseInt(searchParams.get(pageParamKey) || "1", 10) || 1);
288
+ const offset = (currentPage - 1) * itemsPerPage;
289
+ const listParams = new URLSearchParams({ limit: String(itemsPerPage), offset: String(offset) });
290
+ if (search) listParams.set(searchParamKey, search);
291
+ if (status && status !== "all") listParams.set(statusParamKey, status);
292
+ const { data, isLoading, error, reload } = _chunkUGDGUO26cjs.useSelfFetch.call(void 0,
293
+ `${endpoint}?${listParams.toString()}`,
294
+ { initialData }
295
+ );
296
+ const releases = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _3 => _3.data]), () => ( []));
297
+ const totalCount = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _4 => _4.count]), () => ( 0));
298
+ const totalPages = Math.ceil(totalCount / itemsPerPage);
299
+ const hasActiveFilters = search !== "" || status !== "all";
300
+ const showEmpty = !isLoading && !error && releases.length === 0;
301
+ const goToPage = (page) => {
302
+ const params = new URLSearchParams(searchParams.toString());
303
+ params.set(pageParamKey, String(page));
304
+ router.replace(`${pathname}?${params.toString()}`, { scroll: false });
305
+ };
306
+ const resetFilters = () => {
307
+ const params = new URLSearchParams(searchParams.toString());
308
+ params.delete(searchParamKey);
309
+ params.delete(statusParamKey);
310
+ params.delete(pageParamKey);
311
+ router.replace(`${pathname}?${params.toString()}`, { scroll: false });
312
+ };
313
+ if (error) {
314
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkFIG2RKZFcjs.cn.call(void 0, "w-full", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.LoadError, { message: "Failed to load releases.", onRetry: reload }) });
315
+ }
316
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkFIG2RKZFcjs.cn.call(void 0, "w-full flex flex-col gap-[40px]", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[600px]", children: showEmpty ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[600px] flex items-center justify-center", children: hasActiveFilters ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
317
+ _chunkLAMDFGE3cjs.EmptyState,
318
+ {
319
+ type: "search",
320
+ title: "No releases found",
321
+ description: "No releases match your current filters. Try adjusting your search or status filter.",
322
+ showCTA: true,
323
+ ctaText: "Reset Filters",
324
+ onCtaClick: resetFilters
325
+ }
326
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
327
+ _chunkLAMDFGE3cjs.EmptyState,
328
+ {
329
+ type: "generic",
330
+ title: "No releases available",
331
+ description: "Check back soon for product updates!",
332
+ showCTA: false
333
+ }
334
+ ) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
335
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex flex-col gap-6", children: Array.from({ length: itemsPerPage }).map((_, i) => {
336
+ const release = releases[i];
337
+ const hasData = !!release;
338
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
339
+ "div",
340
+ {
341
+ style: { visibility: isLoading || hasData ? "visible" : "hidden" },
342
+ children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.ProductReleaseCardSkeleton, { size: "lg" }) : release ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ReleaseRow, { release, basePath, buildCardProps }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.ProductReleaseCardSkeleton, { size: "lg" })
343
+ },
344
+ _nullishCoalesce(_optionalChain([release, 'optionalAccess', _5 => _5.id]), () => ( `slot-${i}`))
345
+ );
346
+ }) }),
347
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-6 md:mt-8 flex justify-center", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-12 m-3 w-64" }) : releases.length > 0 && totalPages > 1 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
348
+ PersistentPaginationWrapper,
349
+ {
350
+ isLoading: false,
351
+ currentPage,
352
+ totalPages,
353
+ onPageChange: goToPage,
354
+ variant: "blog"
355
+ }
356
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-12 m-3 w-64", style: { visibility: "hidden" } }) })
357
+ ] }) }) });
358
+ }
359
+
360
+ // src/components/shared/media-gallery-strip.tsx
361
+ var _react = require('react');
362
+
363
+ function isGalleryImage(mediaType) {
364
+ return mediaType !== "video" && mediaType !== "demo";
365
+ }
366
+ function MediaGalleryStrip({ items, maxDisplay, className }) {
367
+ const [galleryOpen, setGalleryOpen] = _react.useState.call(void 0, false);
368
+ const [galleryIndex, setGalleryIndex] = _react.useState.call(void 0, 0);
369
+ if (!items || items.length === 0) return null;
370
+ const display = typeof maxDisplay === "number" ? items.slice(0, Math.max(0, maxDisplay)) : items;
371
+ const galleryImages = display.filter((m) => isGalleryImage(m.media_type)).map((m) => m.media_url);
372
+ const tileClass = "shrink-0 w-[240px] h-[200px] rounded-md overflow-hidden border border-ods-border bg-black transition-opacity";
373
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
374
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `flex gap-6 overflow-x-auto w-full ${_nullishCoalesce(className, () => ( ""))}`, children: display.map((mediaItem, index) => {
375
+ if (isGalleryImage(mediaItem.media_type)) {
376
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
377
+ "button",
378
+ {
379
+ type: "button",
380
+ className: `${tileClass} cursor-pointer hover:opacity-80`,
381
+ "aria-label": `Open ${mediaItem.title || `media ${index + 1}`} in gallery`,
382
+ onClick: () => {
383
+ setGalleryIndex(display.slice(0, index).filter((m) => isGalleryImage(m.media_type)).length);
384
+ setGalleryOpen(true);
385
+ },
386
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: mediaItem.media_url, alt: mediaItem.title || `Media ${index + 1}`, className: "w-full h-full object-cover" })
387
+ },
388
+ mediaItem.id || index
389
+ );
390
+ }
391
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: tileClass, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.Video, { url: mediaItem.media_url, layout: "native" }) }, mediaItem.id || index);
392
+ }) }),
393
+ galleryImages.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
394
+ _chunkXAQJ4ZLYcjs.ImageGalleryModal,
395
+ {
396
+ images: galleryImages,
397
+ isOpen: galleryOpen,
398
+ onClose: () => setGalleryOpen(false),
399
+ initialIndex: galleryIndex
400
+ }
401
+ )
402
+ ] });
403
+ }
404
+
405
+ // src/components/shared/product-release/release-detail-page.tsx
406
+ _chunkWBR7H6E3cjs.init_next_link.call(void 0, );
407
+ _chunkG7UE6RKVcjs.init_next_navigation.call(void 0, );
408
+
409
+ var _lucidereact = require('lucide-react');
410
+
411
+ var DefaultMarkdownRenderer = _chunkXAQJ4ZLYcjs.RichMarkdownRenderer;
412
+ function ReleaseDetailPage({
413
+ authorHref,
414
+ slug,
415
+ initialData,
416
+ useRelease,
417
+ MarkdownRenderer = DefaultMarkdownRenderer,
418
+ RoadmapSection,
419
+ DeliverySection,
420
+ VideoSection,
421
+ VideoDisplaySection,
422
+ roadmapApiEndpoint = "/api/roadmap",
423
+ deliveryApiEndpoint = "/api/delivery",
424
+ backButton,
425
+ relatedContent,
426
+ shell = true
427
+ }) {
428
+ const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
429
+ const renderShell = (node) => shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.PageShell, { children: node }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: node });
430
+ const { data: fetchedRelease, error, isLoading } = useRelease(initialData ? void 0 : slug);
431
+ const release = initialData || fetchedRelease;
432
+ const showBackButton = backButton !== false;
433
+ const backLabel = _nullishCoalesce((backButton ? backButton.label : void 0), () => ( "Back to home"));
434
+ const backHref = _nullishCoalesce((backButton ? backButton.href : void 0), () => ( "/"));
435
+ const [roadmapTasks, setRoadmapTasks] = _react.useState.call(void 0, []);
436
+ const [deliveryData, setDeliveryData] = _react.useState.call(void 0, null);
437
+ const [roadmapLoading, setRoadmapLoading] = _react.useState.call(void 0, false);
438
+ const [deliveryLoading, setDeliveryLoading] = _react.useState.call(void 0, false);
439
+ _react.useEffect.call(void 0, () => {
440
+ async function fetchLinkedTasks() {
441
+ if (!release) return;
442
+ try {
443
+ const roadmapTasksData = release.clickup_roadmap_tasks;
444
+ if (roadmapTasksData && roadmapTasksData.length > 0 && RoadmapSection) {
445
+ setRoadmapLoading(true);
446
+ const roadmapIds = roadmapTasksData.map((t) => t.clickup_task_id).join(",");
447
+ const roadmapResponse = await _chunkL5JSGNT3cjs.contentFetch.call(void 0, `${roadmapApiEndpoint}?task_ids=${roadmapIds}`);
448
+ const roadmapData = await roadmapResponse.json();
449
+ setRoadmapTasks(roadmapData.items || []);
450
+ setRoadmapLoading(false);
451
+ }
452
+ const deliveryTasksData = release.clickup_delivery_tasks;
453
+ if (deliveryTasksData && deliveryTasksData.length > 0 && DeliverySection) {
454
+ setDeliveryLoading(true);
455
+ const deliveryIds = deliveryTasksData.map((t) => t.clickup_task_id).join(",");
456
+ const deliveryResponse = await _chunkL5JSGNT3cjs.contentFetch.call(void 0, `${deliveryApiEndpoint}?task_ids=${deliveryIds}`);
457
+ const deliveryResponseData = await deliveryResponse.json();
458
+ setDeliveryData(deliveryResponseData);
459
+ setDeliveryLoading(false);
460
+ }
461
+ } catch (err) {
462
+ console.error("Error fetching linked tasks:", err);
463
+ setRoadmapLoading(false);
464
+ setDeliveryLoading(false);
465
+ }
466
+ }
467
+ fetchLinkedTasks();
468
+ }, [release, RoadmapSection, DeliverySection, roadmapApiEndpoint, deliveryApiEndpoint]);
469
+ if (!initialData && isLoading) {
470
+ return renderShell(
471
+ // Match the loaded page's top offset (TitleBlock's
472
+ // `pt-[var(--spacing-system-l)]`) so content doesn't jump on load.
473
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVCE3ZEN3cjs.DetailPageSkeleton, { bare: true, metadataColumns: 4, showImageGallery: true }) })
474
+ );
475
+ }
476
+ if (error || !release) {
477
+ return renderShell(
478
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center py-16", children: [
479
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "text-4xl font-bold text-ods-text-primary mb-4", children: "Release Not Found" }),
480
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xl text-ods-text-secondary", children: "The release you're looking for doesn't exist." })
481
+ ] })
482
+ );
483
+ }
484
+ const hasBreakingChanges = Array.isArray(release.breaking_changes) && release.breaking_changes.length > 0;
485
+ const releaseTitle = release.title;
486
+ const releaseVersion = release.version;
487
+ const releaseSummary = release.summary;
488
+ const releaseContent = release.content;
489
+ const releaseDate = release.release_date;
490
+ const releaseType = release.release_type;
491
+ const releaseStatus = release.release_status;
492
+ const releaseMedia = release.release_media;
493
+ const author = release.author;
494
+ const githubReleases = release.github_releases;
495
+ const knowledgeBaseLinks = release.knowledge_base_links;
496
+ const migrationGuideUrl = release.migration_guide_url;
497
+ const documentationUrl = release.documentation_url;
498
+ const youtubeUrl = release.youtube_url;
499
+ const mainVideoUrl = release.main_video_url;
500
+ const videoBites = release.video_bites;
501
+ const highlightVideoUrl = release.highlight_video_url;
502
+ const highlightVideoThumbnail = release.highlight_video_thumbnail;
503
+ const breakingChanges = release.breaking_changes;
504
+ const featuresAdded = release.features_added;
505
+ const bugFixed = release.bugs_fixed;
506
+ const improvements = release.improvements;
507
+ return renderShell(
508
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
509
+ _chunkXAQJ4ZLYcjs.PageLayout,
510
+ {
511
+ title: releaseTitle,
512
+ subtitle: `Version: ${releaseVersion}`,
513
+ titleSize: "h1",
514
+ backButton: showBackButton ? { label: backLabel, onClick: () => router.push(backHref) } : void 0,
515
+ children: [
516
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-6 md:space-y-8", children: [
517
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.EntityTagBadges, { tags: release.product_release_tags }),
518
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-1 md:grid-cols-4 border border-ods-border rounded-md overflow-hidden w-full", children: [
519
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border-b md:border-b-0 md:border-r border-ods-border p-4 flex flex-col gap-3", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-0", children: [
520
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h4 text-ods-text-primary", children: releaseType.toLocaleUpperCase() }),
521
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "font-['DM_Sans'] font-medium text-[14px] leading-[20px] text-ods-text-secondary", children: "Release Type" })
522
+ ] }) }),
523
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border-b md:border-b-0 md:border-r border-ods-border p-4 flex flex-col gap-3", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-0", children: [
524
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h4 text-ods-text-primary", children: releaseStatus.toLocaleUpperCase() }),
525
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "font-['DM_Sans'] font-medium text-[14px] leading-[20px] text-ods-text-secondary", children: "Release Status" })
526
+ ] }) }),
527
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border-b md:border-b-0 md:border-r border-ods-border p-4 flex flex-col gap-3", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-0", children: [
528
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h4 text-ods-text-primary", children: _chunkXAQJ4ZLYcjs.formatReleaseDate.call(void 0, releaseDate) }),
529
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "font-['DM_Sans'] font-medium text-[14px] leading-[20px] text-ods-text-secondary", children: "Release Date" })
530
+ ] }) }),
531
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
532
+ _chunkXAQJ4ZLYcjs.EntityMetadataAuthorCell,
533
+ {
534
+ author: _nullishCoalesce(author, () => ( { full_name: null, avatar_url: null })),
535
+ authorHref: _optionalChain([author, 'optionalAccess', _6 => _6.full_name]) ? authorHref : void 0
536
+ }
537
+ )
538
+ ] }),
539
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MediaGalleryStrip, { items: _nullishCoalesce(releaseMedia, () => ( [])), maxDisplay: 5 }),
540
+ releaseSummary && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-h4 text-ods-text-primary", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: releaseSummary }) }),
541
+ VideoDisplaySection ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
542
+ VideoDisplaySection,
543
+ {
544
+ mainVideoUrl,
545
+ youtubeUrl,
546
+ highlightVideoUrl,
547
+ highlightVideoThumbnail,
548
+ title: releaseTitle,
549
+ videoBites,
550
+ bitesTitle: "Video Clips",
551
+ filterPublishedBites: true,
552
+ srtContent: _optionalChain([release, 'optionalAccess', _7 => _7.srt_content]),
553
+ captionsUrl: _optionalChain([release, 'optionalAccess', _8 => _8.captionsUrl])
554
+ }
555
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
556
+ youtubeUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
557
+ _chunkXAQJ4ZLYcjs.Video,
558
+ {
559
+ kind: "youtube",
560
+ url: youtubeUrl,
561
+ title: `${releaseTitle} - Video`,
562
+ layout: "native"
563
+ }
564
+ ),
565
+ !youtubeUrl && mainVideoUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
566
+ _chunkXAQJ4ZLYcjs.Video,
567
+ {
568
+ url: mainVideoUrl,
569
+ srtContent: _optionalChain([release, 'optionalAccess', _9 => _9.srt_content]),
570
+ captionsUrl: _optionalChain([release, 'optionalAccess', _10 => _10.captionsUrl]),
571
+ layout: "centered"
572
+ }
573
+ ),
574
+ highlightVideoUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
575
+ _chunkXAQJ4ZLYcjs.Video,
576
+ {
577
+ url: highlightVideoUrl,
578
+ poster: highlightVideoThumbnail,
579
+ layout: "centered"
580
+ }
581
+ )
582
+ ] }),
583
+ releaseContent && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-h4 text-ods-text-primary", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownRenderer, { content: releaseContent }) }),
584
+ hasBreakingChanges && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.Card, { className: "border-red-500 bg-red-500/10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.CardContent, { className: "p-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
585
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.AlertTriangle, { className: "h-6 w-6 text-red-500" }),
586
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
587
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "font-bold text-red-500 text-lg", children: "Breaking Changes" }),
588
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary", children: "This release contains breaking changes. Review carefully before upgrading." })
589
+ ] })
590
+ ] }) }) }),
591
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
592
+ _chunkXAQJ4ZLYcjs.ReleaseChangelogSection,
593
+ {
594
+ title: "Breaking Changes",
595
+ entries: breakingChanges || [],
596
+ isBreaking: true,
597
+ hideTitle: true,
598
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.AlertTriangle, { className: "h-6 w-6" }),
599
+ SimpleMarkdownRenderer: MarkdownRenderer
600
+ }
601
+ ),
602
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
603
+ _chunkXAQJ4ZLYcjs.ReleaseChangelogSection,
604
+ {
605
+ title: "Features Added",
606
+ entries: featuresAdded || [],
607
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Sparkles, { className: "h-6 w-6" }),
608
+ previewFirst: true,
609
+ SimpleMarkdownRenderer: MarkdownRenderer
610
+ }
611
+ ),
612
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
613
+ _chunkXAQJ4ZLYcjs.ReleaseChangelogSection,
614
+ {
615
+ title: "Bugs Fixed",
616
+ entries: bugFixed || [],
617
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Wrench, { className: "h-6 w-6" }),
618
+ previewFirst: true,
619
+ SimpleMarkdownRenderer: MarkdownRenderer
620
+ }
621
+ ),
622
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
623
+ _chunkXAQJ4ZLYcjs.ReleaseChangelogSection,
624
+ {
625
+ title: "Improvements",
626
+ entries: improvements || [],
627
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.TrendingUp, { className: "h-6 w-6" }),
628
+ previewFirst: true,
629
+ SimpleMarkdownRenderer: MarkdownRenderer
630
+ }
631
+ ),
632
+ !VideoDisplaySection && VideoSection && videoBites && videoBites.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
633
+ VideoSection,
634
+ {
635
+ bites: videoBites,
636
+ title: "Video Clips",
637
+ filterPublished: true
638
+ }
639
+ ),
640
+ RoadmapSection && (roadmapLoading || roadmapTasks.length > 0) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4 w-full", children: [
641
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h5 tracking-[-0.28px] text-ods-text-secondary", children: "Related Roadmap Items" }),
642
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
643
+ RoadmapSection,
644
+ {
645
+ items: roadmapTasks,
646
+ isLoading: roadmapLoading,
647
+ onItemUpdate: (updatedItem) => {
648
+ setRoadmapTasks(
649
+ (prevTasks) => prevTasks.map(
650
+ (task) => task.id === updatedItem.id ? updatedItem : task
651
+ )
652
+ );
653
+ }
654
+ }
655
+ )
656
+ ] }),
657
+ DeliverySection && (deliveryLoading || deliveryData && (deliveryData.completed.length > 0 || deliveryData.inProgress.length > 0)) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full space-y-4", children: [
658
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h5 tracking-[-0.28px] text-ods-text-secondary", children: "Related Enhancements and Bug-fixes" }),
659
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
660
+ DeliverySection,
661
+ {
662
+ data: deliveryData,
663
+ isLoading: deliveryLoading
664
+ }
665
+ )
666
+ ] }),
667
+ (_optionalChain([githubReleases, 'optionalAccess', _11 => _11.length]) || _optionalChain([knowledgeBaseLinks, 'optionalAccess', _12 => _12.length]) || migrationGuideUrl || documentationUrl) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-1 w-full", children: [
668
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-h5 tracking-[-0.28px] text-ods-text-secondary", children: "Related Links" }),
669
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.Card, { className: "bg-ods-card border-ods-border p-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
670
+ githubReleases && githubReleases.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: githubReleases.map((ghRelease) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-1", children: [
671
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLWNPMLIHcjs.GitHubIcon, { className: "shrink-0", width: 24, height: 24, color: "var(--color-text-secondary)" }),
672
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-h4 text-ods-text-primary", children: "Github Release" }),
673
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
674
+ "a",
675
+ {
676
+ href: ghRelease.github_release_url,
677
+ target: "_blank",
678
+ rel: "noopener noreferrer",
679
+ className: "text-h4 text-[#ffc008] hover:underline",
680
+ children: ghRelease.github_release_url.split("/").pop()
681
+ }
682
+ ),
683
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "h-6 w-6 text-[#ffc008] shrink-0" })
684
+ ] }, ghRelease.id)) }),
685
+ knowledgeBaseLinks && knowledgeBaseLinks.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: knowledgeBaseLinks.map((linkObj) => {
686
+ const path = typeof linkObj === "string" ? linkObj : linkObj.kb_article_path;
687
+ const linkId = typeof linkObj === "string" ? path : linkObj.id || path;
688
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-1", children: [
689
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.BookMarked, { className: "h-6 w-6 text-ods-text-secondary shrink-0" }),
690
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-h4 text-ods-text-primary", children: "Knowledge Base" }),
691
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
692
+ _chunkWBR7H6E3cjs.next_link_default,
693
+ {
694
+ href: path.startsWith("http") ? path : `/knowledge-base${path.startsWith("/") ? "" : "/"}${path}`,
695
+ className: "text-h4 text-[#ffc008] hover:underline",
696
+ children: _optionalChain([path, 'access', _13 => _13.replace, 'call', _14 => _14(/^\//, ""), 'access', _15 => _15.split, 'call', _16 => _16("/"), 'access', _17 => _17.pop, 'call', _18 => _18(), 'optionalAccess', _19 => _19.replace, 'call', _20 => _20(/-/g, " ")]) || "View Article"
697
+ }
698
+ ),
699
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "h-6 w-6 text-[#ffc008] shrink-0" })
700
+ ] }, linkId);
701
+ }) }),
702
+ migrationGuideUrl && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-1", children: [
703
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.BookMarked, { className: "h-6 w-6 text-ods-text-secondary shrink-0" }),
704
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
705
+ "a",
706
+ {
707
+ href: migrationGuideUrl,
708
+ target: "_blank",
709
+ rel: "noopener noreferrer",
710
+ className: "text-h4 text-[#ffc008] hover:underline",
711
+ children: "\u{1F4D6} Migration Guide"
712
+ }
713
+ ),
714
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "h-6 w-6 text-[#ffc008] shrink-0" })
715
+ ] }),
716
+ documentationUrl && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-1", children: [
717
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.BookMarked, { className: "h-6 w-6 text-ods-text-secondary shrink-0" }),
718
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
719
+ "a",
720
+ {
721
+ href: documentationUrl,
722
+ target: "_blank",
723
+ rel: "noopener noreferrer",
724
+ className: "text-h4 text-[#ffc008] hover:underline",
725
+ children: "\u{1F4DA} Documentation"
726
+ }
727
+ ),
728
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "h-6 w-6 text-[#ffc008] shrink-0" })
729
+ ] })
730
+ ] }) })
731
+ ] })
732
+ ] }),
733
+ relatedContent
734
+ ]
735
+ }
736
+ )
737
+ );
738
+ }
739
+
740
+ // src/components/shared/product-release/release-detail-skeleton.tsx
741
+
742
+ function ReleaseDetailSkeleton() {
743
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVCE3ZEN3cjs.DetailPageSkeleton, { metadataColumns: 4, showImageGallery: true });
744
+ }
745
+
746
+ // src/components/shared/roadmap/use-roadmap-voting.ts
747
+
748
+ var DEFAULT_VOTE_ENDPOINT = "/api/roadmap/vote";
749
+ var DEFAULT_STORAGE_KEY = "roadmap_votes_v1";
750
+ function useRoadmapVoting(options = {}) {
751
+ const voteApiEndpoint = _nullishCoalesce(options.voteApiEndpoint, () => ( DEFAULT_VOTE_ENDPOINT));
752
+ const storageKey = _nullishCoalesce(options.storageKey, () => ( DEFAULT_STORAGE_KEY));
753
+ const [votes, setVotes] = _react.useState.call(void 0, {});
754
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, true);
755
+ _react.useEffect.call(void 0, () => {
756
+ setIsLoading(true);
757
+ setVotes({});
758
+ try {
759
+ const stored = localStorage.getItem(storageKey);
760
+ if (stored) {
761
+ setVotes(JSON.parse(stored));
762
+ }
763
+ } catch (error) {
764
+ console.error("[Voting] Error loading votes from localStorage:", error);
765
+ } finally {
766
+ setIsLoading(false);
767
+ }
768
+ }, [storageKey]);
769
+ _react.useEffect.call(void 0, () => {
770
+ if (!isLoading) {
771
+ try {
772
+ localStorage.setItem(storageKey, JSON.stringify(votes));
773
+ } catch (error) {
774
+ console.error("[Voting] Error saving votes to localStorage:", error);
775
+ }
776
+ }
777
+ }, [votes, isLoading, storageKey]);
778
+ const getVote = _react.useCallback.call(void 0,
779
+ (taskId) => {
780
+ return votes[taskId] || null;
781
+ },
782
+ [votes]
783
+ );
784
+ const toggleVote = _react.useCallback.call(void 0,
785
+ async (taskId, voteType) => {
786
+ const currentVote = votes[taskId];
787
+ let newVote = null;
788
+ let action = "add";
789
+ if (currentVote === voteType) {
790
+ newVote = null;
791
+ action = "remove";
792
+ } else {
793
+ if (currentVote) {
794
+ await _chunkL5JSGNT3cjs.contentFetch.call(void 0, voteApiEndpoint, {
795
+ method: "POST",
796
+ headers: { "Content-Type": "application/json" },
797
+ body: JSON.stringify({
798
+ taskId,
799
+ voteType: currentVote,
800
+ action: "remove"
801
+ })
802
+ }).catch((err) => console.error("[Voting] Error removing opposite vote:", err));
803
+ }
804
+ newVote = voteType;
805
+ action = "add";
806
+ }
807
+ setVotes((prev) => ({
808
+ ...prev,
809
+ [taskId]: newVote
810
+ }));
811
+ try {
812
+ const response = await _chunkL5JSGNT3cjs.contentFetch.call(void 0, voteApiEndpoint, {
813
+ method: "POST",
814
+ headers: { "Content-Type": "application/json" },
815
+ body: JSON.stringify({ taskId, voteType, action })
816
+ });
817
+ if (!response.ok) {
818
+ throw new Error("Vote API request failed");
819
+ }
820
+ return { success: true, newVote, action };
821
+ } catch (error) {
822
+ console.error("[Voting] API error:", error);
823
+ setVotes((prev) => ({
824
+ ...prev,
825
+ [taskId]: currentVote
826
+ }));
827
+ return { success: false, newVote: currentVote, action };
828
+ }
829
+ },
830
+ [votes, voteApiEndpoint]
831
+ );
832
+ const clearVotes = _react.useCallback.call(void 0, () => {
833
+ setVotes({});
834
+ localStorage.removeItem(storageKey);
835
+ }, [storageKey]);
836
+ return {
837
+ votes,
838
+ isLoading,
839
+ getVote,
840
+ toggleVote,
841
+ clearVotes
842
+ };
843
+ }
844
+
845
+ // src/components/shared/roadmap/roadmap-grid.tsx
846
+
847
+ _chunkFIG2RKZFcjs.init_cn.call(void 0, );
848
+
849
+ var DEFAULT_BUILD_REFRESH_URL = (taskId) => `/api/roadmap/${taskId}`;
850
+ var BACKLOG = "Backlog";
851
+ function getStatusPriority(status) {
852
+ const s = (status || "").toLowerCase();
853
+ if (s.includes("complete") || s.includes("done")) return 1;
854
+ if (s.includes("working") || s.includes("progress")) return 2;
855
+ if (s.includes("review")) return 3;
856
+ if (s.includes("to do") || s.includes("plan")) return 4;
857
+ return 5;
858
+ }
859
+ function parseQuarterString(q) {
860
+ const match = q.match(/Q(\d+)\s+(\d+)/);
861
+ if (!match) return null;
862
+ return { quarter: parseInt(match[1], 10), year: parseInt(match[2], 10) };
863
+ }
864
+ function compareQuarters(a, b) {
865
+ if (a.year !== b.year) return a.year - b.year;
866
+ return a.quarter - b.quarter;
867
+ }
868
+ function getCurrentQuarter() {
869
+ const now = /* @__PURE__ */ new Date();
870
+ return { quarter: Math.floor(now.getMonth() / 3) + 1, year: now.getFullYear() };
871
+ }
872
+ function computeDefaultExpandedQuarters(quarters, quartersToKeepClosed) {
873
+ const currentQ = getCurrentQuarter();
874
+ const out = [];
875
+ for (const q of quarters) {
876
+ if (q === BACKLOG) continue;
877
+ const parsed = parseQuarterString(q);
878
+ if (!parsed) continue;
879
+ const diff = compareQuarters(parsed, currentQ);
880
+ if (diff >= 0) {
881
+ out.push(q);
882
+ } else {
883
+ const quartersAgo = currentQ.year * 4 + currentQ.quarter - (parsed.year * 4 + parsed.quarter);
884
+ if (quartersAgo < quartersToKeepClosed) out.push(q);
885
+ }
886
+ }
887
+ if (quarters.includes(BACKLOG)) out.push(BACKLOG);
888
+ return out;
889
+ }
890
+ function RoadmapGridSingle({
891
+ items,
892
+ showLeftMargin,
893
+ getVote,
894
+ onVote,
895
+ votingTasks
896
+ }) {
897
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `grid grid-cols-1 md:grid-cols-2 gap-6 ${showLeftMargin ? "md:ml-[120px]" : ""}`, children: items.map((item) => (
898
+ // DOM id + sticky-header scroll offset live ON RoadmapCard's own
899
+ // outer element (no wrapper div). Anchor mirrors
900
+ // `buildDevSectionUrl('roadmap', <id>)` → `#roadmap-<external_id>`;
901
+ // `useScrollToHash` in `roadmap-view.tsx` finds the card by id
902
+ // and scrolls.
903
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
904
+ _chunkXAQJ4ZLYcjs.RoadmapCard,
905
+ {
906
+ item,
907
+ id: _chunkXAQJ4ZLYcjs.devSectionAnchorId.call(void 0, "roadmap", item.id),
908
+ userVote: getVote(item.id),
909
+ onVote: (voteType) => onVote(item.id, voteType),
910
+ isVoting: votingTasks.has(item.id)
911
+ },
912
+ item.id
913
+ )
914
+ )) });
915
+ }
916
+ function RoadmapGrid({
917
+ items,
918
+ onItemUpdate,
919
+ showLeftMargin = true,
920
+ buildRefreshUrl = DEFAULT_BUILD_REFRESH_URL,
921
+ votingOptions,
922
+ groupByQuarter = false,
923
+ hasActiveFilters = false,
924
+ quartersToKeepClosed = 2
925
+ }) {
926
+ const { getVote, toggleVote } = useRoadmapVoting(votingOptions);
927
+ const [votingTasks, setVotingTasks] = _react.useState.call(void 0, /* @__PURE__ */ new Set());
928
+ const handleVote = async (taskId, voteType) => {
929
+ if (votingTasks.has(taskId)) return;
930
+ setVotingTasks((prev) => new Set(prev).add(taskId));
931
+ try {
932
+ const result = await toggleVote(taskId, voteType);
933
+ if (result.success) {
934
+ const response = await _chunkL5JSGNT3cjs.contentFetch.call(void 0, buildRefreshUrl(taskId));
935
+ if (response.ok) {
936
+ const data = await response.json();
937
+ if (data.item && onItemUpdate) onItemUpdate(data.item);
938
+ }
939
+ }
940
+ } finally {
941
+ setVotingTasks((prev) => {
942
+ const next = new Set(prev);
943
+ next.delete(taskId);
944
+ return next;
945
+ });
946
+ }
947
+ };
948
+ const itemsByQuarter = items.reduce((acc, item) => {
949
+ const q = item.quarter || BACKLOG;
950
+ (acc[q] || (acc[q] = [])).push(item);
951
+ return acc;
952
+ }, {});
953
+ for (const q of Object.keys(itemsByQuarter)) {
954
+ itemsByQuarter[q].sort((a, b) => getStatusPriority(a.status) - getStatusPriority(b.status));
955
+ }
956
+ const sortedQuarters = Object.keys(itemsByQuarter).sort((a, b) => {
957
+ if (a === BACKLOG) return 1;
958
+ if (b === BACKLOG) return -1;
959
+ const aD = _nullishCoalesce(parseQuarterString(a), () => ( { quarter: 0, year: 0 }));
960
+ const bD = _nullishCoalesce(parseQuarterString(b), () => ( { quarter: 0, year: 0 }));
961
+ return compareQuarters(aD, bD);
962
+ });
963
+ const sortedQuartersKey = sortedQuarters.join(",");
964
+ const [expandedQuarters, setExpandedQuarters] = _react.useState.call(void 0, []);
965
+ const [isInitialized, setIsInitialized] = _react.useState.call(void 0, false);
966
+ const hasSetInitialState = _react.useRef.call(void 0, false);
967
+ const prevItemsLength = _react.useRef.call(void 0, 0);
968
+ _react.useEffect.call(void 0, () => {
969
+ const itemsJustLoaded = prevItemsLength.current === 0 && items.length > 0;
970
+ prevItemsLength.current = items.length;
971
+ if (sortedQuarters.length > 0 && (!hasSetInitialState.current || itemsJustLoaded)) {
972
+ hasSetInitialState.current = true;
973
+ setExpandedQuarters(
974
+ hasActiveFilters ? [...sortedQuarters] : computeDefaultExpandedQuarters(sortedQuarters, quartersToKeepClosed)
975
+ );
976
+ setIsInitialized(true);
977
+ }
978
+ }, [sortedQuarters.length, items.length]);
979
+ _react.useEffect.call(void 0, () => {
980
+ if (!isInitialized || sortedQuarters.length === 0) return;
981
+ setExpandedQuarters(
982
+ hasActiveFilters ? [...sortedQuarters] : computeDefaultExpandedQuarters(sortedQuarters, quartersToKeepClosed)
983
+ );
984
+ }, [hasActiveFilters, sortedQuartersKey, isInitialized, quartersToKeepClosed]);
985
+ if (items.length === 0) {
986
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
987
+ _chunkLAMDFGE3cjs.EmptyState,
988
+ {
989
+ type: "generic",
990
+ title: "No roadmap items",
991
+ description: "Check back soon for upcoming features and improvements!"
992
+ }
993
+ );
994
+ }
995
+ if (!groupByQuarter) {
996
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
997
+ RoadmapGridSingle,
998
+ {
999
+ items,
1000
+ showLeftMargin,
1001
+ getVote,
1002
+ onVote: handleVote,
1003
+ votingTasks
1004
+ }
1005
+ );
1006
+ }
1007
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1008
+ _chunkXAQJ4ZLYcjs.Accordion,
1009
+ {
1010
+ type: "multiple",
1011
+ value: expandedQuarters,
1012
+ onValueChange: setExpandedQuarters,
1013
+ className: "flex flex-col gap-10",
1014
+ children: sortedQuarters.map((quarter) => {
1015
+ const itemCount = _optionalChain([itemsByQuarter, 'access', _21 => _21[quarter], 'optionalAccess', _22 => _22.length]) || 0;
1016
+ const isExpanded = expandedQuarters.includes(quarter);
1017
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1018
+ _chunkXAQJ4ZLYcjs.AccordionItem,
1019
+ {
1020
+ value: quarter,
1021
+ id: `quarter-${quarter.replace(/\s+/g, "-").toLowerCase()}`,
1022
+ className: "border-0",
1023
+ children: [
1024
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.AccordionTrigger, { className: "w-full p-0 hover:no-underline [&>svg]:h-5 [&>svg]:w-5 [&>svg]:text-ods-text-secondary [&>svg]:ml-auto [&>svg]:shrink-0", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
1025
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1026
+ "h3",
1027
+ {
1028
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
1029
+ "font-['Azeret_Mono'] font-semibold text-[24px] md:text-[28px] lg:text-[32px] leading-[32px] md:leading-[36px] lg:leading-[40px] text-ods-text-primary tracking-[-0.48px] md:tracking-[-0.56px] lg:tracking-[-0.64px] transition-opacity",
1030
+ isExpanded ? "opacity-100" : "opacity-60"
1031
+ ),
1032
+ children: [
1033
+ quarter,
1034
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-accent", children: ":" })
1035
+ ]
1036
+ }
1037
+ ),
1038
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1039
+ "span",
1040
+ {
1041
+ className: _chunkFIG2RKZFcjs.cn.call(void 0,
1042
+ "text-sm font-medium transition-opacity",
1043
+ isExpanded ? "text-ods-text-secondary opacity-100" : "text-ods-text-tertiary opacity-60"
1044
+ ),
1045
+ children: [
1046
+ itemCount,
1047
+ " ",
1048
+ itemCount === 1 ? "item" : "items",
1049
+ isInitialized && !isExpanded && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-2 text-ods-accent", children: "Click to expand" })
1050
+ ]
1051
+ }
1052
+ )
1053
+ ] }) }),
1054
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.AccordionContent, { className: "pt-4 pb-0 overflow-hidden data-[state=closed]:animate-none data-[state=open]:animate-none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1055
+ RoadmapGridSingle,
1056
+ {
1057
+ items: itemsByQuarter[quarter],
1058
+ showLeftMargin,
1059
+ getVote,
1060
+ onVote: handleVote,
1061
+ votingTasks
1062
+ }
1063
+ ) })
1064
+ ]
1065
+ },
1066
+ quarter
1067
+ );
1068
+ })
1069
+ }
1070
+ );
1071
+ }
1072
+
1073
+ // src/components/shared/roadmap/roadmap-grid-skeleton.tsx
1074
+
1075
+ function RoadmapCardSkeleton() {
1076
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "bg-ods-card border border-ods-border rounded-[6px] p-[24px] flex flex-col gap-[16px] min-h-[340px] relative", children: [
1077
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute top-[24px] right-[24px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] w-[80px] bg-ods-border rounded animate-pulse" }) }),
1078
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-[16px] pr-[120px]", children: [
1079
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-[80px] h-[80px] bg-ods-border rounded-lg flex-shrink-0 animate-pulse" }),
1080
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
1081
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[48px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[24px] w-full bg-ods-border rounded animate-pulse" }) }),
1082
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[20px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[14px] w-1/2 bg-ods-border rounded animate-pulse" }) })
1083
+ ] })
1084
+ ] }),
1085
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[72px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full space-y-2", children: [
1086
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[24px] bg-ods-border rounded animate-pulse" }),
1087
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[24px] bg-ods-border rounded animate-pulse" }),
1088
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[24px] w-4/5 bg-ods-border rounded animate-pulse" })
1089
+ ] }) }),
1090
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
1091
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between", children: [
1092
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[48px] w-[120px] bg-ods-border rounded animate-pulse" }),
1093
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[32px] w-[100px] bg-ods-border rounded animate-pulse" })
1094
+ ] })
1095
+ ] });
1096
+ }
1097
+ function RoadmapGridSkeleton({ count = 4, showLeftMargin = true }) {
1098
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `grid grid-cols-1 md:grid-cols-2 gap-6 ${showLeftMargin ? "md:ml-[120px]" : ""}`, children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RoadmapCardSkeleton, {}, i)) });
1099
+ }
1100
+
1101
+ // src/components/shared/roadmap/roadmap-view.tsx
1102
+
1103
+
1104
+ var DEFAULT_ENDPOINT2 = "/api/roadmap";
1105
+ var DEFAULT_SEARCH_PARAM_KEY2 = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.search;
1106
+ var DEFAULT_STATUS_PARAM_KEY2 = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.status;
1107
+ function RoadmapView({
1108
+ endpoint = DEFAULT_ENDPOINT2,
1109
+ initialItems,
1110
+ showLeftMargin,
1111
+ buildRefreshUrl,
1112
+ votingOptions,
1113
+ searchParamKey = DEFAULT_SEARCH_PARAM_KEY2,
1114
+ statusParamKey = DEFAULT_STATUS_PARAM_KEY2
1115
+ } = {}) {
1116
+ const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
1117
+ const search = searchParams.get(searchParamKey) || "";
1118
+ const status = searchParams.get(statusParamKey) || "all";
1119
+ const listParams = new URLSearchParams();
1120
+ if (search) listParams.set(searchParamKey, search);
1121
+ if (status && status !== "all") listParams.set(statusParamKey, status);
1122
+ const qs = listParams.toString();
1123
+ const url = qs ? `${endpoint}?${qs}` : endpoint;
1124
+ const initialData = _react.useMemo.call(void 0, () => initialItems ? { items: initialItems } : void 0, [initialItems]);
1125
+ const { data, setData, isLoading, error, reload } = _chunkUGDGUO26cjs.useSelfFetch.call(void 0,
1126
+ url,
1127
+ { initialData }
1128
+ );
1129
+ const items = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _23 => _23.items]), () => ( []));
1130
+ _chunkL5JSGNT3cjs.useScrollToHash.call(void 0, data, { headerOffset: _chunkL5JSGNT3cjs.STICKY_HEADER_OFFSET_PX });
1131
+ if (error) {
1132
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.LoadError, { message: "Failed to load roadmap.", onRetry: reload });
1133
+ }
1134
+ if (isLoading && !data) {
1135
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RoadmapGridSkeleton, { showLeftMargin });
1136
+ }
1137
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1138
+ RoadmapGrid,
1139
+ {
1140
+ items,
1141
+ showLeftMargin,
1142
+ buildRefreshUrl,
1143
+ votingOptions,
1144
+ groupByQuarter: true,
1145
+ hasActiveFilters: search !== "" || status !== "all",
1146
+ onItemUpdate: (updated) => setData(
1147
+ (prev) => prev ? { ...prev, items: (_nullishCoalesce(prev.items, () => ( []))).map((it) => it.id === updated.id ? updated : it) } : prev
1148
+ )
1149
+ }
1150
+ );
1151
+ }
1152
+
1153
+ // src/components/shared/delivery/delivery-table.tsx
1154
+
1155
+ function SkeletonRow() {
1156
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-b border-ods-border last:border-b-0 p-[12px] md:p-[16px]", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col md:flex-row items-start justify-between gap-[12px] md:gap-[16px] w-full", children: [
1157
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 w-full md:w-auto flex flex-col gap-[12px] md:gap-[16px]", children: [
1158
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[24px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] bg-ods-border rounded animate-pulse w-full" }) }),
1159
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[20px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] bg-ods-border rounded animate-pulse w-1/2" }) }),
1160
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[72px] flex items-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 space-y-1", children: [
1161
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] bg-ods-border rounded animate-pulse w-full" }),
1162
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] bg-ods-border rounded animate-pulse w-full" }),
1163
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[20px] bg-ods-border rounded animate-pulse w-2/3" })
1164
+ ] }) })
1165
+ ] }),
1166
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-shrink-0 self-start flex flex-col gap-2", children: [
1167
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[32px] w-[100px] bg-ods-border rounded animate-pulse" }),
1168
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[32px] w-[120px] bg-ods-border rounded animate-pulse" })
1169
+ ] })
1170
+ ] }) });
1171
+ }
1172
+ function DeliveryTable({ items, isLoading = false }) {
1173
+ if (isLoading) {
1174
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border border-ods-border rounded-[6px] overflow-hidden w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SkeletonRow, {}, i)) }) });
1175
+ }
1176
+ if (items.length === 0) {
1177
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border border-ods-border rounded-[6px] p-[40px] text-center w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-[14px] font-['DM_Sans'] font-medium", children: "No tasks available" }) });
1178
+ }
1179
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-card border border-ods-border rounded-[6px] overflow-hidden w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: items.map((item) => (
1180
+ // DOM id lives on DeliveryRow's own outer element (no wrapper
1181
+ // div). Anchor mirrors `buildDevSectionUrl('delivery', <id>)`
1182
+ // → `#delivery-<external_id>`; `useScrollToHash` in
1183
+ // `delivery-lists.tsx` finds the row by id and scrolls. The
1184
+ // outer wrapper here ONLY exists for the row separators.
1185
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1186
+ "div",
1187
+ {
1188
+ className: "border-b border-ods-border last:border-b-0",
1189
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAMDFGE3cjs.DeliveryRow, { item, id: _chunkXAQJ4ZLYcjs.devSectionAnchorId.call(void 0, "delivery", item.id) })
1190
+ },
1191
+ item.id
1192
+ )
1193
+ )) }) });
1194
+ }
1195
+
1196
+ // src/components/shared/delivery/delivery-lists.tsx
1197
+
1198
+
1199
+ var DEFAULT_COMPLETED_ENDPOINT = "/api/delivery/completed";
1200
+ var DEFAULT_IN_PROGRESS_ENDPOINT = "/api/delivery/in-progress";
1201
+ var DEFAULT_SEARCH_PARAM_KEY3 = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.search;
1202
+ var DEFAULT_TASK_TYPE_PARAM_KEY = _chunkXAQJ4ZLYcjs.DEV_SECTION_PARAM_KEYS.deliveryTaskType;
1203
+ function DeliveryLists({
1204
+ completedApiEndpoint = DEFAULT_COMPLETED_ENDPOINT,
1205
+ inProgressApiEndpoint = DEFAULT_IN_PROGRESS_ENDPOINT,
1206
+ searchParamKey = DEFAULT_SEARCH_PARAM_KEY3,
1207
+ taskTypeParamKey = DEFAULT_TASK_TYPE_PARAM_KEY
1208
+ } = {}) {
1209
+ const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
1210
+ const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
1211
+ const pathname = _chunkG7UE6RKVcjs.usePathname.call(void 0, );
1212
+ const [data, setData] = _react.useState.call(void 0, null);
1213
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, true);
1214
+ const [error, setError] = _react.useState.call(void 0, null);
1215
+ const searchQuery = searchParams.get(searchParamKey) || "";
1216
+ const taskTypeFilter = searchParams.get(taskTypeParamKey) || "all";
1217
+ _react.useEffect.call(void 0, () => {
1218
+ async function fetchDeliveryData() {
1219
+ try {
1220
+ setIsLoading(true);
1221
+ setError(null);
1222
+ const params = new URLSearchParams();
1223
+ if (searchQuery) {
1224
+ params.set(searchParamKey, searchQuery);
1225
+ }
1226
+ if (taskTypeFilter && taskTypeFilter !== "all") {
1227
+ params.set(taskTypeParamKey, taskTypeFilter);
1228
+ }
1229
+ const queryString = params.toString();
1230
+ const queryParam = queryString ? `?${queryString}` : "";
1231
+ const [completedResponse, inProgressResponse] = await Promise.all([
1232
+ _chunkL5JSGNT3cjs.contentFetch.call(void 0, `${completedApiEndpoint}${queryParam}`),
1233
+ _chunkL5JSGNT3cjs.contentFetch.call(void 0, `${inProgressApiEndpoint}${queryParam}`)
1234
+ ]);
1235
+ if (!completedResponse.ok || !inProgressResponse.ok) {
1236
+ throw new Error("Failed to fetch delivery items");
1237
+ }
1238
+ const [completedResult, inProgressResult] = await Promise.all([
1239
+ completedResponse.json(),
1240
+ inProgressResponse.json()
1241
+ ]);
1242
+ setData({
1243
+ completed: completedResult.items || [],
1244
+ inProgress: inProgressResult.items || []
1245
+ });
1246
+ } catch (err) {
1247
+ console.error("Error fetching delivery items:", err);
1248
+ setError("Failed to load delivery items. Please try again later.");
1249
+ } finally {
1250
+ setIsLoading(false);
1251
+ }
1252
+ }
1253
+ fetchDeliveryData();
1254
+ }, [searchQuery, taskTypeFilter, completedApiEndpoint, inProgressApiEndpoint, searchParamKey, taskTypeParamKey]);
1255
+ const filteredCompleted = _optionalChain([data, 'optionalAccess', _24 => _24.completed]) || [];
1256
+ const filteredInProgress = _optionalChain([data, 'optionalAccess', _25 => _25.inProgress]) || [];
1257
+ _chunkL5JSGNT3cjs.useScrollToHash.call(void 0, data, { headerOffset: _chunkL5JSGNT3cjs.STICKY_HEADER_OFFSET_PX });
1258
+ const showCompleted = true;
1259
+ const showInProgress = true;
1260
+ const hasActiveFilters = searchQuery !== "" || taskTypeFilter !== "all";
1261
+ const hasResults = showCompleted && filteredCompleted.length > 0 || showInProgress && filteredInProgress.length > 0;
1262
+ if (error) {
1263
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.LoadError, { message: error, onRetry: () => window.location.reload() }) });
1264
+ }
1265
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full flex flex-col gap-[40px]", children: [
1266
+ !isLoading && !hasResults && (hasActiveFilters ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1267
+ _chunkLAMDFGE3cjs.EmptyState,
1268
+ {
1269
+ type: "search",
1270
+ title: "No tasks found",
1271
+ description: "No tasks match your current filters. Try adjusting your search or status filter.",
1272
+ showCTA: true,
1273
+ ctaText: "Reset Filters",
1274
+ onCtaClick: () => {
1275
+ const params = new URLSearchParams(searchParams.toString());
1276
+ params.delete(searchParamKey);
1277
+ params.delete(taskTypeParamKey);
1278
+ router.replace(`${pathname}?${params.toString()}`, { scroll: false });
1279
+ }
1280
+ }
1281
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1282
+ _chunkLAMDFGE3cjs.EmptyState,
1283
+ {
1284
+ type: "generic",
1285
+ title: "No tasks available",
1286
+ description: "Check back soon for upcoming tasks!",
1287
+ showCTA: false
1288
+ }
1289
+ )),
1290
+ showCompleted && (hasResults || isLoading) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full", children: [
1291
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "h3", { className: "text-h2 text-ods-text-primary tracking-[-0.48px] md:tracking-[-0.56px] lg:tracking-[-0.64px] mb-4", children: [
1292
+ "Recently Completed",
1293
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-accent", children: ":" })
1294
+ ] }),
1295
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1296
+ DeliveryTable,
1297
+ {
1298
+ items: filteredCompleted,
1299
+ isLoading
1300
+ }
1301
+ )
1302
+ ] }),
1303
+ showInProgress && (hasResults || isLoading) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full", children: [
1304
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "h3", { className: "text-h2 text-ods-text-primary tracking-[-0.48px] md:tracking-[-0.56px] lg:tracking-[-0.64px] mb-4", children: [
1305
+ "Active Tasks",
1306
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-accent", children: ":" })
1307
+ ] }),
1308
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1309
+ DeliveryTable,
1310
+ {
1311
+ items: filteredInProgress,
1312
+ isLoading
1313
+ }
1314
+ )
1315
+ ] })
1316
+ ] });
1317
+ }
1318
+
1319
+ // src/components/shared/legal-document/use-legal-docs.ts
1320
+
1321
+ function useLegalDocs(docType, options = {}) {
1322
+ const { initialData = null, apiEndpoint } = options;
1323
+ const effectiveEndpoint = _nullishCoalesce(apiEndpoint, () => ( `/api/legal/${docType}`));
1324
+ const [data, setData] = _react.useState.call(void 0, _nullishCoalesce(initialData, () => ( null)));
1325
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, !initialData);
1326
+ const [error, setError] = _react.useState.call(void 0, null);
1327
+ const fetchDocument = _react.useCallback.call(void 0, async () => {
1328
+ try {
1329
+ setIsLoading(true);
1330
+ setError(null);
1331
+ const response = await _chunkL5JSGNT3cjs.contentFetch.call(void 0, effectiveEndpoint);
1332
+ if (!response.ok) {
1333
+ throw new Error(
1334
+ `Failed to fetch ${docType} document: ${response.status} ${response.statusText}`
1335
+ );
1336
+ }
1337
+ const result = await response.json();
1338
+ if (!result.content) {
1339
+ throw new Error(`${docType} document content is empty`);
1340
+ }
1341
+ setData(result);
1342
+ } catch (err) {
1343
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
1344
+ console.error("Error fetching legal document:", docType, err);
1345
+ setError(errorMessage);
1346
+ } finally {
1347
+ setIsLoading(false);
1348
+ }
1349
+ }, [docType, effectiveEndpoint]);
1350
+ _react.useEffect.call(void 0, () => {
1351
+ setData(_nullishCoalesce(initialData, () => ( null)));
1352
+ setError(null);
1353
+ setIsLoading(!initialData);
1354
+ }, [docType, initialData]);
1355
+ _react.useEffect.call(void 0, () => {
1356
+ if (initialData) return;
1357
+ fetchDocument();
1358
+ }, [fetchDocument, initialData]);
1359
+ const refetch = () => {
1360
+ fetchDocument();
1361
+ };
1362
+ return {
1363
+ data,
1364
+ isLoading,
1365
+ error,
1366
+ refetch
1367
+ };
1368
+ }
1369
+
1370
+ // src/components/shared/legal-document/legal-document-page.tsx
1371
+ _chunkG7UE6RKVcjs.init_next_navigation.call(void 0, );
1372
+
1373
+ function LegalDocumentPage({
1374
+ docType,
1375
+ title,
1376
+ fallbackDescription,
1377
+ contactEmail,
1378
+ errorContactPrompt,
1379
+ errorTitle,
1380
+ emptyStateMessage,
1381
+ initialData = null,
1382
+ initialLastUpdatedLabel = null,
1383
+ apiEndpoint,
1384
+ MarkdownRenderer = _chunkXAQJ4ZLYcjs.RichMarkdownRenderer,
1385
+ backButton,
1386
+ shell = true
1387
+ }) {
1388
+ const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
1389
+ const { data, isLoading, error } = useLegalDocs(docType, { initialData, apiEndpoint });
1390
+ const backCfg = backButton === false ? void 0 : {
1391
+ label: _nullishCoalesce(_optionalChain([backButton, 'optionalAccess', _26 => _26.label]), () => ( "Back to home")),
1392
+ onClick: () => router.push(_nullishCoalesce(_optionalChain([backButton, 'optionalAccess', _27 => _27.href]), () => ( "/")))
1393
+ };
1394
+ const fallbackLastUpdatedLabel = _optionalChain([data, 'optionalAccess', _28 => _28.lastSynced]) != null ? _chunkXAQJ4ZLYcjs.formatLegalDate.call(void 0, data.lastSynced) : null;
1395
+ const effectiveLastUpdatedLabel = _nullishCoalesce(initialLastUpdatedLabel, () => ( fallbackLastUpdatedLabel));
1396
+ const subtitle = effectiveLastUpdatedLabel ? `Last Updated: ${effectiveLastUpdatedLabel}` : fallbackDescription;
1397
+ const inner = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkXAQJ4ZLYcjs.PageLayout, { title, subtitle, backButton: backCfg, titleSize: "h1", children: [
1398
+ _optionalChain([data, 'optionalAccess', _29 => _29.sourceFile]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "font-['DM_Sans'] text-sm text-ods-text-secondary opacity-75", children: [
1399
+ "Source: ",
1400
+ data.sourceFile
1401
+ ] }),
1402
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex flex-col lg:flex-row gap-6 lg:gap-10 items-start flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "article", { className: "space-y-2", children: isLoading ? (
1403
+ // Loading skeleton matching Knowledge Hub pattern
1404
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-6", children: [
1405
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-ods-skeleton rounded-lg w-3/4 animate-pulse" }),
1406
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
1407
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-ods-skeleton rounded w-full animate-pulse" }),
1408
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-ods-skeleton rounded w-full animate-pulse" }),
1409
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-ods-skeleton rounded w-5/6 animate-pulse" })
1410
+ ] }),
1411
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-32 bg-ods-card border border-ods-border rounded-lg animate-pulse" }),
1412
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
1413
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-ods-skeleton rounded w-full animate-pulse" }),
1414
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-ods-skeleton rounded w-4/5 animate-pulse" })
1415
+ ] })
1416
+ ] })
1417
+ ) : error ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center space-y-4", children: [
1418
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "bg-red-900/20 border border-red-700 rounded-lg p-6", children: [
1419
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-400 mb-2", children: errorTitle }),
1420
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-300 text-sm", children: error })
1421
+ ] }),
1422
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-ods-text-secondary", children: [
1423
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: errorContactPrompt }),
1424
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: `mailto:${contactEmail}`, className: "text-ods-accent hover:underline", children: contactEmail })
1425
+ ] })
1426
+ ] }) : data ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1427
+ MarkdownRenderer,
1428
+ {
1429
+ content: data.content,
1430
+ sectionIds: data.sections || [],
1431
+ demoteMarkdownH1ToH2: true
1432
+ }
1433
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center text-ods-text-secondary py-16", children: [
1434
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xl", children: emptyStateMessage }),
1435
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "mt-2", children: [
1436
+ "Please contact",
1437
+ " ",
1438
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: `mailto:${contactEmail}`, className: "text-ods-accent hover:underline", children: contactEmail }),
1439
+ " ",
1440
+ "for more information."
1441
+ ] })
1442
+ ] }) }) }) }) })
1443
+ ] });
1444
+ return shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXAQJ4ZLYcjs.PageShell, { children: inner }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: inner });
1445
+ }
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+ exports.PersistentPagination = PersistentPagination; exports.usePaginationLoading = usePaginationLoading; exports.PersistentPaginationWrapper = PersistentPaginationWrapper; exports.ProductReleasesView = ProductReleasesView; exports.MediaGalleryStrip = MediaGalleryStrip; exports.ReleaseDetailPage = ReleaseDetailPage; exports.ReleaseDetailSkeleton = ReleaseDetailSkeleton; exports.useRoadmapVoting = useRoadmapVoting; exports.RoadmapGrid = RoadmapGrid; exports.RoadmapGridSkeleton = RoadmapGridSkeleton; exports.RoadmapView = RoadmapView; exports.DeliveryTable = DeliveryTable; exports.DeliveryLists = DeliveryLists; exports.useLegalDocs = useLegalDocs; exports.LegalDocumentPage = LegalDocumentPage;
1464
+ //# sourceMappingURL=chunk-FOVX3W3C.cjs.map