@cedros/data-react 0.1.0

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 (152) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +177 -0
  3. package/dist/admin/api.d.ts +19 -0
  4. package/dist/admin/api.js +108 -0
  5. package/dist/admin/components.d.ts +36 -0
  6. package/dist/admin/components.js +22 -0
  7. package/dist/admin/history.d.ts +17 -0
  8. package/dist/admin/history.js +103 -0
  9. package/dist/admin/icons.d.ts +15 -0
  10. package/dist/admin/icons.js +18 -0
  11. package/dist/admin/index.d.ts +13 -0
  12. package/dist/admin/index.js +12 -0
  13. package/dist/admin/permissions.d.ts +4 -0
  14. package/dist/admin/permissions.js +45 -0
  15. package/dist/admin/plugin.d.ts +4 -0
  16. package/dist/admin/plugin.js +180 -0
  17. package/dist/admin/primitives/ConfirmDialog.d.ts +14 -0
  18. package/dist/admin/primitives/ConfirmDialog.js +7 -0
  19. package/dist/admin/primitives/DataTable.d.ts +14 -0
  20. package/dist/admin/primitives/DataTable.js +7 -0
  21. package/dist/admin/primitives/DiffViewer.d.ts +11 -0
  22. package/dist/admin/primitives/DiffViewer.js +8 -0
  23. package/dist/admin/primitives/FormFieldRow.d.ts +23 -0
  24. package/dist/admin/primitives/FormFieldRow.js +16 -0
  25. package/dist/admin/primitives/JsonCodeEditor.d.ts +10 -0
  26. package/dist/admin/primitives/JsonCodeEditor.js +42 -0
  27. package/dist/admin/primitives/Pagination.d.ts +8 -0
  28. package/dist/admin/primitives/Pagination.js +8 -0
  29. package/dist/admin/primitives/Toolbar.d.ts +23 -0
  30. package/dist/admin/primitives/Toolbar.js +10 -0
  31. package/dist/admin/primitives/alerts.d.ts +21 -0
  32. package/dist/admin/primitives/alerts.js +44 -0
  33. package/dist/admin/sectionIds.d.ts +20 -0
  34. package/dist/admin/sectionIds.js +33 -0
  35. package/dist/admin/sections/CollectionsSection.d.ts +2 -0
  36. package/dist/admin/sections/CollectionsSection.js +125 -0
  37. package/dist/admin/sections/ContractVerifySection.d.ts +11 -0
  38. package/dist/admin/sections/ContractVerifySection.js +98 -0
  39. package/dist/admin/sections/CustomDataSection.d.ts +2 -0
  40. package/dist/admin/sections/CustomDataSection.js +256 -0
  41. package/dist/admin/sections/DataOpsSection.d.ts +26 -0
  42. package/dist/admin/sections/DataOpsSection.js +245 -0
  43. package/dist/admin/sections/HistorySection.d.ts +2 -0
  44. package/dist/admin/sections/HistorySection.js +26 -0
  45. package/dist/admin/sections/MonetizationSection.d.ts +2 -0
  46. package/dist/admin/sections/MonetizationSection.js +140 -0
  47. package/dist/admin/sections/NavigationSection.d.ts +13 -0
  48. package/dist/admin/sections/NavigationSection.js +195 -0
  49. package/dist/admin/sections/PagesSection.d.ts +2 -0
  50. package/dist/admin/sections/PagesSection.js +157 -0
  51. package/dist/admin/sections/SchemaDesignerSection.d.ts +2 -0
  52. package/dist/admin/sections/SchemaDesignerSection.js +167 -0
  53. package/dist/admin/sections/SiteSettingsSection.d.ts +12 -0
  54. package/dist/admin/sections/SiteSettingsSection.js +122 -0
  55. package/dist/admin/sections/TippingSection.d.ts +2 -0
  56. package/dist/admin/sections/TippingSection.js +178 -0
  57. package/dist/admin/sections/media/MediaDetail.d.ts +12 -0
  58. package/dist/admin/sections/media/MediaDetail.js +74 -0
  59. package/dist/admin/sections/media/MediaGrid.d.ts +14 -0
  60. package/dist/admin/sections/media/MediaGrid.js +22 -0
  61. package/dist/admin/sections/media/MediaSection.d.ts +2 -0
  62. package/dist/admin/sections/media/MediaSection.js +97 -0
  63. package/dist/admin/sections/media/MediaUploader.d.ts +7 -0
  64. package/dist/admin/sections/media/MediaUploader.js +72 -0
  65. package/dist/admin/sections/media/types.d.ts +33 -0
  66. package/dist/admin/sections/media/types.js +1 -0
  67. package/dist/admin/styles.css +533 -0
  68. package/dist/admin/types.d.ts +85 -0
  69. package/dist/admin/types.js +1 -0
  70. package/dist/index.d.ts +4 -0
  71. package/dist/index.js +3 -0
  72. package/dist/react/CmsContent.d.ts +20 -0
  73. package/dist/react/CmsContent.js +31 -0
  74. package/dist/react/entries.d.ts +9 -0
  75. package/dist/react/entries.js +25 -0
  76. package/dist/react/fetch.d.ts +11 -0
  77. package/dist/react/fetch.js +32 -0
  78. package/dist/react/index.d.ts +10 -0
  79. package/dist/react/index.js +9 -0
  80. package/dist/react/metadata.d.ts +44 -0
  81. package/dist/react/metadata.js +142 -0
  82. package/dist/react/sanitize.d.ts +17 -0
  83. package/dist/react/sanitize.js +326 -0
  84. package/dist/react/server.d.ts +14 -0
  85. package/dist/react/server.js +13 -0
  86. package/dist/react/sitemap.d.ts +28 -0
  87. package/dist/react/sitemap.js +91 -0
  88. package/dist/react/slugs.d.ts +27 -0
  89. package/dist/react/slugs.js +52 -0
  90. package/dist/react/types.d.ts +85 -0
  91. package/dist/react/types.js +1 -0
  92. package/dist/react/visitor.d.ts +7 -0
  93. package/dist/react/visitor.js +18 -0
  94. package/dist/site-templates/BlogTemplates.d.ts +95 -0
  95. package/dist/site-templates/BlogTemplates.js +64 -0
  96. package/dist/site-templates/ContactPageTemplate.d.ts +14 -0
  97. package/dist/site-templates/ContactPageTemplate.js +5 -0
  98. package/dist/site-templates/DashboardOverviewTemplate.d.ts +29 -0
  99. package/dist/site-templates/DashboardOverviewTemplate.js +17 -0
  100. package/dist/site-templates/DashboardShell.d.ts +28 -0
  101. package/dist/site-templates/DashboardShell.js +10 -0
  102. package/dist/site-templates/DocsSidebar.d.ts +14 -0
  103. package/dist/site-templates/DocsSidebar.js +13 -0
  104. package/dist/site-templates/DocsTemplates.d.ts +60 -0
  105. package/dist/site-templates/DocsTemplates.js +47 -0
  106. package/dist/site-templates/HomePageTemplate.d.ts +15 -0
  107. package/dist/site-templates/HomePageTemplate.js +10 -0
  108. package/dist/site-templates/LegalPageTemplate.d.ts +12 -0
  109. package/dist/site-templates/LegalPageTemplate.js +6 -0
  110. package/dist/site-templates/MarkdownContent.d.ts +7 -0
  111. package/dist/site-templates/MarkdownContent.js +24 -0
  112. package/dist/site-templates/NotFoundTemplate.d.ts +9 -0
  113. package/dist/site-templates/NotFoundTemplate.js +5 -0
  114. package/dist/site-templates/SiteFooter.d.ts +13 -0
  115. package/dist/site-templates/SiteFooter.js +4 -0
  116. package/dist/site-templates/SiteLayout.d.ts +14 -0
  117. package/dist/site-templates/SiteLayout.js +6 -0
  118. package/dist/site-templates/TopNav.d.ts +10 -0
  119. package/dist/site-templates/TopNav.js +8 -0
  120. package/dist/site-templates/blogControls.d.ts +19 -0
  121. package/dist/site-templates/blogControls.js +37 -0
  122. package/dist/site-templates/codeBlock.d.ts +9 -0
  123. package/dist/site-templates/codeBlock.js +31 -0
  124. package/dist/site-templates/content-styles.css +410 -0
  125. package/dist/site-templates/contentIndex.d.ts +65 -0
  126. package/dist/site-templates/contentIndex.js +181 -0
  127. package/dist/site-templates/contentUi.d.ts +14 -0
  128. package/dist/site-templates/contentUi.js +24 -0
  129. package/dist/site-templates/docs-styles.css +259 -0
  130. package/dist/site-templates/docsNavigation.d.ts +18 -0
  131. package/dist/site-templates/docsNavigation.js +50 -0
  132. package/dist/site-templates/index.d.ts +28 -0
  133. package/dist/site-templates/index.js +25 -0
  134. package/dist/site-templates/monetization-styles.css +154 -0
  135. package/dist/site-templates/paywallControls.d.ts +22 -0
  136. package/dist/site-templates/paywallControls.js +9 -0
  137. package/dist/site-templates/routing.d.ts +12 -0
  138. package/dist/site-templates/routing.js +36 -0
  139. package/dist/site-templates/solanaAtaSetup.d.ts +11 -0
  140. package/dist/site-templates/solanaAtaSetup.js +38 -0
  141. package/dist/site-templates/solanaMicropayments.d.ts +65 -0
  142. package/dist/site-templates/solanaMicropayments.js +115 -0
  143. package/dist/site-templates/styles.css +332 -0
  144. package/dist/site-templates/tipControls.d.ts +24 -0
  145. package/dist/site-templates/tipControls.js +43 -0
  146. package/dist/site-templates/tocExtractor.d.ts +16 -0
  147. package/dist/site-templates/tocExtractor.js +58 -0
  148. package/dist/site-templates/tocScrollSpy.d.ts +16 -0
  149. package/dist/site-templates/tocScrollSpy.js +37 -0
  150. package/dist/templates.d.ts +8 -0
  151. package/dist/templates.js +20 -0
  152. package/package.json +58 -0
