@flamingo-stack/openframe-frontend-core 0.0.582-1967.5390.1 → 0.0.582

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 (115) hide show
  1. package/dist/chunk-2EIGO6ZS.js +1055 -0
  2. package/dist/chunk-2EIGO6ZS.js.map +1 -0
  3. package/dist/{chunk-PDK6KVU6.js → chunk-53ZVUW2M.js} +4 -4
  4. package/dist/{chunk-BTXJQPGE.js → chunk-5U2FU5LM.js} +2 -2
  5. package/dist/{chunk-VG2SRECA.cjs → chunk-7WE6FGGK.cjs} +49 -49
  6. package/dist/{chunk-VG2SRECA.cjs.map → chunk-7WE6FGGK.cjs.map} +1 -1
  7. package/dist/{chunk-EXBNO6FB.js → chunk-CJW6KZD3.js} +2 -2
  8. package/dist/{chunk-UQXQCM3F.cjs → chunk-E4TK2BBD.cjs} +3 -3
  9. package/dist/{chunk-UQXQCM3F.cjs.map → chunk-E4TK2BBD.cjs.map} +1 -1
  10. package/dist/{chunk-NOO3QOJI.js → chunk-EULY3BXB.js} +2 -2
  11. package/dist/{chunk-ML22BIKH.js → chunk-GAL6EXUY.js} +3 -3
  12. package/dist/{chunk-YTZK2ORN.js → chunk-H7K76TPX.js} +4 -4
  13. package/dist/{chunk-RH7EY7YN.cjs → chunk-HMEEW73F.cjs} +1978 -237
  14. package/dist/chunk-HMEEW73F.cjs.map +1 -0
  15. package/dist/{chunk-KNQZZJYJ.js → chunk-IB23CRL2.js} +2 -2
  16. package/dist/{chunk-GHYWIVSU.cjs → chunk-IVJ6TBVW.cjs} +34 -34
  17. package/dist/{chunk-GHYWIVSU.cjs.map → chunk-IVJ6TBVW.cjs.map} +1 -1
  18. package/dist/{chunk-XJ3Y4OOF.js → chunk-IZGXIZWF.js} +2 -2
  19. package/dist/chunk-JMWLF2GL.cjs +1055 -0
  20. package/dist/chunk-JMWLF2GL.cjs.map +1 -0
  21. package/dist/{chunk-MCFETAH7.js → chunk-JUXCEHK2.js} +2 -2
  22. package/dist/{chunk-KX4F4O26.cjs → chunk-KS7NKONC.cjs} +3 -3
  23. package/dist/{chunk-KX4F4O26.cjs.map → chunk-KS7NKONC.cjs.map} +1 -1
  24. package/dist/{chunk-VYNYJVSE.cjs → chunk-LHQ6RVFE.cjs} +17 -17
  25. package/dist/{chunk-VYNYJVSE.cjs.map → chunk-LHQ6RVFE.cjs.map} +1 -1
  26. package/dist/{chunk-LGHMGCUG.cjs → chunk-M3ERSHPM.cjs} +4 -4
  27. package/dist/{chunk-LGHMGCUG.cjs.map → chunk-M3ERSHPM.cjs.map} +1 -1
  28. package/dist/{chunk-Q7X74UZF.cjs → chunk-RBMVTCRM.cjs} +3 -3
  29. package/dist/{chunk-Q7X74UZF.cjs.map → chunk-RBMVTCRM.cjs.map} +1 -1
  30. package/dist/{chunk-LYU3IZOA.cjs → chunk-RILGQ2OY.cjs} +10 -10
  31. package/dist/{chunk-LYU3IZOA.cjs.map → chunk-RILGQ2OY.cjs.map} +1 -1
  32. package/dist/{chunk-T6DRWYLM.cjs → chunk-RQMS2CF5.cjs} +17 -17
  33. package/dist/{chunk-T6DRWYLM.cjs.map → chunk-RQMS2CF5.cjs.map} +1 -1
  34. package/dist/{chunk-TC47NAJ3.cjs → chunk-S2ZXUQLR.cjs} +16 -16
  35. package/dist/{chunk-TC47NAJ3.cjs.map → chunk-S2ZXUQLR.cjs.map} +1 -1
  36. package/dist/{chunk-G3ZMLSKJ.js → chunk-SM6JAZ4C.js} +2 -2
  37. package/dist/{chunk-LENIASJW.js → chunk-T4DIAKIK.js} +2 -2
  38. package/dist/{chunk-ODOFQLSP.cjs → chunk-TMNFC24G.cjs} +13 -13
  39. package/dist/{chunk-ODOFQLSP.cjs.map → chunk-TMNFC24G.cjs.map} +1 -1
  40. package/dist/{chunk-FVF2MVIT.js → chunk-U6GFESVF.js} +2 -2
  41. package/dist/{chunk-2T7GXHRQ.js → chunk-XA5UPYWE.js} +2745 -1004
  42. package/dist/chunk-XA5UPYWE.js.map +1 -0
  43. package/dist/{chunk-TVLQVTZ6.cjs → chunk-XNSEZVV4.cjs} +4 -4
  44. package/dist/{chunk-TVLQVTZ6.cjs.map → chunk-XNSEZVV4.cjs.map} +1 -1
  45. package/dist/{chunk-XJJ2D64Q.cjs → chunk-YU4QZ6I6.cjs} +3 -3
  46. package/dist/{chunk-XJJ2D64Q.cjs.map → chunk-YU4QZ6I6.cjs.map} +1 -1
  47. package/dist/{chunk-LFG5JG2D.js → chunk-ZSENCE55.js} +5 -5
  48. package/dist/components/case-studies/index.cjs +8 -8
  49. package/dist/components/case-studies/index.js +2 -2
  50. package/dist/components/contact/index.cjs +3 -3
  51. package/dist/components/contact/index.js +2 -2
  52. package/dist/components/docs/index.cjs +6 -6
  53. package/dist/components/docs/index.js +5 -5
  54. package/dist/components/embeds/index.cjs +3 -3
  55. package/dist/components/embeds/index.js +2 -2
  56. package/dist/components/faq/index.cjs +3 -3
  57. package/dist/components/faq/index.js +2 -2
  58. package/dist/components/features/index.cjs +2 -2
  59. package/dist/components/features/index.js +1 -1
  60. package/dist/components/features/push-button-selector.d.ts +29 -1
  61. package/dist/components/features/push-button-selector.d.ts.map +1 -1
  62. package/dist/components/help-center-pages/index.cjs +22 -22
  63. package/dist/components/help-center-pages/index.js +13 -13
  64. package/dist/components/index.cjs +61 -892
  65. package/dist/components/index.cjs.map +1 -1
  66. package/dist/components/index.js +244 -1075
  67. package/dist/components/index.js.map +1 -1
  68. package/dist/components/meeting-scheduler/index.cjs +18 -18
  69. package/dist/components/meeting-scheduler/index.js +1 -1
  70. package/dist/components/navigation/index.cjs +5 -5
  71. package/dist/components/navigation/index.js +4 -4
  72. package/dist/components/onboarding-guides/index.cjs +5 -5
  73. package/dist/components/onboarding-guides/index.js +4 -4
  74. package/dist/components/tickets/index.cjs +6 -6
  75. package/dist/components/tickets/index.js +5 -5
  76. package/dist/components/ui/index.cjs +2 -2
  77. package/dist/components/ui/index.js +1 -1
  78. package/dist/index.cjs +6 -6
  79. package/dist/index.js +5 -5
  80. package/dist/utils/announcement-storage.d.ts +16 -25
  81. package/dist/utils/announcement-storage.d.ts.map +1 -1
  82. package/dist/utils/dismiss-cookie.d.ts +8 -27
  83. package/dist/utils/dismiss-cookie.d.ts.map +1 -1
  84. package/dist/utils/dismissal-storage.d.ts +2 -2
  85. package/dist/utils/dismissal-storage.d.ts.map +1 -1
  86. package/dist/utils/index.cjs +53 -70
  87. package/dist/utils/index.cjs.map +1 -1
  88. package/dist/utils/index.js +53 -70
  89. package/dist/utils/index.js.map +1 -1
  90. package/package.json +1 -1
  91. package/src/components/features/.push-button-selector.md +1 -1
  92. package/src/components/features/push-button-selector.tsx +142 -17
  93. package/src/utils/announcement-storage.ts +16 -25
  94. package/src/utils/dismiss-cookie.ts +9 -86
  95. package/src/utils/dismissal-storage.ts +2 -2
  96. package/dist/chunk-2T7GXHRQ.js.map +0 -1
  97. package/dist/chunk-FWNIZC6A.js +0 -1867
  98. package/dist/chunk-FWNIZC6A.js.map +0 -1
  99. package/dist/chunk-IHFTLVDF.cjs +0 -1867
  100. package/dist/chunk-IHFTLVDF.cjs.map +0 -1
  101. package/dist/chunk-RH7EY7YN.cjs.map +0 -1
  102. package/src/utils/__tests__/dismiss-cookie.test.ts +0 -133
  103. /package/dist/{chunk-PDK6KVU6.js.map → chunk-53ZVUW2M.js.map} +0 -0
  104. /package/dist/{chunk-BTXJQPGE.js.map → chunk-5U2FU5LM.js.map} +0 -0
  105. /package/dist/{chunk-EXBNO6FB.js.map → chunk-CJW6KZD3.js.map} +0 -0
  106. /package/dist/{chunk-NOO3QOJI.js.map → chunk-EULY3BXB.js.map} +0 -0
  107. /package/dist/{chunk-ML22BIKH.js.map → chunk-GAL6EXUY.js.map} +0 -0
  108. /package/dist/{chunk-YTZK2ORN.js.map → chunk-H7K76TPX.js.map} +0 -0
  109. /package/dist/{chunk-KNQZZJYJ.js.map → chunk-IB23CRL2.js.map} +0 -0
  110. /package/dist/{chunk-XJ3Y4OOF.js.map → chunk-IZGXIZWF.js.map} +0 -0
  111. /package/dist/{chunk-MCFETAH7.js.map → chunk-JUXCEHK2.js.map} +0 -0
  112. /package/dist/{chunk-G3ZMLSKJ.js.map → chunk-SM6JAZ4C.js.map} +0 -0
  113. /package/dist/{chunk-LENIASJW.js.map → chunk-T4DIAKIK.js.map} +0 -0
  114. /package/dist/{chunk-FVF2MVIT.js.map → chunk-U6GFESVF.js.map} +0 -0
  115. /package/dist/{chunk-LFG5JG2D.js.map → chunk-ZSENCE55.js.map} +0 -0
