@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,259 @@
1
+ /* ─── Syntax highlighting (GitHub-light inspired, dark-mode aware) ──── */
2
+
3
+ .cedros-site__prose .hljs {
4
+ color: var(--cds-fg);
5
+ background: transparent;
6
+ }
7
+
8
+ .hljs-comment,
9
+ .hljs-quote {
10
+ color: color-mix(in srgb, var(--cds-muted) 85%, var(--cds-fg) 15%);
11
+ font-style: italic;
12
+ }
13
+
14
+ .hljs-keyword,
15
+ .hljs-selector-tag,
16
+ .hljs-type {
17
+ color: #cf222e;
18
+ }
19
+
20
+ .hljs-string,
21
+ .hljs-addition {
22
+ color: #0a3069;
23
+ }
24
+
25
+ .hljs-number,
26
+ .hljs-literal,
27
+ .hljs-variable,
28
+ .hljs-template-variable {
29
+ color: #0550ae;
30
+ }
31
+
32
+ .hljs-title,
33
+ .hljs-section,
34
+ .hljs-attr {
35
+ color: #953800;
36
+ }
37
+
38
+ .hljs-built_in,
39
+ .hljs-name {
40
+ color: #8250df;
41
+ }
42
+
43
+ .hljs-deletion {
44
+ color: #82071e;
45
+ background: #ffebe9;
46
+ }
47
+
48
+ @media (prefers-color-scheme: dark) {
49
+ .hljs-keyword,
50
+ .hljs-selector-tag,
51
+ .hljs-type {
52
+ color: #ff7b72;
53
+ }
54
+
55
+ .hljs-string,
56
+ .hljs-addition {
57
+ color: #a5d6ff;
58
+ }
59
+
60
+ .hljs-number,
61
+ .hljs-literal,
62
+ .hljs-variable,
63
+ .hljs-template-variable {
64
+ color: #79c0ff;
65
+ }
66
+
67
+ .hljs-title,
68
+ .hljs-section,
69
+ .hljs-attr {
70
+ color: #ffa657;
71
+ }
72
+
73
+ .hljs-built_in,
74
+ .hljs-name {
75
+ color: #d2a8ff;
76
+ }
77
+
78
+ .hljs-deletion {
79
+ color: #ffdcd7;
80
+ background: #67060c;
81
+ }
82
+ }
83
+
84
+ /* ─── Code block copy button ──── */
85
+
86
+ .cedros-site__code-block {
87
+ position: relative;
88
+ }
89
+
90
+ .cedros-site__code-copy {
91
+ position: absolute;
92
+ top: 0.45rem;
93
+ right: 0.45rem;
94
+ padding: 0.2rem 0.5rem;
95
+ font-size: 0.7rem;
96
+ border: 1px solid var(--cds-border);
97
+ border-radius: calc(var(--cds-radius) - 2px);
98
+ background: var(--cds-bg);
99
+ color: var(--cds-muted);
100
+ cursor: pointer;
101
+ opacity: 0;
102
+ transition: opacity 0.15s;
103
+ }
104
+
105
+ .cedros-site__code-block:hover .cedros-site__code-copy {
106
+ opacity: 1;
107
+ }
108
+
109
+ .cedros-site__code-copy:hover {
110
+ color: var(--cds-fg);
111
+ border-color: var(--cds-fg);
112
+ }
113
+
114
+ /* ─── Callout / alert styles (remark-github-blockquote-alert) ──── */
115
+
116
+ .markdown-alert {
117
+ margin: 0;
118
+ padding: 0.65rem 0.85rem;
119
+ border-left: 3px solid var(--cds-border);
120
+ border-radius: calc(var(--cds-radius) - 2px);
121
+ background: color-mix(in srgb, var(--cds-muted-bg) 72%, var(--cds-bg) 28%);
122
+ }
123
+
124
+ .markdown-alert .markdown-alert-title {
125
+ font-weight: 600;
126
+ font-size: 0.82rem;
127
+ margin-bottom: 0.35rem;
128
+ display: flex;
129
+ align-items: center;
130
+ gap: 0.35rem;
131
+ }
132
+
133
+ .markdown-alert-note {
134
+ border-left-color: #0969da;
135
+ }
136
+
137
+ .markdown-alert-tip {
138
+ border-left-color: #1a7f37;
139
+ }
140
+
141
+ .markdown-alert-important {
142
+ border-left-color: #8250df;
143
+ }
144
+
145
+ .markdown-alert-warning {
146
+ border-left-color: #9a6700;
147
+ }
148
+
149
+ .markdown-alert-caution {
150
+ border-left-color: #cf222e;
151
+ }
152
+
153
+ /* ─── Prose table styles ──── */
154
+
155
+ .cedros-site__prose table {
156
+ width: 100%;
157
+ border-collapse: collapse;
158
+ font-size: 0.85rem;
159
+ }
160
+
161
+ .cedros-site__prose th,
162
+ .cedros-site__prose td {
163
+ padding: 0.45rem 0.65rem;
164
+ border: 1px solid var(--cds-border);
165
+ text-align: left;
166
+ }
167
+
168
+ .cedros-site__prose th {
169
+ background: var(--cds-muted-bg);
170
+ font-weight: 600;
171
+ }
172
+
173
+ /* ─── Collapsible sidebar sections ──── */
174
+
175
+ .cedros-site__docs-section summary {
176
+ cursor: pointer;
177
+ list-style: none;
178
+ user-select: none;
179
+ }
180
+
181
+ .cedros-site__docs-section summary::-webkit-details-marker {
182
+ display: none;
183
+ }
184
+
185
+ .cedros-site__docs-section summary::before {
186
+ content: "▸ ";
187
+ font-size: 0.65em;
188
+ vertical-align: middle;
189
+ }
190
+
191
+ .cedros-site__docs-section[open] summary::before {
192
+ content: "▾ ";
193
+ }
194
+
195
+ /* ─── Mobile sidebar drawer ──── */
196
+
197
+ .cedros-site__sidebar-toggle {
198
+ display: none;
199
+ width: 100%;
200
+ padding: 0.55rem 0.75rem;
201
+ font-size: 0.85rem;
202
+ font-weight: 600;
203
+ border: 1px solid var(--cds-border);
204
+ border-radius: var(--cds-radius);
205
+ background: var(--cds-bg);
206
+ color: var(--cds-fg);
207
+ cursor: pointer;
208
+ text-align: left;
209
+ }
210
+
211
+ .cedros-site__sidebar-overlay {
212
+ display: none;
213
+ }
214
+
215
+ @media (max-width: 900px) {
216
+ .cedros-site__sidebar-toggle {
217
+ display: block;
218
+ }
219
+
220
+ .cedros-site__docs-sidebar {
221
+ display: none;
222
+ }
223
+
224
+ .cedros-site__docs-sidebar--open {
225
+ display: grid;
226
+ position: fixed;
227
+ inset: 0;
228
+ z-index: 100;
229
+ overflow-y: auto;
230
+ max-width: 320px;
231
+ box-shadow: 4px 0 12px rgba(0, 0, 0, 0.15);
232
+ }
233
+
234
+ .cedros-site__sidebar-overlay {
235
+ display: block;
236
+ position: fixed;
237
+ inset: 0;
238
+ z-index: 99;
239
+ background: rgba(0, 0, 0, 0.3);
240
+ }
241
+ }
242
+
243
+ /* ─── TOC scroll-spy active link ──── */
244
+
245
+ .cedros-site__toc-link--active {
246
+ color: var(--cds-link);
247
+ font-weight: 600;
248
+ }
249
+
250
+ /* ─── Autolinked heading anchors ──── */
251
+
252
+ .cedros-site__prose :where(h2, h3, h4) a {
253
+ color: inherit;
254
+ text-decoration: none;
255
+ }
256
+
257
+ .cedros-site__prose :where(h2, h3, h4) a:hover {
258
+ text-decoration: underline;
259
+ }
@@ -0,0 +1,18 @@
1
+ import type { DocsIndexEntry } from "./contentIndex.js";
2
+ export interface DocsSidebarItem {
3
+ key: string;
4
+ label: string;
5
+ href: string;
6
+ isActive?: boolean;
7
+ depth?: 0 | 1 | 2;
8
+ badge?: string;
9
+ }
10
+ export interface DocsSidebarSection {
11
+ key: string;
12
+ label: string;
13
+ items: DocsSidebarItem[];
14
+ /** When true, section renders collapsed by default in the sidebar. */
15
+ collapsed?: boolean;
16
+ }
17
+ export declare function buildDocsSidebarSections(docs: DocsIndexEntry[], basePath?: string): DocsSidebarSection[];
18
+ export declare function withActiveDocsSidebar(sections: DocsSidebarSection[], currentPath?: string): DocsSidebarSection[];
@@ -0,0 +1,50 @@
1
+ import { isRouteActive, normalizeRoutePath } from "./routing.js";
2
+ export function buildDocsSidebarSections(docs, basePath = "/docs") {
3
+ const grouped = new Map();
4
+ docs.forEach((doc) => {
5
+ const sectionLabel = doc.category ?? "Overview";
6
+ const sectionKey = sectionLabel.toLowerCase().replace(/\s+/gu, "-");
7
+ const current = grouped.get(sectionKey) ?? { label: sectionLabel, items: [] };
8
+ current.items.push({
9
+ key: doc.slug,
10
+ label: doc.title,
11
+ href: `${basePath}/${doc.slug}`
12
+ });
13
+ grouped.set(sectionKey, current);
14
+ });
15
+ return [...grouped.entries()]
16
+ .map(([key, value]) => ({
17
+ key,
18
+ label: value.label,
19
+ items: [...value.items].sort((left, right) => left.label.localeCompare(right.label))
20
+ }))
21
+ .sort((left, right) => left.label.localeCompare(right.label));
22
+ }
23
+ export function withActiveDocsSidebar(sections, currentPath) {
24
+ if (!currentPath) {
25
+ return sections.map((section) => ({
26
+ ...section,
27
+ items: section.items.map((item) => ({
28
+ ...item,
29
+ isActive: item.isActive ?? false
30
+ }))
31
+ }));
32
+ }
33
+ const candidateLengths = sections
34
+ .flatMap((section) => section.items)
35
+ .filter((item) => item.isActive === undefined && isRouteActive(item.href, currentPath))
36
+ .map((item) => normalizeRoutePath(item.href).length);
37
+ const longestCandidateLength = candidateLengths.length > 0 ? Math.max(...candidateLengths) : 0;
38
+ return sections.map((section) => ({
39
+ ...section,
40
+ items: section.items.map((item) => {
41
+ const inferredActive = longestCandidateLength > 0 &&
42
+ normalizeRoutePath(item.href).length === longestCandidateLength &&
43
+ isRouteActive(item.href, currentPath);
44
+ return {
45
+ ...item,
46
+ isActive: item.isActive ?? inferredActive
47
+ };
48
+ })
49
+ }));
50
+ }
@@ -0,0 +1,28 @@
1
+ export { SiteLayout, type SiteLayoutProps, type SiteNavigationItem } from "./SiteLayout.js";
2
+ export { TopNav, type TopNavProps } from "./TopNav.js";
3
+ export { SiteFooter, type SiteFooterProps, type SiteFooterLink } from "./SiteFooter.js";
4
+ export { DashboardShell, type DashboardShellProps, type DashboardNavItem } from "./DashboardShell.js";
5
+ export { DashboardOverviewTemplate, type DashboardOverviewTemplateProps, type DashboardPanel, type DashboardStat } from "./DashboardOverviewTemplate.js";
6
+ export { isRouteActive, normalizeRoutePath, withActiveRouteState, type RouteAwareItem, type RouteMatcherOptions } from "./routing.js";
7
+ export { buildContentListHref, collectFilterValues, collectDimensionValues, matchesFilterDimensions, prepareBlogIndex, prepareDocsIndex, type BlogIndexEntry, type BlogIndexQuery, type DocsIndexEntry, type DocsIndexQuery, type FilterDimension, type FilterDimensionValues, type PaginationResult } from "./contentIndex.js";
8
+ export { buildDocsSidebarSections, withActiveDocsSidebar, type DocsSidebarItem, type DocsSidebarSection } from "./docsNavigation.js";
9
+ export { MarkdownContent, type MarkdownContentProps } from "./MarkdownContent.js";
10
+ export { extractTocFromMarkdown, type TocEntry } from "./tocExtractor.js";
11
+ export { DocsSidebar, type DocsSidebarProps } from "./DocsSidebar.js";
12
+ export { TocScrollSpy, type TocScrollSpyProps } from "./tocScrollSpy.js";
13
+ export { CodeBlock, type CodeBlockProps } from "./codeBlock.js";
14
+ export { Breadcrumbs, ContentPagination, type PaginationProps } from "./contentUi.js";
15
+ export { HomePageTemplate, type HomePageTemplateProps, type HomeFeature } from "./HomePageTemplate.js";
16
+ export { DocsIndexTemplate, DocArticleTemplate, type DocsIndexTemplateProps, type DocArticleTemplateProps, type DocsIndexItem } from "./DocsTemplates.js";
17
+ export { BlogIndexTemplate, BlogPostTemplate, type BlogIndexTemplateProps, type BlogPostTemplateProps, type BlogPostSummary, type BlogTippingConfig, type BlogPaywallConfig } from "./BlogTemplates.js";
18
+ export { TipWidget } from "./tipControls.js";
19
+ export type { TipWidgetProps, TipCurrency, TipParams, TipPayClient } from "./tipControls.js";
20
+ export { ContentPaywall } from "./paywallControls.js";
21
+ export type { ContentPaywallProps, PaywallPrice, PaywallPayClient } from "./paywallControls.js";
22
+ export { BlogSearchInput, FilterDimensionChips, BookmarkButton } from "./blogControls.js";
23
+ export type { BlogSearchInputProps, FilterDimensionChipsProps, BookmarkButtonProps } from "./blogControls.js";
24
+ export { SolanaMicropayments, createSolanaTipClient, detectSolanaWallet, SOL_CURRENCY, USDC_CURRENCY, type SolanaMicropaymentsProps, } from "./solanaMicropayments.js";
25
+ export { ensureRecipientAta } from "./solanaAtaSetup.js";
26
+ export { LegalPageTemplate, type LegalPageTemplateProps } from "./LegalPageTemplate.js";
27
+ export { ContactPageTemplate, type ContactPageTemplateProps, type ContactDetail } from "./ContactPageTemplate.js";
28
+ export { NotFoundTemplate, type NotFoundTemplateProps } from "./NotFoundTemplate.js";
@@ -0,0 +1,25 @@
1
+ export { SiteLayout } from "./SiteLayout.js";
2
+ export { TopNav } from "./TopNav.js";
3
+ export { SiteFooter } from "./SiteFooter.js";
4
+ export { DashboardShell } from "./DashboardShell.js";
5
+ export { DashboardOverviewTemplate } from "./DashboardOverviewTemplate.js";
6
+ export { isRouteActive, normalizeRoutePath, withActiveRouteState } from "./routing.js";
7
+ export { buildContentListHref, collectFilterValues, collectDimensionValues, matchesFilterDimensions, prepareBlogIndex, prepareDocsIndex } from "./contentIndex.js";
8
+ export { buildDocsSidebarSections, withActiveDocsSidebar } from "./docsNavigation.js";
9
+ export { MarkdownContent } from "./MarkdownContent.js";
10
+ export { extractTocFromMarkdown } from "./tocExtractor.js";
11
+ export { DocsSidebar } from "./DocsSidebar.js";
12
+ export { TocScrollSpy } from "./tocScrollSpy.js";
13
+ export { CodeBlock } from "./codeBlock.js";
14
+ export { Breadcrumbs, ContentPagination } from "./contentUi.js";
15
+ export { HomePageTemplate } from "./HomePageTemplate.js";
16
+ export { DocsIndexTemplate, DocArticleTemplate } from "./DocsTemplates.js";
17
+ export { BlogIndexTemplate, BlogPostTemplate } from "./BlogTemplates.js";
18
+ export { TipWidget } from "./tipControls.js";
19
+ export { ContentPaywall } from "./paywallControls.js";
20
+ export { BlogSearchInput, FilterDimensionChips, BookmarkButton } from "./blogControls.js";
21
+ export { SolanaMicropayments, createSolanaTipClient, detectSolanaWallet, SOL_CURRENCY, USDC_CURRENCY, } from "./solanaMicropayments.js";
22
+ export { ensureRecipientAta } from "./solanaAtaSetup.js";
23
+ export { LegalPageTemplate } from "./LegalPageTemplate.js";
24
+ export { ContactPageTemplate } from "./ContactPageTemplate.js";
25
+ export { NotFoundTemplate } from "./NotFoundTemplate.js";
@@ -0,0 +1,154 @@
1
+ /* TipWidget styles */
2
+ .cedros-site__tip-widget {
3
+ display: grid;
4
+ gap: 0.75rem;
5
+ border: 1px solid var(--cds-border);
6
+ border-radius: var(--cds-radius);
7
+ padding: 1.25rem;
8
+ background: var(--cds-bg);
9
+ }
10
+
11
+ .cedros-site__tip-title {
12
+ margin: 0;
13
+ font-size: 1.05rem;
14
+ }
15
+
16
+ .cedros-site__tip-description {
17
+ margin: 0;
18
+ font-size: 0.82rem;
19
+ color: var(--cds-muted);
20
+ }
21
+
22
+ .cedros-site__tip-currency {
23
+ width: 100%;
24
+ border: 1px solid var(--cds-border);
25
+ border-radius: calc(var(--cds-radius) - 2px);
26
+ background: color-mix(in srgb, var(--cds-bg) 90%, var(--cds-muted-bg) 10%);
27
+ color: var(--cds-fg);
28
+ height: 2.25rem;
29
+ padding: 0 0.6rem;
30
+ }
31
+
32
+ .cedros-site__tip-presets {
33
+ display: inline-flex;
34
+ flex-wrap: wrap;
35
+ gap: 0.35rem;
36
+ }
37
+
38
+ .cedros-site__tip-amount input {
39
+ width: 100%;
40
+ border: 1px solid var(--cds-border);
41
+ border-radius: calc(var(--cds-radius) - 2px);
42
+ background: color-mix(in srgb, var(--cds-bg) 90%, var(--cds-muted-bg) 10%);
43
+ color: var(--cds-fg);
44
+ height: 2.25rem;
45
+ padding: 0 0.6rem;
46
+ }
47
+
48
+ .cedros-site__tip-submit {
49
+ border: none;
50
+ border-radius: calc(var(--cds-radius) - 2px);
51
+ background: var(--cds-link);
52
+ color: var(--cds-bg);
53
+ padding: 0.55rem 1.2rem;
54
+ font-size: 0.85rem;
55
+ cursor: pointer;
56
+ }
57
+
58
+ .cedros-site__tip-submit:hover {
59
+ opacity: 0.9;
60
+ }
61
+
62
+ .cedros-site__tip-submit:disabled {
63
+ opacity: 0.5;
64
+ cursor: not-allowed;
65
+ }
66
+
67
+ .cedros-site__tip-status {
68
+ margin: 0;
69
+ font-size: 0.82rem;
70
+ }
71
+
72
+ .cedros-site__tip-status--success {
73
+ color: #16a34a;
74
+ }
75
+
76
+ .cedros-site__tip-status--error {
77
+ color: #dc2626;
78
+ }
79
+
80
+ /* ContentPaywall styles */
81
+ .cedros-site__paywall {
82
+ position: relative;
83
+ }
84
+
85
+ .cedros-site__paywall-fade {
86
+ position: relative;
87
+ overflow: hidden;
88
+ max-height: 18rem;
89
+ }
90
+
91
+ .cedros-site__paywall-fade::after {
92
+ content: "";
93
+ position: absolute;
94
+ bottom: 0;
95
+ left: 0;
96
+ right: 0;
97
+ height: 6rem;
98
+ background: linear-gradient(to bottom, transparent, var(--cds-bg));
99
+ pointer-events: none;
100
+ }
101
+
102
+ .cedros-site__paywall-lock {
103
+ display: flex;
104
+ flex-direction: column;
105
+ align-items: center;
106
+ gap: 0.6rem;
107
+ padding: 2rem 1rem;
108
+ color: var(--cds-muted);
109
+ }
110
+
111
+ .cedros-site__paywall-lock p {
112
+ margin: 0;
113
+ font-size: 0.9rem;
114
+ }
115
+
116
+ .cedros-site__paywall-cta {
117
+ display: grid;
118
+ gap: 0.75rem;
119
+ justify-items: center;
120
+ padding: 1.25rem;
121
+ border: 1px solid var(--cds-border);
122
+ border-radius: var(--cds-radius);
123
+ background: var(--cds-muted-bg);
124
+ margin-top: 0.75rem;
125
+ }
126
+
127
+ .cedros-site__paywall-price {
128
+ margin: 0;
129
+ font-size: 1.1rem;
130
+ font-weight: 600;
131
+ }
132
+
133
+ .cedros-site__paywall-actions {
134
+ display: inline-flex;
135
+ flex-wrap: wrap;
136
+ gap: 0.5rem;
137
+ justify-content: center;
138
+ }
139
+
140
+ /* Metered paywall banner */
141
+ .cedros-site__metered-banner {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ gap: 0.5rem;
146
+ margin-top: 1.25rem;
147
+ padding: 0.65rem 1rem;
148
+ border: 1px solid var(--cds-border);
149
+ border-radius: var(--cds-radius);
150
+ background: var(--cds-muted-bg);
151
+ color: var(--cds-muted);
152
+ font-size: 0.82rem;
153
+ text-align: center;
154
+ }
@@ -0,0 +1,22 @@
1
+ export interface PaywallPrice {
2
+ amount: number;
3
+ currency: string;
4
+ }
5
+ /** Provided by @cedros/pay-react (or any compatible implementation). */
6
+ export interface PaywallPayClient {
7
+ purchase?: () => Promise<void>;
8
+ subscribe?: () => Promise<void>;
9
+ useCredits?: () => Promise<void>;
10
+ creditsBalance?: number;
11
+ }
12
+ export interface ContentPaywallProps {
13
+ mode: "preview" | "locked";
14
+ previewContent?: string;
15
+ previewHtml?: string;
16
+ allowUnsafeHtmlFallback?: boolean;
17
+ price?: PaywallPrice;
18
+ payClient: PaywallPayClient;
19
+ purchaseLabel?: string;
20
+ subscriptionLabel?: string;
21
+ }
22
+ export declare function ContentPaywall({ mode, previewContent, previewHtml, allowUnsafeHtmlFallback, price, payClient, purchaseLabel, subscriptionLabel }: ContentPaywallProps): React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { MarkdownContent } from "./MarkdownContent.js";
4
+ export function ContentPaywall({ mode, previewContent, previewHtml, allowUnsafeHtmlFallback, price, payClient, purchaseLabel = "Purchase", subscriptionLabel = "Subscribe" }) {
5
+ const showCredits = payClient.useCredits &&
6
+ payClient.creditsBalance !== undefined &&
7
+ payClient.creditsBalance > 0;
8
+ return (_jsxs("div", { className: "cedros-site__paywall", children: [mode === "preview" && (_jsx("div", { className: "cedros-site__paywall-fade", children: _jsx(MarkdownContent, { bodyMarkdown: previewContent, bodyHtml: previewHtml, allowUnsafeHtmlFallback: allowUnsafeHtmlFallback }) })), mode === "locked" && (_jsxs("div", { className: "cedros-site__paywall-lock", children: [_jsxs("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0110 0v4" })] }), _jsx("p", { children: "Unlock this article" })] })), _jsxs("div", { className: "cedros-site__paywall-cta", children: [price && price.amount > 0 && (_jsxs("p", { className: "cedros-site__paywall-price", children: [price.amount, " ", price.currency] })), _jsxs("div", { className: "cedros-site__paywall-actions", children: [payClient.purchase && (_jsx("button", { type: "button", className: "cedros-site__tip-submit", onClick: () => void payClient.purchase(), children: purchaseLabel })), payClient.subscribe && (_jsx("button", { type: "button", className: "cedros-site__pill", onClick: () => void payClient.subscribe(), children: subscriptionLabel })), showCredits && (_jsxs("button", { type: "button", className: "cedros-site__pill", onClick: () => void payClient.useCredits(), children: ["Use Credits (", payClient.creditsBalance, ")"] }))] })] })] }));
9
+ }
@@ -0,0 +1,12 @@
1
+ export interface RouteMatcherOptions {
2
+ exact?: boolean;
3
+ }
4
+ export interface RouteAwareItem {
5
+ route: string;
6
+ isActive?: boolean;
7
+ }
8
+ export declare function normalizeRoutePath(route: string): string;
9
+ export declare function isRouteActive(route: string, currentPath: string, options?: RouteMatcherOptions): boolean;
10
+ export declare function withActiveRouteState<T extends RouteAwareItem>(items: T[], currentPath: string, options?: RouteMatcherOptions): Array<T & {
11
+ isActive: boolean;
12
+ }>;
@@ -0,0 +1,36 @@
1
+ export function normalizeRoutePath(route) {
2
+ if (!route) {
3
+ return "/";
4
+ }
5
+ const [pathOnly] = route.split(/[?#]/u, 1);
6
+ if (!pathOnly || pathOnly === "/") {
7
+ return "/";
8
+ }
9
+ const withLeadingSlash = pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
10
+ return withLeadingSlash.replace(/\/+$/u, "") || "/";
11
+ }
12
+ export function isRouteActive(route, currentPath, options = {}) {
13
+ const normalizedRoute = normalizeRoutePath(route);
14
+ const normalizedCurrentPath = normalizeRoutePath(currentPath);
15
+ if (options.exact || normalizedRoute === "/") {
16
+ return normalizedRoute === normalizedCurrentPath;
17
+ }
18
+ return (normalizedCurrentPath === normalizedRoute ||
19
+ normalizedCurrentPath.startsWith(`${normalizedRoute}/`));
20
+ }
21
+ export function withActiveRouteState(items, currentPath, options = {}) {
22
+ const candidates = items
23
+ .filter((item) => item.isActive === undefined && isRouteActive(item.route, currentPath, options))
24
+ .map((item) => normalizeRoutePath(item.route).length);
25
+ const longestCandidateLength = candidates.length > 0 ? Math.max(...candidates) : 0;
26
+ return items.map((item) => {
27
+ const normalizedRouteLength = normalizeRoutePath(item.route).length;
28
+ const inferredActive = longestCandidateLength > 0 &&
29
+ normalizedRouteLength === longestCandidateLength &&
30
+ isRouteActive(item.route, currentPath, options);
31
+ return {
32
+ ...item,
33
+ isActive: item.isActive ?? inferredActive
34
+ };
35
+ });
36
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Helper for admin to pre-create Associated Token Accounts (ATAs) for
3
+ * SPL token tipping. Browser wallets expose signAndSendTransaction
4
+ * rather than raw Signer, so we manually check + create.
5
+ *
6
+ * @param recipient - Solana wallet address of the tip recipient
7
+ * @param mint - SPL token mint address (e.g. USDC)
8
+ * @param rpcEndpoint - Solana RPC URL, defaults to mainnet-beta
9
+ * @returns The ATA address as a base58 string
10
+ */
11
+ export declare function ensureRecipientAta(recipient: string, mint: string, rpcEndpoint?: string): Promise<string>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Helper for admin to pre-create Associated Token Accounts (ATAs) for
3
+ * SPL token tipping. Browser wallets expose signAndSendTransaction
4
+ * rather than raw Signer, so we manually check + create.
5
+ *
6
+ * @param recipient - Solana wallet address of the tip recipient
7
+ * @param mint - SPL token mint address (e.g. USDC)
8
+ * @param rpcEndpoint - Solana RPC URL, defaults to mainnet-beta
9
+ * @returns The ATA address as a base58 string
10
+ */
11
+ export async function ensureRecipientAta(recipient, mint, rpcEndpoint = "https://api.mainnet-beta.solana.com") {
12
+ const { Connection, PublicKey, Transaction } = await import("@solana/web3.js");
13
+ const { getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, } = await import("@solana/spl-token");
14
+ const connection = new Connection(rpcEndpoint, "confirmed");
15
+ const recipientPubkey = new PublicKey(recipient);
16
+ const mintPubkey = new PublicKey(mint);
17
+ const ata = await getAssociatedTokenAddress(mintPubkey, recipientPubkey);
18
+ const info = await connection.getAccountInfo(ata);
19
+ if (info) {
20
+ // ATA already exists
21
+ return ata.toBase58();
22
+ }
23
+ // Create ATA — requires connected wallet to sign + pay fees
24
+ const wallet = window.solana;
25
+ if (!wallet)
26
+ throw new Error("No Solana wallet detected");
27
+ if (!wallet.isConnected)
28
+ await wallet.connect();
29
+ if (!wallet.publicKey)
30
+ throw new Error("Wallet not connected");
31
+ const payerPubkey = new PublicKey(wallet.publicKey.toString());
32
+ const tx = new Transaction().add(createAssociatedTokenAccountInstruction(payerPubkey, ata, recipientPubkey, mintPubkey));
33
+ tx.feePayer = payerPubkey;
34
+ tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
35
+ const { signature } = await wallet.signAndSendTransaction(tx);
36
+ await connection.confirmTransaction(signature, "confirmed");
37
+ return ata.toBase58();
38
+ }