@@ -0,0 +1,410 @@
1
+ .cedros-site__controls {
2
+ margin-top: 1rem;
3
+ display: grid;
4
+ grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
5
+ gap: 0.7rem;
6
+ align-items: end;
7
+ }
8
+
9
+ .cedros-site__control {
10
+ display: grid;
11
+ gap: 0.35rem;
12
+ font-size: 0.78rem;
13
+ color: var(--cds-muted);
14
+ }
15
+
16
+ .cedros-site__control input,
17
+ .cedros-site__control select {
18
+ width: 100%;
19
+ border: 1px solid var(--cds-border);
20
+ border-radius: calc(var(--cds-radius) - 2px);
21
+ background: color-mix(in srgb, var(--cds-bg) 90%, var(--cds-muted-bg) 10%);
22
+ color: var(--cds-fg);
23
+ height: 2.25rem;
24
+ padding: 0 0.6rem;
25
+ }
26
+
27
+ .cedros-site__control-actions {
28
+ display: inline-flex;
29
+ gap: 0.5rem;
30
+ align-items: center;
31
+ }
32
+
33
+ .cedros-site__control-actions button {
34
+ cursor: pointer;
35
+ }
36
+
37
+ .cedros-site__content-grid {
38
+ margin-top: 1rem;
39
+ display: grid;
40
+ gap: 0.85rem;
41
+ }
42
+
43
+ .cedros-site__content-grid--docs {
44
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
45
+ }
46
+
47
+ .cedros-site__entry-card {
48
+ display: grid;
49
+ gap: 0.6rem;
50
+ }
51
+
52
+ .cedros-site__entry-header {
53
+ display: flex;
54
+ align-items: flex-start;
55
+ justify-content: space-between;
56
+ gap: 0.6rem;
57
+ }
58
+
59
+ .cedros-site__entry-title {
60
+ margin: 0;
61
+ font-size: 1rem;
62
+ }
63
+
64
+ .cedros-site__entry-title a {
65
+ text-decoration: none;
66
+ }
67
+
68
+ .cedros-site__entry-title a:hover {
69
+ text-decoration: underline;
70
+ }
71
+
72
+ .cedros-site__entry-meta {
73
+ margin: 0;
74
+ font-size: 0.78rem;
75
+ color: var(--cds-muted);
76
+ }
77
+
78
+ .cedros-site__tag-list {
79
+ display: inline-flex;
80
+ flex-wrap: wrap;
81
+ gap: 0.35rem;
82
+ }
83
+
84
+ .cedros-site__pagination {
85
+ margin-top: 0.8rem;
86
+ display: inline-flex;
87
+ flex-wrap: wrap;
88
+ gap: 0.45rem;
89
+ }
90
+
91
+ .cedros-site__breadcrumbs {
92
+ margin-top: 0.2rem;
93
+ display: inline-flex;
94
+ flex-wrap: wrap;
95
+ align-items: center;
96
+ gap: 0.45rem;
97
+ font-size: 0.78rem;
98
+ color: var(--cds-muted);
99
+ }
100
+
101
+ .cedros-site__breadcrumbs a {
102
+ color: var(--cds-muted);
103
+ text-decoration: none;
104
+ }
105
+
106
+ .cedros-site__breadcrumbs a:hover {
107
+ color: var(--cds-fg);
108
+ text-decoration: underline;
109
+ }
110
+
111
+ .cedros-site__docs-page {
112
+ margin-top: 0.85rem;
113
+ display: grid;
114
+ gap: 1rem;
115
+ grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);
116
+ align-items: start;
117
+ }
118
+
119
+ .cedros-site__docs-page--article {
120
+ grid-template-columns: minmax(220px, 260px) minmax(0, 1fr) minmax(220px, 260px);
121
+ }
122
+
123
+ .cedros-site__docs-main {
124
+ min-width: 0;
125
+ }
126
+
127
+ .cedros-site__docs-sidebar {
128
+ position: sticky;
129
+ top: 0.95rem;
130
+ display: grid;
131
+ gap: 0.75rem;
132
+ }
133
+
134
+ .cedros-site__docs-sidebar-title {
135
+ margin: 0;
136
+ font-size: 0.95rem;
137
+ }
138
+
139
+ .cedros-site__docs-search {
140
+ display: grid;
141
+ gap: 0.45rem;
142
+ }
143
+
144
+ .cedros-site__docs-root-link {
145
+ font-size: 0.8rem;
146
+ text-decoration: none;
147
+ color: var(--cds-muted);
148
+ }
149
+
150
+ .cedros-site__docs-root-link:hover {
151
+ color: var(--cds-fg);
152
+ text-decoration: underline;
153
+ }
154
+
155
+ .cedros-site__docs-section {
156
+ display: grid;
157
+ gap: 0.35rem;
158
+ }
159
+
160
+ .cedros-site__docs-section-title {
161
+ margin: 0;
162
+ font-size: 0.72rem;
163
+ color: var(--cds-muted);
164
+ text-transform: uppercase;
165
+ letter-spacing: 0.03em;
166
+ }
167
+
168
+ .cedros-site__docs-section-links {
169
+ display: grid;
170
+ gap: 0.2rem;
171
+ }
172
+
173
+ .cedros-site__docs-item {
174
+ border: 1px solid transparent;
175
+ border-radius: calc(var(--cds-radius) - 2px);
176
+ padding: 0.35rem 0.48rem;
177
+ text-decoration: none;
178
+ color: var(--cds-muted);
179
+ font-size: 0.79rem;
180
+ display: inline-flex;
181
+ align-items: center;
182
+ justify-content: space-between;
183
+ gap: 0.45rem;
184
+ }
185
+
186
+ .cedros-site__docs-item:hover {
187
+ color: var(--cds-fg);
188
+ background: var(--cds-muted-bg);
189
+ border-color: var(--cds-border);
190
+ }
191
+
192
+ .cedros-site__docs-item--active {
193
+ color: var(--cds-fg);
194
+ border-color: color-mix(in srgb, var(--cds-link) 50%, var(--cds-border) 50%);
195
+ background: color-mix(in srgb, var(--cds-link) 9%, var(--cds-muted-bg) 91%);
196
+ }
197
+
198
+ .cedros-site__docs-item--depth-1 {
199
+ padding-left: 0.9rem;
200
+ }
201
+
202
+ .cedros-site__docs-item--depth-2 {
203
+ padding-left: 1.3rem;
204
+ }
205
+
206
+ .cedros-site__docs-item-badge {
207
+ border: 1px solid var(--cds-border);
208
+ border-radius: 999px;
209
+ padding: 0.05rem 0.38rem;
210
+ font-size: 0.67rem;
211
+ color: var(--cds-muted);
212
+ }
213
+
214
+ .cedros-site__article-layout {
215
+ margin-top: 0.85rem;
216
+ display: grid;
217
+ gap: 1rem;
218
+ grid-template-columns: minmax(0, 1fr) minmax(220px, 270px);
219
+ align-items: start;
220
+ }
221
+
222
+ .cedros-site__article {
223
+ min-width: 0;
224
+ }
225
+
226
+ .cedros-site__article-header {
227
+ display: grid;
228
+ gap: 0.55rem;
229
+ }
230
+
231
+ .cedros-site__prose {
232
+ margin-top: 1rem;
233
+ display: grid;
234
+ gap: 0.85rem;
235
+ line-height: 1.65;
236
+ }
237
+
238
+ .cedros-site__prose :where(h2, h3, h4) {
239
+ margin: 1rem 0 0;
240
+ line-height: 1.25;
241
+ }
242
+
243
+ .cedros-site__prose p {
244
+ margin: 0;
245
+ }
246
+
247
+ .cedros-site__prose pre {
248
+ margin: 0;
249
+ padding: 0.9rem;
250
+ border-radius: calc(var(--cds-radius) - 2px);
251
+ border: 1px solid var(--cds-border);
252
+ overflow-x: auto;
253
+ background: color-mix(in srgb, var(--cds-muted-bg) 85%, var(--cds-bg) 15%);
254
+ font-size: 0.82rem;
255
+ }
256
+
257
+ .cedros-site__prose code {
258
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
259
+ }
260
+
261
+ .cedros-site__prose :not(pre) > code {
262
+ border: 1px solid var(--cds-border);
263
+ border-radius: 0.3rem;
264
+ background: color-mix(in srgb, var(--cds-muted-bg) 85%, var(--cds-bg) 15%);
265
+ padding: 0.1rem 0.3rem;
266
+ }
267
+
268
+ .cedros-site__prose blockquote {
269
+ margin: 0;
270
+ padding: 0.6rem 0.8rem;
271
+ border-left: 3px solid var(--cds-border);
272
+ color: var(--cds-muted);
273
+ background: color-mix(in srgb, var(--cds-muted-bg) 72%, var(--cds-bg) 28%);
274
+ border-radius: calc(var(--cds-radius) - 2px);
275
+ }
276
+
277
+ .cedros-site__prose img {
278
+ max-width: 100%;
279
+ height: auto;
280
+ border-radius: calc(var(--cds-radius) - 2px);
281
+ }
282
+
283
+ .cedros-site__content-warning {
284
+ margin: 0;
285
+ color: var(--cds-muted);
286
+ border: 1px dashed var(--cds-border);
287
+ border-radius: calc(var(--cds-radius) - 2px);
288
+ padding: 0.65rem 0.8rem;
289
+ background: color-mix(in srgb, var(--cds-muted-bg) 78%, var(--cds-bg) 22%);
290
+ }
291
+
292
+ .cedros-site__toc {
293
+ position: sticky;
294
+ top: 1rem;
295
+ display: grid;
296
+ gap: 0.55rem;
297
+ }
298
+
299
+ .cedros-site__toc-title {
300
+ margin: 0;
301
+ font-size: 0.9rem;
302
+ }
303
+
304
+ .cedros-site__toc-links {
305
+ display: grid;
306
+ gap: 0.35rem;
307
+ }
308
+
309
+ .cedros-site__toc-link {
310
+ color: var(--cds-muted);
311
+ text-decoration: none;
312
+ font-size: 0.8rem;
313
+ }
314
+
315
+ .cedros-site__toc-link--depth-3 {
316
+ padding-left: 0.65rem;
317
+ }
318
+
319
+ .cedros-site__toc-link--depth-4 {
320
+ padding-left: 1.3rem;
321
+ }
322
+
323
+ .cedros-site__toc-link:hover {
324
+ color: var(--cds-fg);
325
+ }
326
+
327
+ .cedros-site__doc-footer {
328
+ margin-top: 1rem;
329
+ padding-top: 0.9rem;
330
+ border-top: 1px solid var(--cds-border);
331
+ display: inline-flex;
332
+ flex-wrap: wrap;
333
+ gap: 0.45rem;
334
+ }
335
+
336
+ .cedros-site__empty-state {
337
+ margin-top: 1rem;
338
+ }
339
+
340
+ .cedros-site__pill--active {
341
+ background: var(--cds-link);
342
+ color: var(--cds-bg);
343
+ border-color: var(--cds-link);
344
+ }
345
+
346
+ .cedros-site__filter-dimensions {
347
+ display: grid;
348
+ gap: 0.6rem;
349
+ }
350
+
351
+ .cedros-site__filter-group {
352
+ display: grid;
353
+ gap: 0.3rem;
354
+ }
355
+
356
+ .cedros-site__filter-group-label {
357
+ font-size: 0.72rem;
358
+ color: var(--cds-muted);
359
+ text-transform: uppercase;
360
+ letter-spacing: 0.03em;
361
+ }
362
+
363
+ .cedros-site__bookmark {
364
+ background: none;
365
+ border: 1px solid var(--cds-border);
366
+ border-radius: calc(var(--cds-radius) - 2px);
367
+ padding: 0.25rem 0.4rem;
368
+ cursor: pointer;
369
+ color: var(--cds-muted);
370
+ display: inline-flex;
371
+ align-items: center;
372
+ }
373
+
374
+ .cedros-site__bookmark:hover,
375
+ .cedros-site__bookmark[aria-pressed="true"] {
376
+ color: var(--cds-link);
377
+ border-color: var(--cds-link);
378
+ }
379
+
380
+ .cedros-site__search-input {
381
+ width: 100%;
382
+ }
383
+
384
+ @media (max-width: 900px) {
385
+ .cedros-site__docs-page,
386
+ .cedros-site__docs-page--article {
387
+ grid-template-columns: 1fr;
388
+ }
389
+
390
+ .cedros-site__docs-sidebar {
391
+ position: static;
392
+ }
393
+
394
+ .cedros-site__article-layout {
395
+ grid-template-columns: 1fr;
396
+ }
397
+
398
+ .cedros-site__toc {
399
+ position: static;
400
+ }
401
+ }
402
+
403
+ @media (max-width: 700px) {
404
+ .cedros-site__control-actions {
405
+ flex-wrap: wrap;
406
+ }
407
+ }
408
+
409
+ @import "./docs-styles.css";
410
+ @import "./monetization-styles.css";
@@ -0,0 +1,65 @@
1
+ export interface PaginationResult<T> {
2
+ items: T[];
3
+ page: number;
4
+ pageSize: number;
5
+ totalItems: number;
6
+ totalPages: number;
7
+ }
8
+ export interface BlogIndexEntry {
9
+ slug: string;
10
+ title: string;
11
+ excerpt?: string;
12
+ category?: string;
13
+ tags?: string[];
14
+ publishedAt?: string;
15
+ }
16
+ export interface BlogIndexQuery {
17
+ query?: string;
18
+ category?: string;
19
+ tag?: string;
20
+ sort?: "newest" | "oldest" | "title-asc" | "title-desc";
21
+ page?: number;
22
+ pageSize?: number;
23
+ dimensions?: FilterDimensionValues;
24
+ }
25
+ export interface FilterDimension {
26
+ /** Payload field name, e.g. "category", "knowledgeLevel" */
27
+ key: string;
28
+ /** Display label, e.g. "Category", "Level" */
29
+ label: string;
30
+ /** Available values, e.g. ["Beginner", "Advanced"] */
31
+ values: string[];
32
+ }
33
+ export interface FilterDimensionValues {
34
+ [dimensionKey: string]: string;
35
+ }
36
+ export interface DocsIndexEntry {
37
+ slug: string;
38
+ title: string;
39
+ description?: string;
40
+ category?: string;
41
+ tags?: string[];
42
+ lastUpdated?: string;
43
+ }
44
+ export interface DocsIndexQuery {
45
+ query?: string;
46
+ category?: string;
47
+ tag?: string;
48
+ sort?: "updated-desc" | "updated-asc" | "title-asc" | "title-desc";
49
+ page?: number;
50
+ pageSize?: number;
51
+ }
52
+ export declare function buildContentListHref(basePath: string, query: Record<string, string | number | undefined>): string;
53
+ export declare function prepareBlogIndex<T extends BlogIndexEntry>(entries: T[], query: BlogIndexQuery): PaginationResult<T>;
54
+ export declare function prepareDocsIndex<T extends DocsIndexEntry>(entries: T[], query: DocsIndexQuery): PaginationResult<T>;
55
+ export declare function collectFilterValues(entries: Array<{
56
+ category?: string;
57
+ tags?: string[];
58
+ }>): {
59
+ categories: string[];
60
+ tags: string[];
61
+ };
62
+ /** Extract unique sorted values for each dimension key from entry payloads. */
63
+ export declare function collectDimensionValues(entries: object[], dimensionKeys: string[]): Record<string, string[]>;
64
+ /** Check if an entry matches all active dimension filters. */
65
+ export declare function matchesFilterDimensions(entry: object, activeFilters: FilterDimensionValues): boolean;
@@ -0,0 +1,181 @@
1
+ export function buildContentListHref(basePath, query) {
2
+ const params = new URLSearchParams();
3
+ Object.entries(query).forEach(([key, value]) => {
4
+ if (value === undefined) {
5
+ return;
6
+ }
7
+ const normalized = `${value}`.trim();
8
+ if (!normalized) {
9
+ return;
10
+ }
11
+ params.set(key, normalized);
12
+ });
13
+ const queryString = params.toString();
14
+ return queryString ? `${basePath}?${queryString}` : basePath;
15
+ }
16
+ export function prepareBlogIndex(entries, query) {
17
+ let filtered = entries.filter((entry) => matchesBlogQuery(entry, query));
18
+ if (query.dimensions) {
19
+ const dims = query.dimensions;
20
+ filtered = filtered.filter((entry) => matchesFilterDimensions(entry, dims));
21
+ }
22
+ const sorted = [...filtered].sort((left, right) => compareBlogEntries(left, right, query.sort ?? "newest"));
23
+ return paginate(sorted, query.page, query.pageSize ?? 8);
24
+ }
25
+ export function prepareDocsIndex(entries, query) {
26
+ const filtered = entries.filter((entry) => matchesDocsQuery(entry, query));
27
+ const sorted = [...filtered].sort((left, right) => compareDocsEntries(left, right, query.sort ?? "title-asc"));
28
+ return paginate(sorted, query.page, query.pageSize ?? 10);
29
+ }
30
+ export function collectFilterValues(entries) {
31
+ const categories = new Set();
32
+ const tags = new Set();
33
+ entries.forEach((entry) => {
34
+ if (entry.category) {
35
+ categories.add(entry.category);
36
+ }
37
+ entry.tags?.forEach((tag) => tags.add(tag));
38
+ });
39
+ return {
40
+ categories: [...categories].sort((a, b) => a.localeCompare(b)),
41
+ tags: [...tags].sort((a, b) => a.localeCompare(b))
42
+ };
43
+ }
44
+ /** Extract unique sorted values for each dimension key from entry payloads. */
45
+ export function collectDimensionValues(entries, dimensionKeys) {
46
+ const result = {};
47
+ for (const key of dimensionKeys) {
48
+ result[key] = new Set();
49
+ }
50
+ for (const entry of entries) {
51
+ const record = entry;
52
+ for (const key of dimensionKeys) {
53
+ if (!(key in record))
54
+ continue;
55
+ const value = record[key];
56
+ if (typeof value === "string" && value) {
57
+ result[key].add(value);
58
+ }
59
+ else if (Array.isArray(value)) {
60
+ for (const item of value) {
61
+ if (typeof item === "string" && item) {
62
+ result[key].add(item);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ const out = {};
69
+ for (const key of dimensionKeys) {
70
+ out[key] = [...result[key]].sort((a, b) => a.localeCompare(b));
71
+ }
72
+ return out;
73
+ }
74
+ /** Check if an entry matches all active dimension filters. */
75
+ export function matchesFilterDimensions(entry, activeFilters) {
76
+ const record = entry;
77
+ for (const [key, value] of Object.entries(activeFilters)) {
78
+ if (!value)
79
+ continue;
80
+ if (!(key in record))
81
+ return false;
82
+ const field = record[key];
83
+ if (typeof field === "string") {
84
+ if (field !== value)
85
+ return false;
86
+ }
87
+ else if (Array.isArray(field)) {
88
+ if (!field.includes(value))
89
+ return false;
90
+ }
91
+ else {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ }
97
+ function matchesBlogQuery(entry, query) {
98
+ if (query.category && entry.category !== query.category) {
99
+ return false;
100
+ }
101
+ if (query.tag && !entry.tags?.includes(query.tag)) {
102
+ return false;
103
+ }
104
+ if (!query.query) {
105
+ return true;
106
+ }
107
+ const normalizedQuery = query.query.trim().toLowerCase();
108
+ if (!normalizedQuery) {
109
+ return true;
110
+ }
111
+ const haystack = [entry.title, entry.excerpt, entry.category, ...(entry.tags ?? [])].join(" ").toLowerCase();
112
+ return haystack.includes(normalizedQuery);
113
+ }
114
+ function matchesDocsQuery(entry, query) {
115
+ if (query.category && entry.category !== query.category) {
116
+ return false;
117
+ }
118
+ if (query.tag && !entry.tags?.includes(query.tag)) {
119
+ return false;
120
+ }
121
+ if (!query.query) {
122
+ return true;
123
+ }
124
+ const normalizedQuery = query.query.trim().toLowerCase();
125
+ if (!normalizedQuery) {
126
+ return true;
127
+ }
128
+ const haystack = [entry.title, entry.description, entry.category, ...(entry.tags ?? [])].join(" ").toLowerCase();
129
+ return haystack.includes(normalizedQuery);
130
+ }
131
+ function compareBlogEntries(left, right, sort) {
132
+ if (sort === "oldest") {
133
+ return compareDate(left.publishedAt, right.publishedAt) || left.title.localeCompare(right.title);
134
+ }
135
+ if (sort === "title-asc") {
136
+ return left.title.localeCompare(right.title);
137
+ }
138
+ if (sort === "title-desc") {
139
+ return right.title.localeCompare(left.title);
140
+ }
141
+ return compareDate(right.publishedAt, left.publishedAt) || left.title.localeCompare(right.title);
142
+ }
143
+ function compareDocsEntries(left, right, sort) {
144
+ if (sort === "updated-desc") {
145
+ return compareDate(right.lastUpdated, left.lastUpdated) || left.title.localeCompare(right.title);
146
+ }
147
+ if (sort === "updated-asc") {
148
+ return compareDate(left.lastUpdated, right.lastUpdated) || left.title.localeCompare(right.title);
149
+ }
150
+ if (sort === "title-desc") {
151
+ return right.title.localeCompare(left.title);
152
+ }
153
+ return left.title.localeCompare(right.title);
154
+ }
155
+ function compareDate(left, right) {
156
+ return toTimestamp(left) - toTimestamp(right);
157
+ }
158
+ function toTimestamp(value) {
159
+ const parsed = Date.parse(value ?? "");
160
+ return Number.isNaN(parsed) ? 0 : parsed;
161
+ }
162
+ function paginate(items, pageInput, pageSizeInput) {
163
+ const pageSize = sanitizePositiveInt(pageSizeInput, 10);
164
+ const totalItems = items.length;
165
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
166
+ const page = Math.min(sanitizePositiveInt(pageInput, 1), totalPages);
167
+ const start = (page - 1) * pageSize;
168
+ return {
169
+ items: items.slice(start, start + pageSize),
170
+ page,
171
+ pageSize,
172
+ totalItems,
173
+ totalPages
174
+ };
175
+ }
176
+ function sanitizePositiveInt(value, fallback) {
177
+ if (value === undefined || !Number.isFinite(value)) {
178
+ return fallback;
179
+ }
180
+ return Math.max(1, Math.floor(value));
181
+ }
@@ -0,0 +1,14 @@
1
+ export interface PaginationProps {
2
+ basePath: string;
3
+ page: number;
4
+ totalPages: number;
5
+ query: Record<string, string | number | undefined>;
6
+ }
7
+ export declare function ContentPagination({ basePath, page, totalPages, query }: PaginationProps): React.JSX.Element | null;
8
+ export declare function Breadcrumbs({ trail, className }: {
9
+ trail: Array<{
10
+ label: string;
11
+ href: string;
12
+ }>;
13
+ className?: string;
14
+ }): React.JSX.Element | null;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { buildContentListHref } from "./contentIndex.js";
3
+ export function ContentPagination({ basePath, page, totalPages, query }) {
4
+ if (totalPages <= 1) {
5
+ return null;
6
+ }
7
+ const visiblePages = buildVisiblePages(page, totalPages);
8
+ return (_jsxs("nav", { className: "cedros-site__pagination", "aria-label": "Pagination", children: [_jsx("a", { href: buildContentListHref(basePath, { ...query, page: Math.max(1, page - 1) }), className: `cedros-site__nav-link${page === 1 ? " cedros-site__nav-link--disabled" : ""}`, "aria-disabled": page === 1 ? "true" : undefined, children: "Previous" }), visiblePages.map((entryPage) => (_jsx("a", { href: buildContentListHref(basePath, { ...query, page: entryPage }), className: `cedros-site__nav-link${entryPage === page ? " cedros-site__nav-link--active" : ""}`, "aria-current": entryPage === page ? "page" : undefined, children: entryPage }, entryPage))), _jsx("a", { href: buildContentListHref(basePath, { ...query, page: Math.min(totalPages, page + 1) }), className: `cedros-site__nav-link${page === totalPages ? " cedros-site__nav-link--disabled" : ""}`, "aria-disabled": page === totalPages ? "true" : undefined, children: "Next" })] }));
9
+ }
10
+ export function Breadcrumbs({ trail, className = "cedros-site__breadcrumbs" }) {
11
+ if (trail.length === 0) {
12
+ return null;
13
+ }
14
+ return (_jsx("nav", { className: className, "aria-label": "Breadcrumb", children: trail.map((entry) => (_jsx("a", { href: entry.href, children: entry.label }, entry.href))) }));
15
+ }
16
+ function buildVisiblePages(page, totalPages) {
17
+ const start = Math.max(1, page - 2);
18
+ const end = Math.min(totalPages, page + 2);
19
+ const pages = [];
20
+ for (let current = start; current <= end; current += 1) {
21
+ pages.push(current);
22
+ }
23
+ return pages;
24
+ }