@@ -1,1867 +0,0 @@
1
- "use client";
2
- import {
3
- FileDownloadCard,
4
- GoogleSheetsViewer,
5
- PdfViewer
6
- } from "./chunk-EXBNO6FB.js";
7
- import {
8
- MobileNavigationDropdown,
9
- MultiLevelNavigation,
10
- StickySectionNav
11
- } from "./chunk-NOO3QOJI.js";
12
- import {
13
- DocSearchBar,
14
- useDocSearch
15
- } from "./chunk-KNQZZJYJ.js";
16
- import {
17
- DEFAULT_FOLDER_INDEX_FILE,
18
- FigmaEmbed,
19
- PageLayout,
20
- PageShell,
21
- findDocNodeByPath,
22
- getDocAncestorNodeIds,
23
- stripFolderIndexFromPath
24
- } from "./chunk-2T7GXHRQ.js";
25
- import {
26
- apiErrorMessage
27
- } from "./chunk-T5HDPHN6.js";
28
- import {
29
- contentFetch
30
- } from "./chunk-E4NCHSOE.js";
31
- import {
32
- HUB_HEADER_OFFSET_PX,
33
- navigateSamePageHash,
34
- scrollElementIntoView
35
- } from "./chunk-JRYS4VMV.js";
36
- import {
37
- useRouter
38
- } from "./chunk-XXMHLZ3Y.js";
39
- import {
40
- useChatRuntime
41
- } from "./chunk-RYXIRVDC.js";
42
- import {
43
- cn
44
- } from "./chunk-4CTHP7E5.js";
45
-
46
- // src/components/docs/doc-viewer.tsx
47
- import { useMemo as useMemo3 } from "react";
48
-
49
- // src/components/loading/unified-skeleton.tsx
50
- import { jsx } from "react/jsx-runtime";
51
- function UnifiedSkeleton({
52
- className,
53
- variant = "default",
54
- width,
55
- height,
56
- animate = true,
57
- "aria-label": ariaLabel,
58
- ...props
59
- }) {
60
- const baseClasses = "bg-ods-skeleton";
61
- const variantClasses = {
62
- default: "rounded-md",
63
- text: "rounded-sm",
64
- circular: "rounded-full",
65
- rectangular: "rounded-none"
66
- };
67
- const defaultHeights = {
68
- default: "h-4",
69
- text: "h-4",
70
- circular: "h-12 w-12",
71
- rectangular: "h-4"
72
- };
73
- const animationClasses = animate ? "animate-pulse motion-reduce:animate-none" : "";
74
- const style = {
75
- width,
76
- height
77
- };
78
- return /* @__PURE__ */ jsx(
79
- "div",
80
- {
81
- className: cn(
82
- baseClasses,
83
- variantClasses[variant],
84
- !height && !style.height && defaultHeights[variant],
85
- !width && !style.width && variant !== "circular" && "w-full",
86
- animationClasses,
87
- className
88
- ),
89
- style,
90
- role: "status",
91
- "aria-label": ariaLabel || "Loading content",
92
- ...props
93
- }
94
- );
95
- }
96
- var TextSkeleton = {
97
- /**
98
- * Large heading skeleton (h1, h2)
99
- */
100
- Heading: ({ className, ...props }) => /* @__PURE__ */ jsx(
101
- UnifiedSkeleton,
102
- {
103
- variant: "text",
104
- className: cn("h-8 md:h-10 lg:h-12", className),
105
- "aria-label": "Loading heading",
106
- ...props
107
- }
108
- ),
109
- /**
110
- * Medium heading skeleton (h3, h4)
111
- */
112
- Subheading: ({ className, ...props }) => /* @__PURE__ */ jsx(
113
- UnifiedSkeleton,
114
- {
115
- variant: "text",
116
- className: cn("h-6 md:h-7 lg:h-8", className),
117
- "aria-label": "Loading subheading",
118
- ...props
119
- }
120
- ),
121
- /**
122
- * Body text skeleton
123
- */
124
- Body: ({ className, ...props }) => /* @__PURE__ */ jsx(UnifiedSkeleton, { variant: "text", className: cn("h-4 md:h-5", className), "aria-label": "Loading text", ...props }),
125
- /**
126
- * Small text skeleton (captions, metadata)
127
- */
128
- Caption: ({ className, ...props }) => /* @__PURE__ */ jsx(UnifiedSkeleton, { variant: "text", className: cn("h-3 md:h-4", className), "aria-label": "Loading caption", ...props })
129
- };
130
- var InteractiveSkeleton = {
131
- /**
132
- * Button skeleton with proper touch targets
133
- */
134
- Button: ({ className, ...props }) => /* @__PURE__ */ jsx(
135
- UnifiedSkeleton,
136
- {
137
- variant: "default",
138
- className: cn("h-10 w-32 md:h-12 md:w-40", className),
139
- "aria-label": "Loading button",
140
- ...props
141
- }
142
- ),
143
- /**
144
- * Input field skeleton
145
- */
146
- Input: ({ className, ...props }) => /* @__PURE__ */ jsx(
147
- UnifiedSkeleton,
148
- {
149
- variant: "default",
150
- className: cn("h-10 w-full md:h-12", className),
151
- "aria-label": "Loading input field",
152
- ...props
153
- }
154
- ),
155
- /**
156
- * Filter chip skeleton
157
- */
158
- Chip: ({ className, ...props }) => /* @__PURE__ */ jsx(
159
- UnifiedSkeleton,
160
- {
161
- variant: "default",
162
- className: cn("h-8 w-20 rounded-full", className),
163
- "aria-label": "Loading filter",
164
- ...props
165
- }
166
- )
167
- };
168
- var MediaSkeleton = {
169
- /**
170
- * Avatar/profile image skeleton
171
- */
172
- Avatar: ({
173
- size = "md",
174
- className,
175
- ...props
176
- }) => {
177
- const sizeClasses = {
178
- sm: "h-8 w-8",
179
- md: "h-12 w-12",
180
- lg: "h-16 w-16"
181
- };
182
- return /* @__PURE__ */ jsx(
183
- UnifiedSkeleton,
184
- {
185
- variant: "circular",
186
- className: cn(sizeClasses[size], className),
187
- "aria-label": "Loading profile image",
188
- ...props
189
- }
190
- );
191
- },
192
- /**
193
- * Card image skeleton (1200×630 OG aspect — matches entity-cards default
194
- * so loading state never causes a height shift when card data arrives)
195
- */
196
- CardImage: ({ className, ...props }) => /* @__PURE__ */ jsx(
197
- UnifiedSkeleton,
198
- {
199
- variant: "default",
200
- className: cn("aspect-[1200/630] w-full", className),
201
- "aria-label": "Loading image",
202
- ...props
203
- }
204
- ),
205
- /**
206
- * Icon skeleton
207
- */
208
- Icon: ({
209
- size = "md",
210
- className,
211
- ...props
212
- }) => {
213
- const sizeClasses = {
214
- sm: "h-4 w-4",
215
- md: "h-6 w-6",
216
- lg: "h-8 w-8"
217
- };
218
- return /* @__PURE__ */ jsx(
219
- UnifiedSkeleton,
220
- {
221
- variant: "default",
222
- className: cn(sizeClasses[size], className),
223
- "aria-label": "Loading icon",
224
- ...props
225
- }
226
- );
227
- }
228
- };
229
-
230
- // src/components/loading/card-skeleton.tsx
231
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
232
- function CardSkeleton({
233
- className,
234
- containerClassName,
235
- variant = "vendor",
236
- showActions = true,
237
- showMetadata = true,
238
- ...props
239
- }) {
240
- const cardContent = {
241
- vendor: /* @__PURE__ */ jsx2(VendorCardContent, { showMetadata }),
242
- blog: /* @__PURE__ */ jsx2(BlogCardContent, { showActions, showMetadata }),
243
- category: /* @__PURE__ */ jsx2(CategoryCardContent, {}),
244
- alternative: /* @__PURE__ */ jsx2(AlternativeCardContent, { showActions })
245
- };
246
- return /* @__PURE__ */ jsx2(
247
- "div",
248
- {
249
- className: cn(
250
- containerClassName || "border border-ods-border bg-ods-card",
251
- "overflow-hidden rounded-lg",
252
- // Flex layouts for certain variants
253
- variant === "blog" && "flex h-full flex-col",
254
- variant === "vendor" && "flex h-full flex-col",
255
- className
256
- ),
257
- role: "status",
258
- "aria-label": `Loading ${variant} card`,
259
- ...props,
260
- children: cardContent[variant]
261
- }
262
- );
263
- }
264
- function VendorCardContent({ showMetadata }) {
265
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 p-4", children: [
266
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-start gap-3", children: [
267
- /* @__PURE__ */ jsx2("div", { className: "flex h-[60px] w-[60px] flex-shrink-0 items-center justify-center rounded-lg border border-ods-border bg-ods-bg p-2", children: /* @__PURE__ */ jsx2(MediaSkeleton.Avatar, { size: "sm", className: "h-11 w-11" }) }),
268
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center space-y-1 py-2", children: [
269
- /* @__PURE__ */ jsx2(TextSkeleton.Subheading, { className: "w-3/4" }),
270
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-1/2" })
271
- ] })
272
- ] }),
273
- /* @__PURE__ */ jsx2("div", { className: "flex h-12 w-full items-center overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "w-full space-y-1", children: [
274
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-full" }),
275
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-2/3" })
276
- ] }) }),
277
- showMetadata && /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 items-center justify-between gap-2", children: [
278
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-shrink items-center gap-3 md:gap-4", children: [
279
- /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-1", children: [
280
- /* @__PURE__ */ jsx2(MediaSkeleton.Icon, { size: "sm", className: "h-5 w-5" }),
281
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-8" })
282
- ] }),
283
- /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-1", children: [
284
- /* @__PURE__ */ jsx2(MediaSkeleton.Icon, { size: "sm", className: "h-5 w-5" }),
285
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-10" })
286
- ] })
287
- ] }),
288
- /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 rounded border border-ods-border bg-ods-bg px-2.5 py-1.5", children: [
289
- /* @__PURE__ */ jsx2("div", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-sm bg-ods-border", children: /* @__PURE__ */ jsx2(MediaSkeleton.Icon, { size: "sm", className: "h-2.5 w-2.5" }) }),
290
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-16" })
291
- ] }) })
292
- ] })
293
- ] });
294
- }
295
- function BlogCardContent({ showActions, showMetadata }) {
296
- return /* @__PURE__ */ jsxs(Fragment, { children: [
297
- /* @__PURE__ */ jsx2("div", { className: "blog-card-image-container relative aspect-[1200/630] w-full overflow-hidden bg-ods-bg", children: /* @__PURE__ */ jsx2(MediaSkeleton.CardImage, {}) }),
298
- /* @__PURE__ */ jsxs("div", { className: "flex flex-grow flex-col p-4", children: [
299
- /* @__PURE__ */ jsx2("div", { className: "mb-3 flex min-h-[50.4px] items-center md:min-h-[56px] lg:min-h-[61.6px]", children: /* @__PURE__ */ jsxs("div", { className: "w-full space-y-1", children: [
300
- /* @__PURE__ */ jsx2(TextSkeleton.Subheading, { className: "w-full" }),
301
- /* @__PURE__ */ jsx2(TextSkeleton.Subheading, { className: "w-3/4" })
302
- ] }) }),
303
- /* @__PURE__ */ jsxs("div", { className: "mb-3 flex h-[28px] items-center gap-2", children: [
304
- /* @__PURE__ */ jsx2(InteractiveSkeleton.Chip, { className: "w-16" }),
305
- /* @__PURE__ */ jsx2(InteractiveSkeleton.Chip, { className: "w-12" })
306
- ] }),
307
- /* @__PURE__ */ jsx2("div", { className: "mb-3 flex min-h-[42px] items-center md:min-h-[45px] lg:min-h-[48px]", children: /* @__PURE__ */ jsxs("div", { className: "w-full space-y-1", children: [
308
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-full" }),
309
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-1/2" })
310
- ] }) }),
311
- showActions && /* @__PURE__ */ jsx2("div", { className: "pt-2", children: /* @__PURE__ */ jsx2(InteractiveSkeleton.Button, { className: "h-8 w-24" }) }),
312
- showMetadata && /* @__PURE__ */ jsx2("div", { className: "mt-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 border-t border-ods-border pt-4", children: [
313
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
314
- /* @__PURE__ */ jsx2(MediaSkeleton.Avatar, { size: "sm" }),
315
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-16" })
316
- ] }),
317
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3 text-ods-text-muted", children: [
318
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-12" }),
319
- /* @__PURE__ */ jsx2("div", { className: "h-1 w-1 rounded-full bg-ods-skeleton" }),
320
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-16" })
321
- ] })
322
- ] }) })
323
- ] })
324
- ] });
325
- }
326
- function CategoryCardContent() {
327
- return /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-4 md:p-6", children: [
328
- /* @__PURE__ */ jsx2("div", { className: "flex gap-2 md:gap-3", children: Array.from({ length: 6 }).map((_, index) => /* @__PURE__ */ jsx2(MediaSkeleton.Icon, { size: "lg", className: "flex-shrink-0" }, index)) }),
329
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
330
- /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
331
- /* @__PURE__ */ jsx2(TextSkeleton.Subheading, { className: "w-3/4" }),
332
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-1/2" })
333
- ] }),
334
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 md:items-end md:gap-6", children: [
335
- /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
336
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-full" }),
337
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-2/3" })
338
- ] }),
339
- /* @__PURE__ */ jsx2(InteractiveSkeleton.Button, { className: "h-10 w-10 flex-shrink-0 md:h-12 md:w-12" })
340
- ] })
341
- ] })
342
- ] });
343
- }
344
- function AlternativeCardContent({ showActions }) {
345
- return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4 p-4", children: [
346
- /* @__PURE__ */ jsx2(MediaSkeleton.Avatar, { size: "md", className: "flex-shrink-0" }),
347
- /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
348
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
349
- /* @__PURE__ */ jsx2(TextSkeleton.Subheading, { className: "w-1/3" }),
350
- /* @__PURE__ */ jsx2(TextSkeleton.Caption, { className: "w-16" })
351
- ] }),
352
- /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
353
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-full" }),
354
- /* @__PURE__ */ jsx2(TextSkeleton.Body, { className: "w-5/6" })
355
- ] }),
356
- showActions && /* @__PURE__ */ jsx2("div", { className: "pt-2", children: /* @__PURE__ */ jsx2(InteractiveSkeleton.Button, { className: "h-8 w-20" }) })
357
- ] })
358
- ] });
359
- }
360
- function CardSkeletonGrid({
361
- count = 6,
362
- variant = "vendor",
363
- className,
364
- containerClassName,
365
- ...props
366
- }) {
367
- return /* @__PURE__ */ jsx2(
368
- "div",
369
- {
370
- className: cn(
371
- "grid gap-4 md:gap-6",
372
- // Responsive grid based on card type
373
- variant === "vendor" && "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
374
- variant === "blog" && "grid-cols-1 md:grid-cols-2",
375
- variant === "category" && "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
376
- variant === "alternative" && "grid-cols-1",
377
- className
378
- ),
379
- role: "status",
380
- "aria-label": `Loading ${count} ${variant} cards`,
381
- children: Array.from({ length: count }, (_, index) => /* @__PURE__ */ jsx2(CardSkeleton, { variant, containerClassName, ...props }, index))
382
- }
383
- );
384
- }
385
-
386
- // src/components/loading/page-layout-skeleton.tsx
387
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
388
- function AnnouncementBarSkeleton() {
389
- return /* @__PURE__ */ jsx3("div", { className: "relative w-full animate-pulse bg-ods-skeleton", children: /* @__PURE__ */ jsx3("div", { className: "relative flex w-full flex-row items-center", children: /* @__PURE__ */ jsxs2("div", { className: "relative box-border flex w-full flex-row items-center justify-start gap-4 py-3 pl-4 pr-12 md:gap-6 md:py-4 md:pl-6 md:pr-16", children: [
390
- /* @__PURE__ */ jsx3("div", { className: "relative h-6 w-6 shrink-0 rounded bg-ods-border md:h-8 md:w-8" }),
391
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1 space-y-1 md:space-y-2", children: [
392
- /* @__PURE__ */ jsx3("div", { className: "h-[14px] w-3/4 max-w-md rounded bg-ods-border md:h-[18px]" }),
393
- /* @__PURE__ */ jsx3("div", { className: "hidden h-[12px] w-full max-w-lg rounded bg-ods-border md:block md:h-[18px]" })
394
- ] }),
395
- /* @__PURE__ */ jsx3("div", { className: "absolute right-2 top-2 h-6 w-6 rounded bg-ods-border" })
396
- ] }) }) });
397
- }
398
- function HeroSkeleton() {
399
- return /* @__PURE__ */ jsxs2(
400
- "section",
401
- {
402
- className: "flex w-full animate-pulse flex-col items-center justify-center px-4 py-12 text-center md:px-8 md:py-20",
403
- style: {
404
- background: "radial-gradient(circle at 50% 0%, #242323 0%, #1A1A1A 100%)"
405
- },
406
- children: [
407
- /* @__PURE__ */ jsx3(TextSkeleton.Heading, { className: "mb-4 h-12 w-full max-w-4xl md:mb-6 md:h-20 lg:h-24" }),
408
- /* @__PURE__ */ jsxs2("div", { className: "mb-8 w-full max-w-4xl space-y-3 px-2 md:mb-10", children: [
409
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "h-5 md:h-7" }),
410
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "mx-auto h-5 w-3/4 md:h-7" })
411
- ] }),
412
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Button, { className: "h-12 w-full md:w-64" })
413
- ]
414
- }
415
- );
416
- }
417
- function SearchContainerSkeleton({
418
- className,
419
- showFilters = true
420
- }) {
421
- return /* @__PURE__ */ jsxs2("div", { className: cn("space-y-4", className || ""), children: [
422
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 md:gap-4", children: [
423
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Input, { className: "flex-1" }),
424
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Button, { className: "w-32 md:w-40" })
425
- ] }),
426
- showFilters && /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap gap-2", children: [
427
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, {}),
428
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, { className: "w-24" }),
429
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, { className: "w-16" }),
430
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, { className: "w-20" })
431
- ] })
432
- ] });
433
- }
434
- function CategorySidebarSkeleton({ className }) {
435
- const items = [
436
- { type: "file", width: "w-20", hasBadge: false },
437
- { type: "folder", width: "w-24", hasBadge: true },
438
- { type: "folder", width: "w-20", hasBadge: true },
439
- { type: "folder", width: "w-24", hasBadge: true },
440
- { type: "folder", width: "w-16", hasBadge: true },
441
- { type: "folder", width: "w-20", hasBadge: true },
442
- { type: "folder", width: "w-28", hasBadge: true },
443
- { type: "folder", width: "w-16", hasBadge: true },
444
- { type: "folder", width: "w-24", hasBadge: true },
445
- { type: "file", width: "w-28" },
446
- { type: "file", width: "w-36" }
447
- ];
448
- return /* @__PURE__ */ jsxs2("div", { className: cn("w-full lg:w-[320px]", className), children: [
449
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { className: "mb-4 h-[14px] w-24 rounded" }),
450
- /* @__PURE__ */ jsx3("div", { className: "space-y-1.5", children: items.map((item, index) => /* @__PURE__ */ jsxs2(
451
- "div",
452
- {
453
- className: cn(
454
- "flex min-h-[50px] items-center justify-between rounded-lg border border-ods-border px-4 py-4",
455
- index === 0 ? "bg-ods-accent/20" : "bg-ods-card"
456
- ),
457
- children: [
458
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2.5", children: [
459
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { className: "h-4 w-4 shrink-0 rounded" }),
460
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { className: `h-[14px] ${item.width} rounded` })
461
- ] }),
462
- /* @__PURE__ */ jsxs2("div", { className: "flex h-[18px] items-center gap-2", children: [
463
- item.hasBadge && /* @__PURE__ */ jsx3(UnifiedSkeleton, { className: "h-[18px] w-14 rounded" }),
464
- item.type === "folder" && /* @__PURE__ */ jsx3(UnifiedSkeleton, { className: "h-4 w-4 rounded" })
465
- ] })
466
- ]
467
- },
468
- index
469
- )) })
470
- ] });
471
- }
472
- function BreadcrumbSkeleton({ className }) {
473
- return /* @__PURE__ */ jsxs2("div", { className: cn("mb-6 flex items-center space-x-1", className), children: [
474
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-16" }),
475
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { variant: "default", className: "h-4 w-4 rounded-full" }),
476
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-24" }),
477
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { variant: "default", className: "h-4 w-4 rounded-full" }),
478
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-32" }),
479
- /* @__PURE__ */ jsx3(UnifiedSkeleton, { variant: "default", className: "h-4 w-4 rounded-full" }),
480
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-24" })
481
- ] });
482
- }
483
- function ResultsHeaderSkeleton({ className }) {
484
- return /* @__PURE__ */ jsx3("div", { className: cn("mb-6 flex flex-col items-start justify-between gap-4 md:flex-row md:items-center", className), children: /* @__PURE__ */ jsx3("div", { className: "space-y-1", children: /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-48" }) }) });
485
- }
486
- function TwoColumnLayoutSkeleton({
487
- className,
488
- sidebarContent,
489
- mainContent,
490
- sidebarPosition = "left"
491
- }) {
492
- const sidebar = sidebarContent || /* @__PURE__ */ jsx3(CategorySidebarSkeleton, {});
493
- const main = mainContent || /* @__PURE__ */ jsx3(CardSkeletonGrid, { count: 6 });
494
- return /* @__PURE__ */ jsx3(
495
- "div",
496
- {
497
- className: cn(
498
- "grid grid-cols-1 gap-6 lg:grid-cols-[320px_1fr] lg:gap-8",
499
- sidebarPosition === "right" && "lg:grid-cols-[1fr_320px]",
500
- className
501
- ),
502
- children: sidebarPosition === "left" ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
503
- /* @__PURE__ */ jsx3("aside", { className: "order-2 lg:order-1", children: sidebar }),
504
- /* @__PURE__ */ jsx3("main", { className: "order-1 lg:order-2", children: main })
505
- ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
506
- /* @__PURE__ */ jsx3("main", { className: "order-1", children: main }),
507
- /* @__PURE__ */ jsx3("aside", { className: "order-2", children: sidebar })
508
- ] })
509
- }
510
- );
511
- }
512
- function ArticleLayoutSkeleton({ className }) {
513
- return /* @__PURE__ */ jsxs2("article", { className: cn("mx-auto max-w-4xl", className), children: [
514
- /* @__PURE__ */ jsxs2("header", { className: "mb-8 space-y-4 md:mb-12 md:space-y-6", children: [
515
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
516
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, {}),
517
- /* @__PURE__ */ jsx3(InteractiveSkeleton.Chip, { className: "w-16" })
518
- ] }),
519
- /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
520
- /* @__PURE__ */ jsx3(TextSkeleton.Heading, { className: "w-full" }),
521
- /* @__PURE__ */ jsx3(TextSkeleton.Heading, { className: "w-3/4" })
522
- ] }),
523
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-4 border-t border-ods-divider pt-4", children: [
524
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
525
- /* @__PURE__ */ jsx3(MediaSkeleton.Avatar, { size: "sm" }),
526
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-24" })
527
- ] }),
528
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-20" }),
529
- /* @__PURE__ */ jsx3(TextSkeleton.Caption, { className: "w-16" })
530
- ] })
531
- ] }),
532
- /* @__PURE__ */ jsx3("div", { className: "mb-8 md:mb-12", children: /* @__PURE__ */ jsx3(MediaSkeleton.CardImage, { className: "h-64 w-full md:h-96" }) }),
533
- /* @__PURE__ */ jsxs2("div", { className: "prose prose-invert max-w-none space-y-6", children: [
534
- Array.from({ length: 12 }).map((_, index) => /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
535
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-full" }),
536
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-full" }),
537
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-5/6" }),
538
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-3/4" })
539
- ] }, index)),
540
- /* @__PURE__ */ jsxs2("div", { className: "py-4", children: [
541
- /* @__PURE__ */ jsx3(TextSkeleton.Subheading, { className: "mb-4 w-2/3" }),
542
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
543
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-full" }),
544
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-4/5" })
545
- ] })
546
- ] })
547
- ] })
548
- ] });
549
- }
550
- function VendorDetailLayoutSkeleton({ className }) {
551
- return /* @__PURE__ */ jsx3("main", { className: cn("min-h-screen bg-ods-bg", className), children: /* @__PURE__ */ jsxs2("div", { className: "mx-auto max-w-[1920px] px-6 py-6 md:px-20 md:py-10", children: [
552
- /* @__PURE__ */ jsx3(BreadcrumbSkeleton, { className: "mb-6" }),
553
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col lg:flex-row lg:gap-10", children: [
554
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
555
- /* @__PURE__ */ jsxs2("div", { className: "mb-10", children: [
556
- /* @__PURE__ */ jsxs2("div", { className: "mb-6 flex gap-6", children: [
557
- /* @__PURE__ */ jsx3("div", { className: "h-20 w-20 flex-shrink-0 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
558
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
559
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2", children: [
560
- /* @__PURE__ */ jsx3("div", { className: "h-12 w-80 max-w-full animate-pulse rounded bg-ods-skeleton md:h-16 lg:h-20" }),
561
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-32 animate-pulse rounded bg-ods-skeleton md:h-6" })
562
- ] }),
563
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
564
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-20 animate-pulse rounded bg-ods-skeleton" }),
565
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-16 animate-pulse rounded bg-ods-skeleton" })
566
- ] })
567
- ] })
568
- ] }),
569
- /* @__PURE__ */ jsx3("div", { className: "mb-2 h-[300px] w-full animate-pulse rounded-lg border border-ods-border bg-ods-card md:h-[400px] lg:h-[500px]" }),
570
- /* @__PURE__ */ jsx3("div", { className: "text-center", children: /* @__PURE__ */ jsx3("div", { className: "mx-auto h-4 w-24 animate-pulse rounded bg-ods-skeleton" }) })
571
- ] }),
572
- /* @__PURE__ */ jsx3("div", { className: "mb-10 lg:hidden", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
573
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
574
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
575
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
576
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" })
577
- ] }),
578
- /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-lg border border-ods-border", children: [
579
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 bg-ods-card p-4", children: [
580
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-8 animate-pulse rounded bg-ods-skeleton" }),
581
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", children: [
582
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-20 animate-pulse rounded bg-ods-skeleton" }),
583
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-12 animate-pulse rounded bg-ods-skeleton" })
584
- ] })
585
- ] }),
586
- /* @__PURE__ */ jsx3("div", { className: "space-y-3 p-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
587
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-6 animate-pulse rounded bg-ods-skeleton" }),
588
- /* @__PURE__ */ jsxs2("div", { className: "flex items-end gap-1", children: [
589
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-12 animate-pulse rounded bg-ods-skeleton" }),
590
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-8 animate-pulse rounded bg-ods-skeleton" })
591
- ] })
592
- ] }, i)) })
593
- ] }),
594
- /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
595
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
596
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
597
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" })
598
- ] })
599
- ] }) }),
600
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
601
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-48 animate-pulse rounded bg-ods-skeleton md:h-10" }),
602
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-4", children: [
603
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-48 animate-pulse rounded bg-ods-skeleton" }),
604
- /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx3(
605
- "div",
606
- {
607
- className: "h-10 w-24 animate-pulse rounded-lg border border-ods-border bg-ods-card"
608
- },
609
- i
610
- )) })
611
- ] }),
612
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-4", children: [
613
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-52 animate-pulse rounded bg-ods-skeleton" }),
614
- /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-2", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx3(
615
- "div",
616
- {
617
- className: "h-10 w-28 animate-pulse rounded-lg border border-ods-border bg-ods-card"
618
- },
619
- i
620
- )) })
621
- ] })
622
- ] }),
623
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
624
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-64 animate-pulse rounded bg-ods-skeleton md:h-10" }),
625
- /* @__PURE__ */ jsx3("div", { className: "rounded-lg border border-ods-border bg-ods-card p-6 md:p-8", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
626
- /* @__PURE__ */ jsx3("div", { className: "h-6 animate-pulse rounded bg-ods-skeleton" }),
627
- /* @__PURE__ */ jsx3("div", { className: "h-6 animate-pulse rounded bg-ods-skeleton" }),
628
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-5/6 animate-pulse rounded bg-ods-skeleton" }),
629
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-4/5 animate-pulse rounded bg-ods-skeleton" })
630
- ] }) })
631
- ] }),
632
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
633
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-72 animate-pulse rounded bg-ods-skeleton md:h-10" }),
634
- /* @__PURE__ */ jsx3("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-4 rounded-lg border border-ods-border bg-ods-card p-4", children: [
635
- /* @__PURE__ */ jsx3("div", { className: "h-12 w-12 flex-shrink-0 animate-pulse rounded bg-ods-skeleton" }),
636
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 space-y-2", children: [
637
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-3/4 animate-pulse rounded bg-ods-skeleton" }),
638
- /* @__PURE__ */ jsx3("div", { className: "h-4 animate-pulse rounded bg-ods-skeleton" })
639
- ] })
640
- ] }, i)) })
641
- ] }),
642
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
643
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-80 animate-pulse rounded bg-ods-skeleton md:h-10" }),
644
- /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-2", children: [
645
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-6", children: [
646
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-16 animate-pulse rounded bg-ods-skeleton" }),
647
- Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-3 rounded-lg border border-ods-border bg-ods-card p-4", children: [
648
- /* @__PURE__ */ jsx3("div", { className: "h-12 w-12 flex-shrink-0 animate-pulse rounded border border-ods-border bg-ods-bg" }),
649
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 space-y-2", children: [
650
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-2/3 animate-pulse rounded bg-ods-skeleton" }),
651
- /* @__PURE__ */ jsx3("div", { className: "h-4 animate-pulse rounded bg-ods-skeleton" })
652
- ] })
653
- ] }, i))
654
- ] }),
655
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-6", children: [
656
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-16 animate-pulse rounded bg-ods-skeleton" }),
657
- Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-3 rounded-lg border border-ods-border bg-ods-card p-4", children: [
658
- /* @__PURE__ */ jsx3("div", { className: "h-12 w-12 flex-shrink-0 animate-pulse rounded border border-ods-border bg-ods-bg" }),
659
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 space-y-2", children: [
660
- /* @__PURE__ */ jsx3("div", { className: "h-5 w-2/3 animate-pulse rounded bg-ods-skeleton" }),
661
- /* @__PURE__ */ jsx3("div", { className: "h-4 animate-pulse rounded bg-ods-skeleton" })
662
- ] })
663
- ] }, i))
664
- ] })
665
- ] })
666
- ] }),
667
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
668
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-72 animate-pulse rounded bg-ods-skeleton md:h-10" }),
669
- /* @__PURE__ */ jsx3("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "space-y-4 rounded-lg border border-ods-border bg-ods-card p-6", children: [
670
- /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-4", children: [
671
- /* @__PURE__ */ jsx3("div", { className: "h-16 w-16 flex-shrink-0 animate-pulse rounded-lg border border-ods-border bg-ods-bg" }),
672
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 space-y-2", children: [
673
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-3/4 animate-pulse rounded bg-ods-skeleton" }),
674
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-1/2 animate-pulse rounded bg-ods-skeleton" })
675
- ] }),
676
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-20 animate-pulse rounded bg-ods-skeleton" })
677
- ] }),
678
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
679
- /* @__PURE__ */ jsx3("div", { className: "h-4 animate-pulse rounded bg-ods-skeleton" }),
680
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-5/6 animate-pulse rounded bg-ods-skeleton" }),
681
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-4/5 animate-pulse rounded bg-ods-skeleton" })
682
- ] }),
683
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between border-t border-ods-border pt-2", children: [
684
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-16 animate-pulse rounded bg-ods-skeleton" }),
685
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-20 animate-pulse rounded bg-ods-skeleton" })
686
- ] })
687
- ] }, i)) }),
688
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-md bg-ods-skeleton" })
689
- ] }),
690
- /* @__PURE__ */ jsxs2("div", { className: "mb-20 flex flex-col gap-6", children: [
691
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-64 animate-pulse rounded bg-ods-skeleton md:h-10" }),
692
- /* @__PURE__ */ jsx3("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs2("div", { className: "flex gap-3", children: [
693
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 overflow-hidden rounded-lg border border-ods-border bg-ods-bg", children: [
694
- /* @__PURE__ */ jsxs2("div", { className: "border-b border-ods-border p-3", children: [
695
- /* @__PURE__ */ jsx3("div", { className: "mb-2 h-3 w-8 animate-pulse rounded bg-ods-skeleton" }),
696
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-full animate-pulse rounded bg-ods-skeleton" })
697
- ] }),
698
- /* @__PURE__ */ jsxs2("div", { className: "p-3", children: [
699
- /* @__PURE__ */ jsx3("div", { className: "mb-2 h-3 w-16 animate-pulse rounded bg-ods-skeleton" }),
700
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
701
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-full animate-pulse rounded bg-ods-skeleton" }),
702
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-3/4 animate-pulse rounded bg-ods-skeleton" }),
703
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-1/2 animate-pulse rounded bg-ods-skeleton" })
704
- ] })
705
- ] })
706
- ] }),
707
- /* @__PURE__ */ jsx3("div", { className: "flex items-stretch", children: /* @__PURE__ */ jsx3("div", { className: "h-[120px] w-20 animate-pulse rounded-lg bg-ods-skeleton" }) })
708
- ] }) }),
709
- /* @__PURE__ */ jsx3("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-ods-border bg-ods-card p-4", children: [
710
- /* @__PURE__ */ jsx3("div", { className: "mb-3 flex flex-col gap-3 min-[420px]:flex-row min-[420px]:items-center min-[420px]:justify-between min-[420px]:gap-2", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
711
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 rounded-lg border border-ods-border bg-ods-card px-3 py-2", children: [
712
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-8 animate-pulse rounded-lg bg-ods-skeleton" }),
713
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-20 animate-pulse rounded bg-ods-skeleton" })
714
- ] }),
715
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-12 animate-pulse rounded bg-ods-skeleton" })
716
- ] }) }),
717
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
718
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-2/3 animate-pulse rounded bg-ods-skeleton" }),
719
- /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
720
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-full animate-pulse rounded bg-ods-skeleton" }),
721
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-4/5 animate-pulse rounded bg-ods-skeleton" }),
722
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-3/5 animate-pulse rounded bg-ods-skeleton" })
723
- ] })
724
- ] })
725
- ] }, i)) })
726
- ] })
727
- ] }),
728
- /* @__PURE__ */ jsx3("div", { className: "hidden w-[290px] flex-shrink-0 lg:block", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
729
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
730
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
731
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
732
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" })
733
- ] }),
734
- /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-lg border border-ods-border", children: [
735
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 bg-ods-card p-4", children: [
736
- /* @__PURE__ */ jsx3("div", { className: "h-8 w-8 animate-pulse rounded bg-ods-skeleton" }),
737
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", children: [
738
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-20 animate-pulse rounded bg-ods-skeleton" }),
739
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-12 animate-pulse rounded bg-ods-skeleton" })
740
- ] })
741
- ] }),
742
- /* @__PURE__ */ jsx3("div", { className: "space-y-3 p-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
743
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-6 animate-pulse rounded bg-ods-skeleton" }),
744
- /* @__PURE__ */ jsxs2("div", { className: "flex items-end gap-1", children: [
745
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-12 animate-pulse rounded bg-ods-skeleton" }),
746
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-8 animate-pulse rounded bg-ods-skeleton" })
747
- ] })
748
- ] }, i)) })
749
- ] }),
750
- /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
751
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
752
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
753
- /* @__PURE__ */ jsx3("div", { className: "h-12 animate-pulse rounded-lg border border-ods-border bg-ods-card" })
754
- ] })
755
- ] }) })
756
- ] })
757
- ] }) });
758
- }
759
- function StatsSectionSkeleton({ className, columns = 3 }) {
760
- return /* @__PURE__ */ jsx3(
761
- "div",
762
- {
763
- className: cn(
764
- "mb-12 grid gap-6 md:mb-16",
765
- columns === 3 && "grid-cols-1 md:grid-cols-3",
766
- columns === 4 && "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
767
- className
768
- ),
769
- children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx3("div", { className: "rounded-lg border border-ods-border bg-ods-card p-6", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
770
- /* @__PURE__ */ jsx3(MediaSkeleton.Icon, { size: "lg" }),
771
- /* @__PURE__ */ jsx3(TextSkeleton.Subheading, { className: "w-3/4" }),
772
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
773
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-full" }),
774
- /* @__PURE__ */ jsx3(TextSkeleton.Body, { className: "w-3/4" })
775
- ] })
776
- ] }) }, i))
777
- }
778
- );
779
- }
780
- function BlogCardGridSkeleton({ className }) {
781
- return /* @__PURE__ */ jsx3("div", { className: cn("space-y-6", className), children: /* @__PURE__ */ jsx3(CardSkeletonGrid, { count: 4, variant: "blog", className: "grid-cols-1 md:grid-cols-2" }) });
782
- }
783
- function VendorGridSkeleton({ className }) {
784
- return /* @__PURE__ */ jsx3("div", { className: cn("space-y-6", className), children: /* @__PURE__ */ jsx3(CardSkeletonGrid, { count: 12, variant: "vendor", className: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3" }) });
785
- }
786
- function SlackCommunitySkeleton() {
787
- return /* @__PURE__ */ jsx3("section", { className: "w-full bg-ods-bg px-4 py-12 md:px-20 md:py-20 lg:px-20", "aria-label": "Slack Community Loading", children: /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col gap-4 md:gap-6", children: [
788
- /* @__PURE__ */ jsx3("div", { className: "w-full", children: /* @__PURE__ */ jsx3("div", { className: "h-8 max-w-md animate-pulse rounded-lg bg-ods-skeleton md:h-12 lg:h-14" }) }),
789
- /* @__PURE__ */ jsxs2("div", { className: "flex w-full min-w-0 flex-col gap-4 md:gap-6 lg:flex-row lg:items-start lg:justify-end", children: [
790
- /* @__PURE__ */ jsx3("div", { className: "flex w-full flex-shrink-0 animate-pulse flex-col overflow-hidden rounded border border-ods-border bg-ods-bg lg:w-[290px] lg:max-w-[290px]", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4 p-4", children: [
791
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2", children: [
792
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between", children: [
793
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-24 rounded bg-ods-skeleton" }),
794
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-16 rounded bg-ods-skeleton" })
795
- ] }),
796
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-32 rounded bg-ods-skeleton" })
797
- ] }),
798
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", children: [
799
- /* @__PURE__ */ jsx3("div", { className: "mb-2 h-3 w-16 rounded bg-ods-skeleton" }),
800
- Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex min-h-[48px] items-center gap-2 px-2 py-3", children: [
801
- /* @__PURE__ */ jsx3("div", { className: "h-4 w-4 rounded bg-ods-skeleton" }),
802
- /* @__PURE__ */ jsxs2("div", { className: "flex-1", children: [
803
- /* @__PURE__ */ jsx3("div", { className: "mb-1 h-3 w-24 rounded bg-ods-skeleton" }),
804
- /* @__PURE__ */ jsx3("div", { className: "h-2 w-16 rounded bg-ods-skeleton" })
805
- ] })
806
- ] }, i))
807
- ] }),
808
- /* @__PURE__ */ jsx3("div", { className: "mt-2 border-t border-ods-border pt-3", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
809
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between", children: [
810
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-16 rounded bg-ods-skeleton" }),
811
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-8 rounded bg-ods-skeleton" })
812
- ] }),
813
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between", children: [
814
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-20 rounded bg-ods-skeleton" }),
815
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-8 rounded bg-ods-skeleton" })
816
- ] })
817
- ] }) })
818
- ] }) }),
819
- /* @__PURE__ */ jsxs2("div", { className: "flex h-[450px] min-h-[450px] min-w-0 flex-1 animate-pulse flex-col rounded-lg border border-ods-border bg-ods-card md:h-[500px] md:min-h-[500px] lg:h-[600px] lg:min-h-[600px]", children: [
820
- /* @__PURE__ */ jsxs2("div", { className: "flex h-[56px] flex-shrink-0 items-center justify-between border-b border-ods-border bg-ods-bg p-4 md:h-[60px] md:p-6", children: [
821
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
822
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-3 rounded bg-ods-skeleton md:h-4 md:w-4" }),
823
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-24 rounded bg-ods-skeleton md:h-4 md:w-32" })
824
- ] }),
825
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-12 rounded bg-ods-skeleton md:w-16" })
826
- ] }),
827
- /* @__PURE__ */ jsx3("div", { className: "min-h-[280px] flex-1 space-y-3 overflow-hidden bg-ods-bg p-4 md:min-h-[320px] md:space-y-4 md:p-6 lg:min-h-[420px]", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 md:gap-3", children: [
828
- /* @__PURE__ */ jsx3("div", { className: "h-10 w-10 flex-shrink-0 rounded-lg bg-ods-skeleton md:h-12 md:w-12" }),
829
- /* @__PURE__ */ jsxs2("div", { className: "flex-1", children: [
830
- /* @__PURE__ */ jsxs2("div", { className: "mb-1 flex items-center gap-2", children: [
831
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-16 rounded bg-ods-skeleton md:w-20" }),
832
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-12 rounded bg-ods-skeleton md:w-16" })
833
- ] }),
834
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-full rounded bg-ods-skeleton md:h-4" })
835
- ] })
836
- ] }, i)) }),
837
- /* @__PURE__ */ jsx3("div", { className: "h-[72px] flex-shrink-0 border-t border-ods-border bg-ods-card p-4 md:h-[80px] md:p-6", children: /* @__PURE__ */ jsx3("div", { className: "flex items-end justify-center gap-3 md:justify-end", children: /* @__PURE__ */ jsx3("div", { className: "h-10 w-28 rounded-lg bg-ods-skeleton md:h-12 md:w-32" }) }) })
838
- ] })
839
- ] })
840
- ] }) });
841
- }
842
-
843
- // src/components/persistent-filter-controls.tsx
844
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
845
- function PersistentFilterControls({
846
- isLoading,
847
- children,
848
- className,
849
- disabledOpacity = 0.6,
850
- transitionDuration = 300,
851
- preventInteraction = true
852
- }) {
853
- return /* @__PURE__ */ jsxs3(
854
- "div",
855
- {
856
- className: cn(
857
- "relative transition-all ease-in-out",
858
- isLoading && preventInteraction && "pointer-events-none",
859
- className
860
- ),
861
- style: {
862
- opacity: isLoading ? disabledOpacity : 1,
863
- transitionDuration: `${transitionDuration}ms`
864
- },
865
- role: "region",
866
- "aria-label": "Filter controls",
867
- "aria-busy": isLoading,
868
- "data-loading": isLoading,
869
- children: [
870
- isLoading && /* @__PURE__ */ jsx4("div", { className: "sr-only", role: "status", "aria-live": "polite", children: "Filters temporarily disabled while loading content" }),
871
- /* @__PURE__ */ jsx4(
872
- "div",
873
- {
874
- className: cn("transition-all ease-in-out", isLoading && "cursor-not-allowed"),
875
- style: {
876
- transitionDuration: `${transitionDuration}ms`
877
- },
878
- children
879
- }
880
- ),
881
- isLoading && /* @__PURE__ */ jsx4("div", { className: "absolute right-2 top-2 z-10", role: "status", "aria-label": "Loading filters", children: /* @__PURE__ */ jsx4("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-ods-border border-t-ods-accent" }) })
882
- ]
883
- }
884
- );
885
- }
886
- function PersistentSearchContainer({ isLoading, children, className }) {
887
- return /* @__PURE__ */ jsx4(
888
- PersistentFilterControls,
889
- {
890
- isLoading,
891
- preventInteraction: false,
892
- className,
893
- children
894
- }
895
- );
896
- }
897
- function PersistentSidebar({ isLoading, children, className }) {
898
- return /* @__PURE__ */ jsx4(
899
- PersistentFilterControls,
900
- {
901
- isLoading,
902
- disabledOpacity: 0.5,
903
- className: cn("lg:sticky lg:top-20", className),
904
- children
905
- }
906
- );
907
- }
908
- function PersistentMobileDropdown({ isLoading, children, className }) {
909
- return /* @__PURE__ */ jsx4(PersistentFilterControls, { isLoading, disabledOpacity: 0.7, className: cn("lg:hidden", className), children });
910
- }
911
-
912
- // src/components/docs/doc-navigation-context.tsx
913
- import React, { createContext, useCallback, useContext, useRef } from "react";
914
- import { jsx as jsx5 } from "react/jsx-runtime";
915
- var DocNavigationContext = createContext(null);
916
- function DocNavigationProvider({ children }) {
917
- const navMap = useRef(/* @__PURE__ */ new Map());
918
- const register = useCallback((nav) => {
919
- const existing = navMap.current.get(nav.baseRoute);
920
- if (existing && existing !== nav) {
921
- console.warn(`[DocNavigationContext] duplicate registration for ${nav.baseRoute}; replacing`);
922
- }
923
- navMap.current.set(nav.baseRoute, nav);
924
- return () => {
925
- if (navMap.current.get(nav.baseRoute) === nav) {
926
- navMap.current.delete(nav.baseRoute);
927
- }
928
- };
929
- }, []);
930
- const findOwningNavigator = useCallback((path) => {
931
- const baseRoutes = Array.from(navMap.current.keys()).sort((a, b) => b.length - a.length);
932
- for (const baseRoute of baseRoutes) {
933
- if (path === baseRoute || path.startsWith(`${baseRoute}/`)) {
934
- return navMap.current.get(baseRoute) ?? null;
935
- }
936
- }
937
- if (navMap.current.size === 1) {
938
- return navMap.current.values().next().value ?? null;
939
- }
940
- return null;
941
- }, []);
942
- const navigate = useCallback(
943
- (path) => {
944
- const nav = findOwningNavigator(path);
945
- if (!nav) return false;
946
- const node = nav.findNodeByPath(path);
947
- if (!node) return false;
948
- nav.selectNode(node);
949
- return true;
950
- },
951
- [findOwningNavigator]
952
- );
953
- const isAvailable = useCallback(() => navMap.current.size > 0, []);
954
- const value = React.useMemo(() => ({ register, navigate, isAvailable }), [register, navigate, isAvailable]);
955
- return /* @__PURE__ */ jsx5(DocNavigationContext.Provider, { value, children });
956
- }
957
- function useDocNavigation() {
958
- const ctx = useContext(DocNavigationContext);
959
- if (!ctx) {
960
- return {
961
- register: () => () => {
962
- },
963
- navigate: () => false,
964
- isAvailable: () => false
965
- };
966
- }
967
- return ctx;
968
- }
969
-
970
- // src/components/docs/use-docs-resolve-link.ts
971
- import { useCallback as useCallback2 } from "react";
972
- function toResolveLinkResult(body) {
973
- if (typeof body !== "object" || body === null) {
974
- return { success: false };
975
- }
976
- const envelope = { ...body };
977
- const inner = envelope.data;
978
- const fields = typeof inner === "object" && inner !== null ? { ...inner } : envelope;
979
- const readString2 = (key) => typeof fields[key] === "string" ? fields[key] : void 0;
980
- return {
981
- success: fields.success === true,
982
- resolvedPath: readString2("resolvedPath"),
983
- type: readString2("type"),
984
- action: readString2("action"),
985
- error: readString2("error"),
986
- message: readString2("message")
987
- };
988
- }
989
- function useDocsResolveLink(sourceId, resolveLinkEndpoint) {
990
- const chatRuntime = useChatRuntime();
991
- const resolvedResolveLinkEndpoint = resolveLinkEndpoint ?? chatRuntime?.endpoints.docsResolveLinkUrl ?? "/api/docs/resolve-link";
992
- return useCallback2(
993
- async (href, currentPath) => {
994
- try {
995
- const response = await contentFetch(resolvedResolveLinkEndpoint, {
996
- method: "POST",
997
- headers: { "Content-Type": "application/json" },
998
- body: JSON.stringify({ link: href, currentPath, source: sourceId })
999
- });
1000
- if (!response.ok) {
1001
- return { success: false, error: `Resolve failed: ${response.status}` };
1002
- }
1003
- const json = await response.json();
1004
- return toResolveLinkResult(json);
1005
- } catch (error) {
1006
- return {
1007
- success: false,
1008
- error: error instanceof Error ? error.message : "Resolve failed"
1009
- };
1010
- }
1011
- },
1012
- [resolvedResolveLinkEndpoint, sourceId]
1013
- );
1014
- }
1015
-
1016
- // src/components/docs/use-document-tree.ts
1017
- import { useState, useEffect, useCallback as useCallback3, useMemo, useRef as useRef2 } from "react";
1018
- function scrollToContent() {
1019
- const article = document.querySelector("article");
1020
- if (article) {
1021
- scrollElementIntoView(article, { headerOffset: HUB_HEADER_OFFSET_PX });
1022
- } else {
1023
- scrollElementIntoView(document.documentElement);
1024
- }
1025
- }
1026
- function findFirstDocPath(folder) {
1027
- const children = folder.children ?? [];
1028
- for (const child of children) {
1029
- if (child.type === "file" && !child.path.toLowerCase().endsWith(".mmd")) {
1030
- return child.path;
1031
- }
1032
- }
1033
- for (const child of children) {
1034
- if (child.type === "folder") {
1035
- const nested = findFirstDocPath(child);
1036
- if (nested) return nested;
1037
- }
1038
- }
1039
- return null;
1040
- }
1041
- function isRecord(value) {
1042
- return typeof value === "object" && value !== null;
1043
- }
1044
- function isUnknownArray(value) {
1045
- return Array.isArray(value);
1046
- }
1047
- function readString(source, key) {
1048
- const value = source[key];
1049
- return typeof value === "string" ? value : void 0;
1050
- }
1051
- function isDocumentType(value) {
1052
- return value === "markdown" || value === "pdf" || value === "google_sheet" || value === "figma" || value === "file";
1053
- }
1054
- function toDocNode(value) {
1055
- if (!isRecord(value)) return null;
1056
- const id = readString(value, "id");
1057
- const name = readString(value, "name");
1058
- const path = readString(value, "path");
1059
- const type = value.type;
1060
- if (id === void 0 || name === void 0 || path === void 0) return null;
1061
- if (type !== "file" && type !== "folder") return null;
1062
- const sortOrder = value.sortOrder;
1063
- const hasReadme = value.hasReadme;
1064
- return {
1065
- id,
1066
- name,
1067
- slug: readString(value, "slug") ?? path.split("/").pop() ?? "",
1068
- path,
1069
- type,
1070
- hasReadme: typeof hasReadme === "boolean" ? hasReadme : void 0,
1071
- sortOrder: typeof sortOrder === "number" ? sortOrder : void 0,
1072
- documentType: isDocumentType(value.documentType) ? value.documentType : void 0,
1073
- children: toDocNodes(value.children) ?? void 0
1074
- };
1075
- }
1076
- function toDocNodes(value) {
1077
- if (!isUnknownArray(value)) return null;
1078
- const nodes = [];
1079
- for (const entry of value) {
1080
- const node = toDocNode(entry);
1081
- if (node) nodes.push(node);
1082
- }
1083
- return nodes;
1084
- }
1085
- function toDocSections(value) {
1086
- if (!isUnknownArray(value)) return [];
1087
- const sections = [];
1088
- for (const entry of value) {
1089
- if (!isRecord(entry)) continue;
1090
- const id = readString(entry, "id");
1091
- const title = readString(entry, "title");
1092
- const level = entry.level;
1093
- if (id === void 0 || title === void 0 || typeof level !== "number") continue;
1094
- sections.push({ id, title, level });
1095
- }
1096
- return sections;
1097
- }
1098
- function toStringArray(value) {
1099
- if (!isUnknownArray(value)) return void 0;
1100
- return value.filter((entry) => typeof entry === "string");
1101
- }
1102
- function toDocContent(value, requestedPath) {
1103
- if (!isRecord(value)) return null;
1104
- const fileSize = value.fileSize;
1105
- return {
1106
- content: readString(value, "content") ?? "",
1107
- sections: toDocSections(value.sections),
1108
- path: readString(value, "path") ?? requestedPath,
1109
- documentType: isDocumentType(value.documentType) ? value.documentType : void 0,
1110
- brokenLinks: toStringArray(value.brokenLinks),
1111
- fileUrl: readString(value, "fileUrl"),
1112
- externalUrl: readString(value, "externalUrl"),
1113
- mimeType: readString(value, "mimeType"),
1114
- fileName: readString(value, "fileName"),
1115
- fileSize: typeof fileSize === "number" ? fileSize : void 0,
1116
- publishedAt: readString(value, "publishedAt"),
1117
- updatedAt: readString(value, "updatedAt")
1118
- };
1119
- }
1120
- function useDocumentTree(config, initialPath) {
1121
- const { structureEndpoint, contentEndpoint, baseRoute } = config;
1122
- const folderIndexFile = config.folderIndexFile ?? DEFAULT_FOLDER_INDEX_FILE;
1123
- const cleanInitialPath = stripFolderIndexFromPath(initialPath?.replace(/\/$/, "") || "", folderIndexFile);
1124
- const [structure, setStructure] = useState([]);
1125
- const [selectedPath, setSelectedPath] = useState(cleanInitialPath);
1126
- const [content, setContent] = useState(null);
1127
- const [isLoadingStructure, setIsLoadingStructure] = useState(true);
1128
- const [isLoadingContent, setIsLoadingContent] = useState(false);
1129
- const [error, setError] = useState(null);
1130
- const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
1131
- const lastFetchedPath = useRef2(null);
1132
- const normalizedBaseRoute = baseRoute.replace(/\/$/, "");
1133
- const selectedPathRef = useRef2(selectedPath);
1134
- useEffect(() => {
1135
- selectedPathRef.current = selectedPath;
1136
- });
1137
- const docNavigation = useDocNavigation();
1138
- useEffect(() => {
1139
- const handlePopState = () => {
1140
- const pathname = window.location.pathname;
1141
- let pathFromUrl = "";
1142
- if (pathname === normalizedBaseRoute || pathname === `${normalizedBaseRoute}/`) {
1143
- pathFromUrl = "";
1144
- } else if (pathname.startsWith(`${normalizedBaseRoute}/`)) {
1145
- pathFromUrl = pathname.substring(`${normalizedBaseRoute}/`.length);
1146
- }
1147
- pathFromUrl = stripFolderIndexFromPath(pathFromUrl, folderIndexFile);
1148
- if (pathFromUrl !== selectedPathRef.current) {
1149
- setSelectedPath(pathFromUrl);
1150
- if (pathFromUrl) {
1151
- const parentPath = pathFromUrl.includes("/") ? pathFromUrl.substring(0, pathFromUrl.lastIndexOf("/")) : pathFromUrl;
1152
- setExpandedNodes(new Set(getDocAncestorNodeIds(parentPath)));
1153
- }
1154
- setTimeout(() => {
1155
- scrollToContent();
1156
- }, 150);
1157
- }
1158
- };
1159
- window.addEventListener("popstate", handlePopState);
1160
- return () => window.removeEventListener("popstate", handlePopState);
1161
- }, [normalizedBaseRoute, folderIndexFile]);
1162
- const [syncedInitialPath, setSyncedInitialPath] = useState(cleanInitialPath);
1163
- const [externalNavCount, setExternalNavCount] = useState(0);
1164
- if (syncedInitialPath !== cleanInitialPath) {
1165
- setSyncedInitialPath(cleanInitialPath);
1166
- if (cleanInitialPath !== selectedPath) {
1167
- setSelectedPath(cleanInitialPath);
1168
- if (cleanInitialPath) {
1169
- const parentPath = cleanInitialPath.includes("/") ? cleanInitialPath.substring(0, cleanInitialPath.lastIndexOf("/")) : cleanInitialPath;
1170
- setExpandedNodes(new Set(getDocAncestorNodeIds(parentPath)));
1171
- }
1172
- setExternalNavCount((n) => n + 1);
1173
- }
1174
- }
1175
- useEffect(() => {
1176
- if (externalNavCount === 0) return void 0;
1177
- const timer = setTimeout(scrollToContent, 150);
1178
- return () => clearTimeout(timer);
1179
- }, [externalNavCount]);
1180
- const fetchStructure = async () => {
1181
- try {
1182
- setIsLoadingStructure(true);
1183
- setError(null);
1184
- const response = await contentFetch(structureEndpoint);
1185
- if (!response.ok) {
1186
- throw new Error("Failed to load documentation structure");
1187
- }
1188
- const payload = await response.json();
1189
- const nodes = isRecord(payload) && payload.success ? toDocNodes(payload.data) : null;
1190
- if (nodes) {
1191
- setStructure(nodes);
1192
- if (cleanInitialPath) {
1193
- const pathForExpansion = cleanInitialPath.includes(".") ? cleanInitialPath.substring(0, cleanInitialPath.lastIndexOf("/")) : cleanInitialPath;
1194
- if (pathForExpansion) {
1195
- setExpandedNodes(new Set(getDocAncestorNodeIds(pathForExpansion)));
1196
- }
1197
- } else if (nodes.length > 0) {
1198
- const hasRootReadme = nodes.some((node) => node.type === "file" && node.path === folderIndexFile);
1199
- if (!hasRootReadme) {
1200
- const firstNode = nodes[0];
1201
- if (firstNode.type === "folder") {
1202
- setExpandedNodes(/* @__PURE__ */ new Set([firstNode.id]));
1203
- if (firstNode.hasReadme) {
1204
- setSelectedPath(firstNode.path);
1205
- window.history.replaceState({}, "", `${normalizedBaseRoute}/${firstNode.path}`);
1206
- }
1207
- }
1208
- }
1209
- }
1210
- } else {
1211
- setError(apiErrorMessage(payload, "Failed to load documentation structure"));
1212
- }
1213
- } catch (err) {
1214
- console.error("Error fetching documentation structure:", err);
1215
- setError(err instanceof Error ? err.message : "Failed to load documentation");
1216
- } finally {
1217
- setIsLoadingStructure(false);
1218
- }
1219
- };
1220
- const fetchContent = async (path) => {
1221
- try {
1222
- setIsLoadingContent(true);
1223
- const response = await contentFetch(`${contentEndpoint}?path=${encodeURIComponent(path)}`);
1224
- if (path !== lastFetchedPath.current) return;
1225
- if (!response.ok) {
1226
- if (response.status === 404) {
1227
- const errorPayload = await response.json().catch(() => null);
1228
- if (path !== lastFetchedPath.current) return;
1229
- if (path === folderIndexFile && selectedPath === "") {
1230
- lastFetchedPath.current = null;
1231
- setError(null);
1232
- setContent(null);
1233
- return;
1234
- }
1235
- const probe = findDocNodeByPath(stripFolderIndexFromPath(path, folderIndexFile), structure);
1236
- const probeIsNoReadmeFolder = !!probe && probe.type === "folder" && !probe.hasReadme;
1237
- const preStructureFolderLike = structure.length === 0 && !path.endsWith(".md");
1238
- if (probeIsNoReadmeFolder || preStructureFolderLike) {
1239
- lastFetchedPath.current = null;
1240
- setError(null);
1241
- setContent(null);
1242
- return;
1243
- }
1244
- setError(apiErrorMessage(errorPayload, "Documentation file not found"));
1245
- setContent(null);
1246
- return;
1247
- }
1248
- throw new Error("Failed to load documentation content");
1249
- }
1250
- const payload = await response.json();
1251
- if (path !== lastFetchedPath.current) return;
1252
- setError(null);
1253
- const doc = isRecord(payload) && payload.success ? toDocContent(payload.data, path) : null;
1254
- if (doc) {
1255
- const correctPath = isRecord(payload) && payload.redirect ? readString(payload, "correctPath") : void 0;
1256
- if (correctPath !== void 0) {
1257
- setSelectedPath(correctPath);
1258
- window.history.replaceState({}, "", `${normalizedBaseRoute}/${correctPath}`);
1259
- }
1260
- setContent(doc);
1261
- } else {
1262
- setError(apiErrorMessage(payload, "Failed to load content"));
1263
- setContent(null);
1264
- }
1265
- } catch (err) {
1266
- if (path !== lastFetchedPath.current) return;
1267
- console.error("Error fetching documentation content:", err);
1268
- setError(err instanceof Error ? err.message : "Failed to load content");
1269
- setContent(null);
1270
- } finally {
1271
- if (path === lastFetchedPath.current) setIsLoadingContent(false);
1272
- }
1273
- };
1274
- const latestRef = useRef2({ fetchContent, fetchStructure, cleanInitialPath, folderIndexFile });
1275
- useEffect(() => {
1276
- latestRef.current = { fetchContent, fetchStructure, cleanInitialPath, folderIndexFile };
1277
- });
1278
- useEffect(() => {
1279
- const latest = latestRef.current;
1280
- const speculativeContentPath = latest.cleanInitialPath || latest.folderIndexFile;
1281
- lastFetchedPath.current = speculativeContentPath;
1282
- void latest.fetchContent(speculativeContentPath);
1283
- void latest.fetchStructure();
1284
- }, []);
1285
- useEffect(() => {
1286
- if (selectedPath === null || selectedPath === void 0) return;
1287
- if (!structure || structure.length === 0) return;
1288
- let pathToFetch = null;
1289
- if (selectedPath === "") {
1290
- pathToFetch = folderIndexFile;
1291
- } else {
1292
- const node = findDocNodeByPath(selectedPath, structure);
1293
- if (node && node.type === "folder" && !node.hasReadme) {
1294
- const firstDocPath = findFirstDocPath(node);
1295
- if (!firstDocPath) {
1296
- lastFetchedPath.current = null;
1297
- return;
1298
- }
1299
- pathToFetch = firstDocPath;
1300
- } else if (node && node.type === "folder" && node.hasReadme) {
1301
- if (lastFetchedPath.current === selectedPath) {
1302
- return;
1303
- }
1304
- pathToFetch = `${selectedPath}/${folderIndexFile}`;
1305
- } else {
1306
- pathToFetch = selectedPath;
1307
- }
1308
- }
1309
- if (pathToFetch === lastFetchedPath.current) {
1310
- return;
1311
- }
1312
- if (pathToFetch) {
1313
- lastFetchedPath.current = pathToFetch;
1314
- void latestRef.current.fetchContent(pathToFetch);
1315
- }
1316
- }, [selectedPath, structure, folderIndexFile]);
1317
- const toggleNode = useCallback3((nodeId) => {
1318
- setExpandedNodes((prev) => {
1319
- const next = new Set(prev);
1320
- if (next.has(nodeId)) {
1321
- next.delete(nodeId);
1322
- } else {
1323
- next.add(nodeId);
1324
- }
1325
- return next;
1326
- });
1327
- }, []);
1328
- const selectNode = useCallback3(
1329
- (node) => {
1330
- if (node.type === "folder") {
1331
- setExpandedNodes((prev) => {
1332
- if (prev.has(node.id)) {
1333
- const ancestorIds = getDocAncestorNodeIds(node.path);
1334
- ancestorIds.pop();
1335
- return new Set(ancestorIds);
1336
- }
1337
- return new Set(getDocAncestorNodeIds(node.path));
1338
- });
1339
- } else {
1340
- const lastSlash = node.path.lastIndexOf("/");
1341
- if (lastSlash > 0) {
1342
- setExpandedNodes(new Set(getDocAncestorNodeIds(node.path.substring(0, lastSlash))));
1343
- }
1344
- }
1345
- lastFetchedPath.current = null;
1346
- setSelectedPath(node.path);
1347
- window.history.pushState({}, "", `${normalizedBaseRoute}/${node.path}`);
1348
- setTimeout(scrollToContent, 150);
1349
- },
1350
- [normalizedBaseRoute]
1351
- );
1352
- const navigateToDoc = useCallback3(
1353
- (path, options) => {
1354
- const hashIndex = path.indexOf("#");
1355
- const anchor = hashIndex !== -1 ? path.substring(hashIndex) : "";
1356
- const cleanPath = path.replace(/\/$/, "").split("#")[0];
1357
- const pathForSelection = anchor && options?.fromInternalLink && cleanPath === "" ? selectedPathRef.current : stripFolderIndexFromPath(cleanPath, folderIndexFile);
1358
- if (anchor && options?.fromInternalLink && pathForSelection === selectedPathRef.current) {
1359
- navigateSamePageHash(anchor, { headerOffset: HUB_HEADER_OFFSET_PX });
1360
- return;
1361
- }
1362
- const scrollAfterNav = () => {
1363
- if (anchor) {
1364
- setTimeout(() => {
1365
- const el = document.getElementById(anchor.substring(1));
1366
- if (el) {
1367
- scrollElementIntoView(el, { headerOffset: HUB_HEADER_OFFSET_PX });
1368
- } else {
1369
- scrollToContent();
1370
- }
1371
- }, 300);
1372
- } else {
1373
- setTimeout(() => {
1374
- scrollToContent();
1375
- }, 150);
1376
- }
1377
- };
1378
- if (options?.expandFolder) {
1379
- lastFetchedPath.current = null;
1380
- setSelectedPath(cleanPath);
1381
- window.history.pushState({}, "", `${normalizedBaseRoute}/${cleanPath}${anchor}`);
1382
- const pathParts2 = cleanPath.split("/");
1383
- const nodeIdsToExpand = [];
1384
- let currentPath2 = "";
1385
- for (const part of pathParts2) {
1386
- currentPath2 = currentPath2 ? `${currentPath2}-${part}` : part;
1387
- nodeIdsToExpand.push(currentPath2.toLowerCase());
1388
- }
1389
- setExpandedNodes(new Set(nodeIdsToExpand));
1390
- if (options?.fromInternalLink) {
1391
- scrollAfterNav();
1392
- }
1393
- setError(null);
1394
- return;
1395
- }
1396
- const urlPath = pathForSelection;
1397
- lastFetchedPath.current = null;
1398
- setSelectedPath(pathForSelection);
1399
- window.history.pushState({}, "", `${normalizedBaseRoute}/${urlPath}${anchor}`);
1400
- if (options?.fromInternalLink) {
1401
- scrollAfterNav();
1402
- }
1403
- const pathParts = cleanPath.split("/");
1404
- const parentIds = [];
1405
- let currentPath = "";
1406
- const partsToProcess = cleanPath.includes(".") ? pathParts.slice(0, -1) : pathParts;
1407
- for (const part of partsToProcess) {
1408
- currentPath = currentPath ? `${currentPath}-${part}` : part;
1409
- parentIds.push(currentPath.toLowerCase());
1410
- }
1411
- if (parentIds.length > 0) {
1412
- setExpandedNodes(new Set(parentIds));
1413
- }
1414
- },
1415
- [normalizedBaseRoute, folderIndexFile]
1416
- );
1417
- useEffect(() => {
1418
- return docNavigation.register({
1419
- baseRoute: normalizedBaseRoute,
1420
- findNodeByPath: (path) => {
1421
- const clean = stripFolderIndexFromPath(path.replace(/\/$/, "").split("#")[0], folderIndexFile);
1422
- return findDocNodeByPath(clean, structure) ?? null;
1423
- },
1424
- selectNode
1425
- });
1426
- }, [docNavigation, normalizedBaseRoute, structure, selectNode, folderIndexFile]);
1427
- const isEmptyFolder = useMemo(() => {
1428
- if (!selectedPath || structure.length === 0) return false;
1429
- const node = findDocNodeByPath(selectedPath, structure);
1430
- return !!node && node.type === "folder" && !node.hasReadme && !findFirstDocPath(node);
1431
- }, [selectedPath, structure]);
1432
- return {
1433
- structure,
1434
- selectedPath,
1435
- setSelectedPath,
1436
- content: isEmptyFolder ? null : content,
1437
- isLoadingStructure,
1438
- isLoadingContent: isEmptyFolder ? false : isLoadingContent,
1439
- error: isEmptyFolder ? null : error,
1440
- expandedNodes,
1441
- toggleNode,
1442
- selectNode,
1443
- navigateToDoc,
1444
- refetch: fetchStructure,
1445
- setExpandedNodes
1446
- };
1447
- }
1448
-
1449
- // src/components/docs/use-scroll-spy.ts
1450
- import { useState as useState2, useRef as useRef3, useCallback as useCallback4, useEffect as useEffect2, useMemo as useMemo2 } from "react";
1451
- var SCROLL_OFFSET = 100;
1452
- var ID_SEPARATOR = "\n";
1453
- function useScrollSpy(sections) {
1454
- const [activeSection, setActiveSection] = useState2("");
1455
- const isScrollingFromClick = useRef3(false);
1456
- const sectionIdsKey = useMemo2(() => sections?.map((s) => s.id).join(ID_SEPARATOR) ?? "", [sections]);
1457
- const handleSectionClick = useCallback4((sectionId) => {
1458
- const targetElement = document.getElementById(sectionId);
1459
- if (!targetElement) return;
1460
- isScrollingFromClick.current = true;
1461
- setActiveSection(sectionId);
1462
- scrollElementIntoView(targetElement, { headerOffset: SCROLL_OFFSET });
1463
- setTimeout(() => {
1464
- isScrollingFromClick.current = false;
1465
- }, 800);
1466
- }, []);
1467
- useEffect2(() => {
1468
- const sectionIds = sectionIdsKey === "" ? [] : sectionIdsKey.split(ID_SEPARATOR);
1469
- if (sectionIds.length === 0) return void 0;
1470
- const handleScroll = () => {
1471
- if (isScrollingFromClick.current) return;
1472
- const scrollPosition = window.scrollY + SCROLL_OFFSET;
1473
- let currentSection = sectionIds[0] ?? "";
1474
- for (let i = sectionIds.length - 1; i >= 0; i--) {
1475
- const element = document.getElementById(sectionIds[i]);
1476
- if (element && scrollPosition >= element.offsetTop) {
1477
- currentSection = sectionIds[i];
1478
- break;
1479
- }
1480
- }
1481
- setActiveSection((prev) => prev !== currentSection ? currentSection : prev);
1482
- };
1483
- let scrollTimer;
1484
- const throttledScroll = () => {
1485
- clearTimeout(scrollTimer);
1486
- scrollTimer = setTimeout(handleScroll, 100);
1487
- };
1488
- window.addEventListener("scroll", throttledScroll);
1489
- handleScroll();
1490
- return () => {
1491
- window.removeEventListener("scroll", throttledScroll);
1492
- clearTimeout(scrollTimer);
1493
- };
1494
- }, [sectionIdsKey]);
1495
- return { activeSection, handleSectionClick };
1496
- }
1497
-
1498
- // src/components/docs/doc-viewer.tsx
1499
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1500
- var DEFAULT_DOC_VIEWER_PALETTE = {
1501
- background: "bg-ods-bg",
1502
- containerBackground: "transparent",
1503
- headerText: "text-ods-text-primary",
1504
- primaryText: "text-ods-text-primary",
1505
- secondaryText: "text-ods-text-secondary",
1506
- accent: "var(--ods-accent)",
1507
- border: "border-ods-border",
1508
- cardBackground: "bg-ods-card"
1509
- };
1510
- function DocViewer(props) {
1511
- return /* @__PURE__ */ jsx6(DocViewerContent, { ...props });
1512
- }
1513
- function DocViewerContent({
1514
- sourceId,
1515
- renderContent,
1516
- renderSkeleton,
1517
- chatSource,
1518
- title,
1519
- subtitle,
1520
- colorPalette = DEFAULT_DOC_VIEWER_PALETTE,
1521
- className = "",
1522
- shell = true,
1523
- docPath,
1524
- sidebarLabel = "DOCUMENTATION",
1525
- structureEndpoint,
1526
- contentEndpoint,
1527
- searchEndpoint,
1528
- resolveLinkEndpoint,
1529
- baseRoute,
1530
- emptyStateText,
1531
- showAIChat = false,
1532
- folderIndexFile,
1533
- backButton
1534
- }) {
1535
- const resolvedStructureEndpoint = structureEndpoint ?? `/api/docs/sources/${sourceId}/structure`;
1536
- const resolvedContentEndpoint = contentEndpoint ?? `/api/docs/sources/${sourceId}/content`;
1537
- const resolveLink = useDocsResolveLink(sourceId, resolveLinkEndpoint);
1538
- const {
1539
- structure,
1540
- selectedPath,
1541
- content,
1542
- isLoadingStructure,
1543
- isLoadingContent,
1544
- error,
1545
- expandedNodes,
1546
- selectNode,
1547
- toggleNode,
1548
- navigateToDoc
1549
- } = useDocumentTree(
1550
- {
1551
- structureEndpoint: resolvedStructureEndpoint,
1552
- contentEndpoint: resolvedContentEndpoint,
1553
- baseRoute,
1554
- folderIndexFile
1555
- },
1556
- docPath
1557
- );
1558
- const { activeSection, handleSectionClick } = useScrollSpy(content?.sections);
1559
- const docNav = useDocNavigation();
1560
- const router = useRouter();
1561
- const backCfg = backButton === false ? null : {
1562
- label: backButton?.label ?? "Back to home",
1563
- onClick: () => router.push(backButton?.href ?? "/")
1564
- };
1565
- const docSearch = useDocSearch({
1566
- source: chatSource,
1567
- baseRoute,
1568
- searchEndpoint,
1569
- onNavigate: (path) => navigateToDoc(path, { fromInternalLink: true }),
1570
- onInPageSwap: (path) => docNav.navigate(path)
1571
- });
1572
- const renderedContent = useMemo3(() => {
1573
- if (!content) return null;
1574
- return renderContent(content, {
1575
- onInternalLinkClick: navigateToDoc,
1576
- // Relative-link base = the RENDERED document's path, NOT `selectedPath`.
1577
- // They diverge for a no-README folder: selection stays on the folder
1578
- // (e.g. `repo/diagrams`) while the body is its first descendant doc
1579
- // (e.g. `repo/diagrams/architecture/README.md`, via `findFirstDocPath`).
1580
- // Resolving `./sibling.mmd` against the folder would 404; resolving it
1581
- // against `content.path` lands in the descendant's directory. The DAL
1582
- // sets `content.path` to the served doc in all cases (file / README
1583
- // folder / first-child fallback), so this is correct everywhere.
1584
- currentPath: content.path,
1585
- sourceId,
1586
- onResolveLink: resolveLink
1587
- });
1588
- }, [content, renderContent, navigateToDoc, sourceId, resolveLink]);
1589
- const selectedNodeDocType = selectedPath && structure.length > 0 ? findDocNodeByPath(selectedPath, structure)?.documentType : void 0;
1590
- const activeDocType = content?.documentType ?? selectedNodeDocType;
1591
- const isMarkdownContent = !activeDocType || activeDocType === "markdown";
1592
- const showStickyNav = isMarkdownContent;
1593
- const stickyNavSections = content?.sections?.map((s) => ({ id: s.id, label: s.title })) ?? [];
1594
- const isColorValue = colorPalette.background.startsWith("#") || colorPalette.background.startsWith("rgb") || colorPalette.background.startsWith("var(");
1595
- const bgStyle = isColorValue ? { backgroundColor: colorPalette.background } : {};
1596
- const bgClass = !isColorValue ? colorPalette.background : "";
1597
- const containerBgStyle = colorPalette.containerBackground !== "transparent" ? { backgroundColor: colorPalette.containerBackground } : {};
1598
- const defaultEmptyText = structure.length > 0 ? "Select a document from the sidebar to view" : "No documents yet. Add content from the admin panel.";
1599
- const resolvedEmptyText = emptyStateText || defaultEmptyText;
1600
- const inner = /* @__PURE__ */ jsx6("div", { style: { ...bgStyle, ...containerBgStyle }, children: /* @__PURE__ */ jsx6(PageLayout, { title, subtitle, titleSize: "h1", titleWrap: true, backButton: backCfg ?? void 0, children: /* @__PURE__ */ jsxs4("div", { className: "flex w-full flex-col gap-10", children: [
1601
- showAIChat && /* @__PURE__ */ jsx6(
1602
- DocSearchBar,
1603
- {
1604
- placeholder: `Search ${sidebarLabel?.toLowerCase() || "documents"}...`,
1605
- query: docSearch.query,
1606
- onQueryChange: docSearch.setQuery,
1607
- results: docSearch.results,
1608
- isLoading: docSearch.isLoading,
1609
- onResultSelect: docSearch.handleResultSelect,
1610
- showDropdown: docSearch.keepDropdownOpen
1611
- }
1612
- ),
1613
- error && /* @__PURE__ */ jsx6("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs4("div", { className: "max-w-md rounded-lg border border-ods-border bg-ods-card p-8 text-center", children: [
1614
- /* @__PURE__ */ jsx6("h2", { className: "text-ods-text-primary text-h3", children: "Error Loading Documents" }),
1615
- /* @__PURE__ */ jsxs4("p", { className: "mt-2 text-ods-text-secondary", children: [
1616
- error,
1617
- ". Please try again later."
1618
- ] })
1619
- ] }) }),
1620
- !error && /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 flex-col items-start gap-6 lg:flex-row lg:gap-10", children: [
1621
- /* @__PURE__ */ jsx6("div", { className: "w-full lg:w-[320px] lg:shrink-0", children: /* @__PURE__ */ jsx6("div", { className: "lg:sticky lg:top-20", children: isLoadingStructure ? /* @__PURE__ */ jsx6(CategorySidebarSkeleton, {}) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
1622
- /* @__PURE__ */ jsx6(PersistentMobileDropdown, { isLoading: false, children: /* @__PURE__ */ jsx6(
1623
- MobileNavigationDropdown,
1624
- {
1625
- nodes: structure,
1626
- selectedPath,
1627
- expandedNodes,
1628
- onNodeClick: selectNode,
1629
- onToggleExpand: toggleNode,
1630
- isLoading: false,
1631
- folderIndexFile
1632
- }
1633
- ) }),
1634
- /* @__PURE__ */ jsx6(PersistentSidebar, { isLoading: false, children: /* @__PURE__ */ jsx6("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsxs4("div", { className: "space-y-4", children: [
1635
- /* @__PURE__ */ jsx6("h3", { className: "font-semibold text-ods-text-secondary text-h5", children: sidebarLabel }),
1636
- /* @__PURE__ */ jsx6(
1637
- MultiLevelNavigation,
1638
- {
1639
- nodes: structure,
1640
- selectedPath,
1641
- expandedNodes,
1642
- onNodeClick: selectNode,
1643
- onToggleExpand: toggleNode,
1644
- isLoading: false,
1645
- folderIndexFile
1646
- }
1647
- )
1648
- ] }) }) })
1649
- ] }) }) }),
1650
- /* @__PURE__ */ jsx6("div", { className: "w-full min-w-0 flex-1", children: /* @__PURE__ */ jsxs4(
1651
- "div",
1652
- {
1653
- className: `grid grid-cols-1 ${// "On this page" right column only makes sense for
1654
- // MARKDOWN content (PDFs / Sheets / Figma / file have no
1655
- // sections to navigate to). Gating the grid template on
1656
- // `isMarkdownContent` also suppresses the section-skeleton
1657
- // bars during embed loads — the user-reported "skeleton
1658
- // shouldn't be on file pages" bug.
1659
- isMarkdownContent && (showStickyNav && stickyNavSections.length > 0 || isLoadingContent || isLoadingStructure) ? "lg:grid-cols-[1fr_280px]" : ""} gap-8`,
1660
- children: [
1661
- /* @__PURE__ */ jsx6("div", { className: `w-full min-w-0 ${isMarkdownContent ? "mx-auto max-w-4xl" : ""}`, children: /* @__PURE__ */ jsx6("article", { className: "space-y-2", children: isLoadingContent || isLoadingStructure ? renderSkeleton(selectedNodeDocType) : !content ? /* @__PURE__ */ jsx6("div", { className: "py-16 text-center", children: /* @__PURE__ */ jsx6("p", { className: "text-ods-text-secondary text-h4", children: resolvedEmptyText }) }) : renderedContent }) }),
1662
- isMarkdownContent && (isLoadingContent || isLoadingStructure) && /* @__PURE__ */ jsx6("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsxs4("div", { className: "sticky top-24", children: [
1663
- /* @__PURE__ */ jsx6("div", { className: "mb-5 h-[14px] w-28 animate-pulse rounded bg-ods-border" }),
1664
- /* @__PURE__ */ jsx6("div", { className: "space-y-0", children: [130, 170, 190, 220, 110, 200, 80, 100, 120, 140, 90].map((w, i) => /* @__PURE__ */ jsx6(
1665
- "div",
1666
- {
1667
- className: `border-l-2 py-[13px] pl-3 ${i === 0 ? "border-ods-accent" : "border-transparent"}`,
1668
- children: /* @__PURE__ */ jsx6("div", { className: "h-[13px] animate-pulse rounded bg-ods-border", style: { width: w } })
1669
- },
1670
- i
1671
- )) })
1672
- ] }) }),
1673
- showStickyNav && content && stickyNavSections.length > 0 && !isLoadingContent && /* @__PURE__ */ jsx6("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsxs4("div", { className: "sticky top-24", children: [
1674
- /* @__PURE__ */ jsx6("h3", { className: "mb-4 font-semibold text-ods-text-secondary text-h5", children: "ON THIS PAGE" }),
1675
- /* @__PURE__ */ jsx6(
1676
- StickySectionNav,
1677
- {
1678
- sections: stickyNavSections,
1679
- activeSection,
1680
- onSectionClick: handleSectionClick,
1681
- ribbonPosition: "left",
1682
- ribbonColor: "var(--ods-accent)"
1683
- }
1684
- )
1685
- ] }) })
1686
- ]
1687
- }
1688
- ) })
1689
- ] })
1690
- ] }) }) });
1691
- return shell ? /* @__PURE__ */ jsx6(PageShell, { contentClassName: `${bgClass} ${className}`, children: inner }) : /* @__PURE__ */ jsx6("div", { className: `page-shell-content ${bgClass} ${className}`.trim(), children: inner });
1692
- }
1693
-
1694
- // src/components/docs/skeletons.tsx
1695
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1696
- function MarkdownSkeleton() {
1697
- return /* @__PURE__ */ jsxs5("div", { className: "mt-6 space-y-7", children: [
1698
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1699
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1700
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1701
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1702
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-3/4 animate-pulse rounded bg-ods-border" })
1703
- ] }),
1704
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1705
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1706
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1707
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1708
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-5/6 animate-pulse rounded bg-ods-border" })
1709
- ] }),
1710
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1711
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1712
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1713
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1714
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1715
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-2/3 animate-pulse rounded bg-ods-border" })
1716
- ] }),
1717
- /* @__PURE__ */ jsx7("div", { className: "h-[88px] animate-pulse rounded-lg border border-ods-border bg-ods-card" }),
1718
- /* @__PURE__ */ jsx7("div", { className: "h-7 w-1/3 animate-pulse rounded bg-ods-border" }),
1719
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1720
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1721
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1722
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1723
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-[72%] animate-pulse rounded bg-ods-border" })
1724
- ] }),
1725
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1726
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1727
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1728
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1729
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1730
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-[58%] animate-pulse rounded bg-ods-border" })
1731
- ] }),
1732
- /* @__PURE__ */ jsx7("div", { className: "h-7 w-2/5 animate-pulse rounded bg-ods-border" }),
1733
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1734
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1735
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1736
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-[90%] animate-pulse rounded bg-ods-border" })
1737
- ] }),
1738
- /* @__PURE__ */ jsxs5("div", { className: "space-y-[14px]", children: [
1739
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1740
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1741
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-full animate-pulse rounded bg-ods-border" }),
1742
- /* @__PURE__ */ jsx7("div", { className: "h-[16px] w-[70%] animate-pulse rounded bg-ods-border" })
1743
- ] }),
1744
- /* @__PURE__ */ jsx7("div", { className: "h-[88px] animate-pulse rounded-lg border border-ods-border bg-ods-card" })
1745
- ] });
1746
- }
1747
- function EmbedSkeleton({ documentType } = {}) {
1748
- if (documentType === "file") {
1749
- return /* @__PURE__ */ jsx7("div", { className: "flex flex-col items-center justify-center py-16", children: /* @__PURE__ */ jsxs5("div", { className: "w-full max-w-md space-y-4 rounded-xl border border-ods-border bg-ods-card p-8 text-center", children: [
1750
- /* @__PURE__ */ jsx7("div", { className: "mx-auto h-16 w-16 animate-pulse rounded bg-ods-border" }),
1751
- /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1752
- /* @__PURE__ */ jsx7("div", { className: "mx-auto h-5 w-2/3 animate-pulse rounded bg-ods-border" }),
1753
- /* @__PURE__ */ jsx7("div", { className: "mx-auto h-4 w-1/2 animate-pulse rounded bg-ods-border" })
1754
- ] }),
1755
- /* @__PURE__ */ jsx7("div", { className: "h-10 w-full animate-pulse rounded bg-ods-border" })
1756
- ] }) });
1757
- }
1758
- const buttonCount = documentType === "pdf" ? 2 : 1;
1759
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
1760
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
1761
- /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
1762
- /* @__PURE__ */ jsx7("div", { className: "h-5 w-5 shrink-0 animate-pulse rounded bg-ods-border" }),
1763
- /* @__PURE__ */ jsx7("div", { className: "h-6 w-2/3 animate-pulse rounded bg-ods-border" })
1764
- ] }),
1765
- /* @__PURE__ */ jsx7("div", { className: "flex w-full items-center gap-2 sm:w-auto", children: Array.from({ length: buttonCount }).map((_, i) => /* @__PURE__ */ jsx7("div", { className: "h-10 w-full flex-1 animate-pulse rounded bg-ods-border sm:w-32 sm:flex-initial" }, i)) })
1766
- ] }),
1767
- /* @__PURE__ */ jsx7(
1768
- "div",
1769
- {
1770
- className: "w-full animate-pulse rounded-lg border border-ods-border bg-ods-card",
1771
- style: { height: "calc(100vh - 250px)" }
1772
- }
1773
- )
1774
- ] });
1775
- }
1776
-
1777
- // src/components/docs/docs-hub-page.tsx
1778
- import { jsx as jsx8 } from "react/jsx-runtime";
1779
- var DEFAULT_TITLE = "Documents";
1780
- var defaultFallbackRenderer = () => /* @__PURE__ */ jsx8("div", { className: "py-16 text-center", children: /* @__PURE__ */ jsx8("p", { className: "text-ods-text-secondary", children: "Unsupported document type" }) });
1781
- var defaultPdfRenderer = (content, handlers) => content.fileUrl ? /* @__PURE__ */ jsx8(PdfViewer, { src: content.fileUrl, fileName: content.fileName }) : defaultFallbackRenderer(content, handlers);
1782
- var defaultGoogleSheetRenderer = (content, handlers) => content.externalUrl ? /* @__PURE__ */ jsx8(GoogleSheetsViewer, { externalUrl: content.externalUrl, fileName: content.fileName }) : defaultFallbackRenderer(content, handlers);
1783
- var defaultFigmaRenderer = (content, handlers) => content.externalUrl ? /* @__PURE__ */ jsx8(FigmaEmbed, { url: content.externalUrl, title: content.fileName, loading: "eager" }) : defaultFallbackRenderer(content, handlers);
1784
- var defaultFileRenderer = (content) => /* @__PURE__ */ jsx8(
1785
- FileDownloadCard,
1786
- {
1787
- fileName: content.fileName,
1788
- mimeType: content.mimeType,
1789
- fileSize: content.fileSize,
1790
- fileUrl: content.fileUrl
1791
- }
1792
- );
1793
- var defaultRenderSkeleton = (documentType) => !documentType || documentType === "markdown" ? /* @__PURE__ */ jsx8(MarkdownSkeleton, {}) : (
1794
- // Forward the documentType so the embed skeleton renders the right
1795
- // shape (PDF=2 buttons, sheets/figma=1 button, file=centered card).
1796
- /* @__PURE__ */ jsx8(EmbedSkeleton, { documentType })
1797
- );
1798
- function DocsHubPage({
1799
- title = DEFAULT_TITLE,
1800
- documentTypeRenderers,
1801
- fallbackRenderer = defaultFallbackRenderer,
1802
- renderSkeleton = defaultRenderSkeleton,
1803
- showAIChat = true,
1804
- className = "min-h-screen",
1805
- sidebarLabel = "DOCUMENTATION",
1806
- ...docViewerProps
1807
- }) {
1808
- const resolvedRenderers = {
1809
- markdown: documentTypeRenderers.markdown,
1810
- pdf: documentTypeRenderers.pdf ?? defaultPdfRenderer,
1811
- google_sheet: documentTypeRenderers.google_sheet ?? defaultGoogleSheetRenderer,
1812
- figma: documentTypeRenderers.figma ?? defaultFigmaRenderer,
1813
- file: documentTypeRenderers.file ?? defaultFileRenderer
1814
- };
1815
- const renderContent = (content, handlers) => {
1816
- const type = content.documentType ?? "markdown";
1817
- const renderer = resolvedRenderers[type] ?? fallbackRenderer;
1818
- return renderer(content, handlers);
1819
- };
1820
- return /* @__PURE__ */ jsx8(
1821
- DocViewer,
1822
- {
1823
- ...docViewerProps,
1824
- title,
1825
- showAIChat,
1826
- className,
1827
- sidebarLabel,
1828
- renderContent,
1829
- renderSkeleton
1830
- }
1831
- );
1832
- }
1833
-
1834
- export {
1835
- UnifiedSkeleton,
1836
- TextSkeleton,
1837
- InteractiveSkeleton,
1838
- MediaSkeleton,
1839
- CardSkeleton,
1840
- CardSkeletonGrid,
1841
- AnnouncementBarSkeleton,
1842
- HeroSkeleton,
1843
- SearchContainerSkeleton,
1844
- CategorySidebarSkeleton,
1845
- BreadcrumbSkeleton,
1846
- ResultsHeaderSkeleton,
1847
- TwoColumnLayoutSkeleton,
1848
- ArticleLayoutSkeleton,
1849
- VendorDetailLayoutSkeleton,
1850
- StatsSectionSkeleton,
1851
- BlogCardGridSkeleton,
1852
- VendorGridSkeleton,
1853
- SlackCommunitySkeleton,
1854
- PersistentFilterControls,
1855
- PersistentSearchContainer,
1856
- PersistentSidebar,
1857
- PersistentMobileDropdown,
1858
- DocNavigationProvider,
1859
- useDocNavigation,
1860
- useDocumentTree,
1861
- useScrollSpy,
1862
- DocViewer,
1863
- MarkdownSkeleton,
1864
- EmbedSkeleton,
1865
- DocsHubPage
1866
- };
1867
- //# sourceMappingURL=chunk-FWNIZC6A.js.map