@geenius/docs 0.1.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +53 -1
  3. package/package.json +101 -13
  4. package/packages/convex/dist/index.d.ts +503 -0
  5. package/packages/convex/dist/index.js +482 -0
  6. package/packages/convex/dist/index.js.map +1 -0
  7. package/packages/react/dist/index.d.ts +439 -0
  8. package/packages/react/dist/index.js +4954 -0
  9. package/packages/react/dist/index.js.map +1 -0
  10. package/packages/react-css/{src/styles.css → dist/index.css} +183 -223
  11. package/packages/react-css/dist/index.css.map +1 -0
  12. package/packages/react-css/dist/index.d.ts +443 -0
  13. package/packages/react-css/dist/index.js +5058 -0
  14. package/packages/react-css/dist/index.js.map +1 -0
  15. package/packages/shared/dist/index.d.ts +684 -0
  16. package/packages/shared/dist/index.js +788 -0
  17. package/packages/shared/dist/index.js.map +1 -0
  18. package/packages/solidjs/dist/index.d.ts +435 -0
  19. package/packages/solidjs/dist/index.js +4584 -0
  20. package/packages/solidjs/dist/index.js.map +1 -0
  21. package/packages/solidjs-css/{src/styles.css → dist/index.css} +183 -223
  22. package/packages/solidjs-css/dist/index.css.map +1 -0
  23. package/packages/solidjs-css/dist/index.d.ts +432 -0
  24. package/packages/solidjs-css/dist/index.js +4934 -0
  25. package/packages/solidjs-css/dist/index.js.map +1 -0
  26. package/.changeset/config.json +0 -11
  27. package/.github/CODEOWNERS +0 -1
  28. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
  29. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
  30. package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
  31. package/.github/dependabot.yml +0 -11
  32. package/.github/workflows/ci.yml +0 -23
  33. package/.github/workflows/release.yml +0 -29
  34. package/.nvmrc +0 -1
  35. package/.project/ACCOUNT.yaml +0 -4
  36. package/.project/IDEAS.yaml +0 -7
  37. package/.project/PROJECT.yaml +0 -11
  38. package/.project/ROADMAP.yaml +0 -15
  39. package/CODE_OF_CONDUCT.md +0 -16
  40. package/CONTRIBUTING.md +0 -26
  41. package/SECURITY.md +0 -15
  42. package/SUPPORT.md +0 -8
  43. package/packages/convex/README.md +0 -1
  44. package/packages/convex/package.json +0 -12
  45. package/packages/convex/src/convex.config.ts +0 -3
  46. package/packages/convex/src/index.ts +0 -3
  47. package/packages/convex/src/mutations.ts +0 -270
  48. package/packages/convex/src/queries.ts +0 -175
  49. package/packages/convex/src/schema.ts +0 -55
  50. package/packages/react/README.md +0 -1
  51. package/packages/react/package.json +0 -36
  52. package/packages/react/src/DocsLayout.tsx +0 -116
  53. package/packages/react/src/DocsProvider.tsx +0 -93
  54. package/packages/react/src/RouterDocsContent.tsx +0 -148
  55. package/packages/react/src/RouterDocsLayout.tsx +0 -161
  56. package/packages/react/src/components/Breadcrumbs.tsx +0 -34
  57. package/packages/react/src/components/DocPage.tsx +0 -191
  58. package/packages/react/src/components/DocSearch.tsx +0 -140
  59. package/packages/react/src/components/DocSidebar.tsx +0 -86
  60. package/packages/react/src/components/DocsLayout.tsx +0 -62
  61. package/packages/react/src/components/EditButton.tsx +0 -26
  62. package/packages/react/src/components/PageNavigation.tsx +0 -45
  63. package/packages/react/src/components/TableOfContents.tsx +0 -46
  64. package/packages/react/src/components/VersionSelector.tsx +0 -60
  65. package/packages/react/src/components/index.ts +0 -9
  66. package/packages/react/src/hooks/index.ts +0 -8
  67. package/packages/react/src/hooks/useDocSearch.ts +0 -55
  68. package/packages/react/src/hooks/useDocs.ts +0 -57
  69. package/packages/react/src/hooks/useDocsAdmin.ts +0 -151
  70. package/packages/react/src/hooks/useTableOfContents.ts +0 -66
  71. package/packages/react/src/index.ts +0 -38
  72. package/packages/react/src/pages/DocSearchPage.tsx +0 -129
  73. package/packages/react/src/pages/DocViewPage.tsx +0 -158
  74. package/packages/react/src/pages/DocsAdminPage.tsx +0 -330
  75. package/packages/react/src/pages/DocsIndexPage.tsx +0 -172
  76. package/packages/react/src/pages/index.ts +0 -4
  77. package/packages/react/src/useDocs.ts +0 -58
  78. package/packages/react/tsup.config.ts +0 -12
  79. package/packages/react-css/README.md +0 -1
  80. package/packages/react-css/package.json +0 -37
  81. package/packages/react-css/src/DocsLayout.tsx +0 -117
  82. package/packages/react-css/src/DocsProvider.tsx +0 -93
  83. package/packages/react-css/src/RouterDocsContent.tsx +0 -60
  84. package/packages/react-css/src/RouterDocsLayout.tsx +0 -101
  85. package/packages/react-css/src/components/DocPage.tsx +0 -21
  86. package/packages/react-css/src/components/DocSearch.tsx +0 -55
  87. package/packages/react-css/src/components/DocSidebar.tsx +0 -56
  88. package/packages/react-css/src/components/DocsLayout.tsx +0 -28
  89. package/packages/react-css/src/components/common.tsx +0 -93
  90. package/packages/react-css/src/components/index.ts +0 -5
  91. package/packages/react-css/src/hooks/index.ts +0 -2
  92. package/packages/react-css/src/index.ts +0 -6
  93. package/packages/react-css/src/index.tsx +0 -3
  94. package/packages/react-css/src/pages/DocViewPage.tsx +0 -78
  95. package/packages/react-css/src/pages/DocsAdminPage.tsx +0 -101
  96. package/packages/react-css/src/pages/DocsIndexPage.tsx +0 -68
  97. package/packages/react-css/src/pages/index.ts +0 -3
  98. package/packages/react-css/src/useDocs.ts +0 -58
  99. package/packages/react-css/tsconfig.json +0 -19
  100. package/packages/react-css/tsup.config.ts +0 -10
  101. package/packages/shared/README.md +0 -1
  102. package/packages/shared/package.json +0 -31
  103. package/packages/shared/src/__tests__/docs.test.ts +0 -69
  104. package/packages/shared/src/config.ts +0 -80
  105. package/packages/shared/src/index.ts +0 -179
  106. package/packages/shared/src/providers/astro.ts +0 -94
  107. package/packages/shared/src/providers/fumadocs.ts +0 -116
  108. package/packages/shared/src/providers/internal.ts +0 -80
  109. package/packages/shared/src/types.ts +0 -73
  110. package/packages/shared/tsconfig.json +0 -18
  111. package/packages/shared/tsup.config.ts +0 -12
  112. package/packages/shared/vitest.config.ts +0 -4
  113. package/packages/solidjs/README.md +0 -1
  114. package/packages/solidjs/package.json +0 -33
  115. package/packages/solidjs/src/DocsLayout.tsx +0 -87
  116. package/packages/solidjs/src/DocsProvider.tsx +0 -95
  117. package/packages/solidjs/src/RouterDocsContent.tsx +0 -147
  118. package/packages/solidjs/src/RouterDocsLayout.tsx +0 -161
  119. package/packages/solidjs/src/components/Breadcrumbs.tsx +0 -27
  120. package/packages/solidjs/src/components/DocPage.tsx +0 -110
  121. package/packages/solidjs/src/components/DocSearch.tsx +0 -81
  122. package/packages/solidjs/src/components/DocSidebar.tsx +0 -92
  123. package/packages/solidjs/src/components/DocsLayout.tsx +0 -38
  124. package/packages/solidjs/src/components/EditButton.tsx +0 -15
  125. package/packages/solidjs/src/components/PageNavigation.tsx +0 -31
  126. package/packages/solidjs/src/components/TableOfContents.tsx +0 -41
  127. package/packages/solidjs/src/components/VersionSelector.tsx +0 -30
  128. package/packages/solidjs/src/components/index.ts +0 -9
  129. package/packages/solidjs/src/createDocs.ts +0 -62
  130. package/packages/solidjs/src/index.ts +0 -28
  131. package/packages/solidjs/src/pages/DocSearchPage.tsx +0 -72
  132. package/packages/solidjs/src/pages/DocViewPage.tsx +0 -80
  133. package/packages/solidjs/src/pages/DocsAdminPage.tsx +0 -123
  134. package/packages/solidjs/src/pages/DocsIndexPage.tsx +0 -85
  135. package/packages/solidjs/src/pages/index.ts +0 -4
  136. package/packages/solidjs/src/primitives/createDocSearch.ts +0 -42
  137. package/packages/solidjs/src/primitives/createDocs.ts +0 -35
  138. package/packages/solidjs/src/primitives/createDocsAdmin.ts +0 -63
  139. package/packages/solidjs/src/primitives/createTableOfContents.ts +0 -51
  140. package/packages/solidjs/src/primitives/index.ts +0 -4
  141. package/packages/solidjs/tsup.config.ts +0 -12
  142. package/packages/solidjs-css/README.md +0 -1
  143. package/packages/solidjs-css/package.json +0 -36
  144. package/packages/solidjs-css/src/DocsLayout.tsx +0 -106
  145. package/packages/solidjs-css/src/DocsProvider.tsx +0 -95
  146. package/packages/solidjs-css/src/RouterDocsContent.tsx +0 -54
  147. package/packages/solidjs-css/src/RouterDocsLayout.tsx +0 -104
  148. package/packages/solidjs-css/src/createDocs.ts +0 -62
  149. package/packages/solidjs-css/src/index.ts +0 -7
  150. package/packages/solidjs-css/src/index.tsx +0 -17
  151. package/packages/solidjs-css/src/pages/DocViewPage.tsx +0 -111
  152. package/packages/solidjs-css/src/pages/DocsAdminPage.tsx +0 -332
  153. package/packages/solidjs-css/src/pages/DocsIndexPage.tsx +0 -116
  154. package/packages/solidjs-css/src/pages/index.ts +0 -3
  155. package/packages/solidjs-css/src/primitives/index.ts +0 -1
  156. package/packages/solidjs-css/tsconfig.json +0 -20
  157. package/packages/solidjs-css/tsup.config.ts +0 -10
  158. package/pnpm-workspace.yaml +0 -2
@@ -1,110 +0,0 @@
1
- import type { DocPage as DocPageType } from '@geenius-docs/shared'
2
- import { slugify } from '@geenius-docs/shared'
3
-
4
- interface DocPageProps {
5
- page: DocPageType
6
- }
7
-
8
- export function DocPage(props: DocPageProps) {
9
- const renderContent = () => {
10
- const lines = props.page.content.split('\n')
11
- const elements: string[] = []
12
- let i = 0
13
- let inCode = false
14
- let codeLang = ''
15
- let codeLines: string[] = []
16
-
17
- while (i < lines.length) {
18
- const line = lines[i]
19
-
20
- if (line.startsWith('```')) {
21
- if (!inCode) {
22
- inCode = true
23
- codeLang = line.slice(3).trim()
24
- codeLines = []
25
- } else {
26
- elements.push(
27
- `<div class="group relative my-4"><div class="flex items-center justify-between rounded-t-lg bg-white/5 px-4 py-2 text-xs text-white/50"><span>${codeLang || 'code'}</span></div><pre class="overflow-x-auto rounded-b-lg bg-black/30 p-4 text-sm leading-relaxed"><code>${escapeHtml(codeLines.join('\n'))}</code></pre></div>`
28
- )
29
- inCode = false
30
- codeLang = ''
31
- }
32
- i++
33
- continue
34
- }
35
-
36
- if (inCode) { codeLines.push(line); i++; continue }
37
-
38
- const calloutMatch = line.match(/^>\s*\[!(NOTE|WARNING|TIP|IMPORTANT|CAUTION)\]/)
39
- if (calloutMatch) {
40
- const type = calloutMatch[1]
41
- const contentLines: string[] = []
42
- i++
43
- while (i < lines.length && lines[i].startsWith('>')) {
44
- contentLines.push(lines[i].replace(/^>\s?/, ''))
45
- i++
46
- }
47
- const styles: Record<string, { bg: string; border: string; icon: string; label: string }> = {
48
- NOTE: { bg: 'bg-blue-500/10', border: 'border-blue-500/30', icon: 'ℹ️', label: 'Note' },
49
- WARNING: { bg: 'bg-amber-500/10', border: 'border-amber-500/30', icon: '⚠️', label: 'Warning' },
50
- TIP: { bg: 'bg-emerald-500/10', border: 'border-emerald-500/30', icon: '💡', label: 'Tip' },
51
- IMPORTANT: { bg: 'bg-purple-500/10', border: 'border-purple-500/30', icon: '❗', label: 'Important' },
52
- CAUTION: { bg: 'bg-red-500/10', border: 'border-red-500/30', icon: '🔴', label: 'Caution' },
53
- }
54
- const s = styles[type] ?? styles.NOTE
55
- elements.push(
56
- `<div class="${s.bg} ${s.border} my-4 rounded-lg border-l-4 p-4"><p class="mb-1 text-sm font-semibold">${s.icon} ${s.label}</p><p class="text-sm leading-relaxed text-white/80">${escapeHtml(contentLines.join(' '))}</p></div>`
57
- )
58
- continue
59
- }
60
-
61
- const headingMatch = line.match(/^(#{1,4})\s+(.+)$/)
62
- if (headingMatch) {
63
- const level = headingMatch[1].length
64
- const text = headingMatch[2]
65
- const id = slugify(text)
66
- const classes: Record<number, string> = {
67
- 1: 'text-3xl font-bold mt-8 mb-4',
68
- 2: 'text-2xl font-bold mt-8 mb-3 pb-2 border-b border-white/10',
69
- 3: 'text-xl font-semibold mt-6 mb-2',
70
- 4: 'text-lg font-medium mt-4 mb-2',
71
- }
72
- elements.push(`<h${level} id="${id}" class="${classes[level]} scroll-mt-20"><a href="#${id}" class="hover:text-indigo-400 transition-colors">${escapeHtml(text)}</a></h${level}>`)
73
- i++
74
- continue
75
- }
76
-
77
- if (line.startsWith('>')) {
78
- const quoteLines: string[] = []
79
- while (i < lines.length && lines[i].startsWith('>')) {
80
- quoteLines.push(lines[i].replace(/^>\s?/, ''))
81
- i++
82
- }
83
- elements.push(`<blockquote class="my-4 border-l-4 border-indigo-500/40 bg-white/5 py-3 pl-4 pr-4 text-white/70 italic rounded-r-lg">${escapeHtml(quoteLines.join(' '))}</blockquote>`)
84
- continue
85
- }
86
-
87
- if (!line.trim()) { i++; continue }
88
-
89
- const formatted = escapeHtml(line)
90
- .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
91
- .replace(/\*(.+?)\*/g, '<em>$1</em>')
92
- .replace(/`(.+?)`/g, '<code class="rounded bg-white/10 px-1.5 py-0.5 text-sm text-indigo-300">$1</code>')
93
- .replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2" class="text-indigo-400 hover:text-indigo-300 underline underline-offset-2">$1</a>')
94
-
95
- elements.push(`<p class="my-3 leading-relaxed text-white/80">${formatted}</p>`)
96
- i++
97
- }
98
-
99
- return elements.join('')
100
- }
101
-
102
- return <article class="prose-custom max-w-none" innerHTML={renderContent()} />
103
- }
104
-
105
- function escapeHtml(text: string): string {
106
- return text
107
- .replace(/&/g, '&amp;')
108
- .replace(/</g, '&lt;')
109
- .replace(/>/g, '&gt;')
110
- }
@@ -1,81 +0,0 @@
1
- import { createSignal, createEffect, For, Show, onCleanup } from 'solid-js'
2
- import type { SearchResult } from '@geenius-docs/shared'
3
- import { highlightMatch } from '@geenius-docs/shared'
4
-
5
- interface DocSearchProps {
6
- results: SearchResult[]; query: string; onQuery: (q: string) => void
7
- onSelect: (result: SearchResult) => void; isOpen: boolean; onClose: () => void
8
- }
9
-
10
- export function DocSearch(props: DocSearchProps) {
11
- const [activeIndex, setActiveIndex] = createSignal(0)
12
- let inputRef: HTMLInputElement | undefined
13
-
14
- createEffect(() => {
15
- if (props.isOpen) { inputRef?.focus(); setActiveIndex(0) }
16
- })
17
-
18
- createEffect(() => { props.results; setActiveIndex(0) })
19
-
20
- const handleKeyDown = (e: KeyboardEvent) => {
21
- if (e.key === 'ArrowDown') { e.preventDefault(); setActiveIndex((i) => Math.min(i + 1, props.results.length - 1)) }
22
- else if (e.key === 'ArrowUp') { e.preventDefault(); setActiveIndex((i) => Math.max(i - 1, 0)) }
23
- else if (e.key === 'Enter' && props.results[activeIndex()]) { e.preventDefault(); props.onSelect(props.results[activeIndex()]) }
24
- else if (e.key === 'Escape') { e.preventDefault(); props.onClose() }
25
- }
26
-
27
- return (
28
- <Show when={props.isOpen}>
29
- <div class="fixed inset-0 z-50 flex items-start justify-center pt-[15vh]" onClick={() => props.onClose()}>
30
- <div class="fixed inset-0 bg-black/60 backdrop-blur-sm" />
31
- <div class="relative z-10 w-full max-w-xl overflow-hidden rounded-2xl border border-white/10 bg-[#0d0e14] shadow-2xl" onClick={(e) => e.stopPropagation()}>
32
- <div class="flex items-center gap-3 border-b border-white/10 px-5 py-4">
33
- <svg class="h-5 w-5 shrink-0 text-white/30" viewBox="0 0 20 20" fill="currentColor">
34
- <path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
35
- </svg>
36
- <input
37
- ref={inputRef}
38
- type="text"
39
- value={props.query}
40
- onInput={(e) => props.onQuery(e.currentTarget.value)}
41
- onKeyDown={handleKeyDown}
42
- placeholder="Search documentation…"
43
- class="flex-1 bg-transparent text-sm text-white placeholder-white/30 outline-none"
44
- />
45
- <kbd class="rounded border border-white/10 bg-white/5 px-1.5 py-0.5 text-[11px] text-white/30">ESC</kbd>
46
- </div>
47
- <div class="max-h-80 overflow-y-auto p-2">
48
- <Show when={props.results.length === 0 && props.query.trim()}>
49
- <div class="flex flex-col items-center py-10 text-center text-white/30">
50
- <p class="text-sm">No results for "{props.query}"</p>
51
- </div>
52
- </Show>
53
- <Show when={props.results.length === 0 && !props.query.trim()}>
54
- <div class="py-8 text-center text-sm text-white/30">Start typing to search…</div>
55
- </Show>
56
- <For each={props.results}>
57
- {(result, idx) => (
58
- <button
59
- type="button"
60
- onClick={() => props.onSelect(result)}
61
- class={`flex w-full flex-col gap-1 rounded-xl px-4 py-3 text-left transition-colors ${
62
- idx() === activeIndex() ? 'bg-indigo-500/15 text-white' : 'text-white/70 hover:bg-white/5'
63
- }`}
64
- >
65
- <div class="flex items-center gap-2">
66
- <span class="rounded bg-indigo-500/20 px-1.5 py-0.5 text-[10px] font-medium text-indigo-300">{result.sectionTitle}</span>
67
- <span class="text-sm font-medium">{result.pageTitle}</span>
68
- </div>
69
- <p class="truncate text-xs text-white/40">{highlightMatch(result.highlight, props.query)}</p>
70
- </button>
71
- )}
72
- </For>
73
- </div>
74
- <div class="flex items-center gap-4 border-t border-white/5 px-5 py-2.5 text-[11px] text-white/20">
75
- <span>↑↓ navigate</span><span>↵ select</span><span>esc close</span>
76
- </div>
77
- </div>
78
- </div>
79
- </Show>
80
- )
81
- }
@@ -1,92 +0,0 @@
1
- import { createSignal, For, Show } from 'solid-js'
2
- import type { DocPage, DocSection } from '@geenius-docs/shared'
3
-
4
- interface DocSidebarProps {
5
- sections: (DocSection & { pages?: DocPage[]; pageCount?: number })[]
6
- currentPageId?: string
7
- onNavigate: (page: DocPage, section: DocSection) => void
8
- }
9
-
10
- export function DocSidebar(props: DocSidebarProps) {
11
- const [expandedIds, setExpandedIds] = createSignal<Set<string>>(new Set())
12
-
13
- const toggle = (id: string) => {
14
- setExpandedIds((prev) => {
15
- const next = new Set(prev)
16
- if (next.has(id)) next.delete(id)
17
- else next.add(id)
18
- return next
19
- })
20
- }
21
-
22
- const topLevel = () => props.sections.filter((s) => !s.parentId)
23
- const childrenOf = (parentId: string) => props.sections.filter((s) => s.parentId === parentId)
24
-
25
- const renderSection = (section: DocSection & { pages?: DocPage[]; pageCount?: number }, depth: number) => {
26
- const children = () => childrenOf(section.id)
27
- const isExpanded = () => expandedIds().has(section.id)
28
- const pages = () => section.pages ?? []
29
- const hasContent = () => children().length > 0 || pages().length > 0
30
-
31
- return (
32
- <div style={{ "padding-left": `${depth * 12}px` }} class="mb-1">
33
- <button
34
- type="button"
35
- onClick={() => toggle(section.id)}
36
- class="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition-colors hover:bg-white/5"
37
- >
38
- <Show when={section.icon}>
39
- <span class="text-base">{section.icon}</span>
40
- </Show>
41
- <span class="flex-1 truncate">{section.title}</span>
42
- <Show when={section.pageCount != null}>
43
- <span class="text-xs tabular-nums opacity-50">{section.pageCount}</span>
44
- </Show>
45
- <Show when={hasContent()}>
46
- <svg
47
- class={`h-3.5 w-3.5 shrink-0 transition-transform ${isExpanded() ? 'rotate-90' : ''}`}
48
- viewBox="0 0 16 16"
49
- fill="currentColor"
50
- >
51
- <path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="2" fill="none" />
52
- </svg>
53
- </Show>
54
- </button>
55
-
56
- <Show when={isExpanded()}>
57
- <div class="ml-2 border-l border-white/10 pl-2">
58
- <For each={pages()}>
59
- {(page) => (
60
- <button
61
- type="button"
62
- onClick={() => props.onNavigate(page, section)}
63
- class={`flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-left text-sm transition-colors ${
64
- props.currentPageId === page.id
65
- ? 'bg-indigo-500/20 text-indigo-300 font-medium'
66
- : 'text-white/60 hover:text-white/90 hover:bg-white/5'
67
- }`}
68
- >
69
- <span class="truncate">{page.title}</span>
70
- </button>
71
- )}
72
- </For>
73
- <For each={children()}>
74
- {(child) => renderSection(child, depth + 1)}
75
- </For>
76
- </div>
77
- </Show>
78
- </div>
79
- )
80
- }
81
-
82
- return (
83
- <nav class="flex flex-col gap-0.5 py-4">
84
- <div class="px-4 pb-3 text-xs font-semibold uppercase tracking-widest text-white/40">
85
- Documentation
86
- </div>
87
- <For each={topLevel()}>
88
- {(s) => renderSection(s, 0)}
89
- </For>
90
- </nav>
91
- )
92
- }
@@ -1,38 +0,0 @@
1
- import { Show } from 'solid-js'
2
- import type { DocPage, DocSection, TocItem, BreadcrumbItem } from '@geenius-docs/shared'
3
- import { DocSidebar } from './DocSidebar'
4
- import { TableOfContents } from './TableOfContents'
5
- import { Breadcrumbs } from './Breadcrumbs'
6
- import type { JSX } from 'solid-js'
7
-
8
- interface DocsLayoutProps {
9
- sections: (DocSection & { pages?: DocPage[] })[]
10
- toc?: TocItem[]; activeHeadingId?: string; breadcrumbs?: BreadcrumbItem[]
11
- currentPageId?: string; onNavigate: (page: DocPage, section: DocSection) => void
12
- children: JSX.Element
13
- }
14
-
15
- export function DocsLayout(props: DocsLayoutProps) {
16
- return (
17
- <div class="flex min-h-screen bg-[#090a0f] text-white">
18
- <aside class="sticky top-0 hidden h-screen w-[260px] shrink-0 overflow-y-auto border-r border-white/5 bg-[#0b0c12] lg:block">
19
- <DocSidebar sections={props.sections} currentPageId={props.currentPageId} onNavigate={props.onNavigate} />
20
- </aside>
21
- <main class="flex-1 overflow-hidden">
22
- <div class="mx-auto flex max-w-6xl gap-8 px-6 py-8 lg:px-10">
23
- <div class="min-w-0 flex-1">
24
- <Show when={props.breadcrumbs && props.breadcrumbs.length > 0}>
25
- <div class="mb-6"><Breadcrumbs items={props.breadcrumbs!} /></div>
26
- </Show>
27
- {props.children}
28
- </div>
29
- <Show when={props.toc && props.toc.length > 0}>
30
- <aside class="hidden w-[220px] shrink-0 xl:block">
31
- <TableOfContents toc={props.toc!} activeId={props.activeHeadingId} />
32
- </aside>
33
- </Show>
34
- </div>
35
- </main>
36
- </div>
37
- )
38
- }
@@ -1,15 +0,0 @@
1
- import { Show } from 'solid-js'
2
-
3
- export function EditButton(props: { pageSlug: string; editUrl?: string }) {
4
- return (
5
- <Show when={props.editUrl}>
6
- <a href={`${props.editUrl!.replace(/\/$/, '')}/${props.pageSlug}.mdx`} target="_blank" rel="noopener noreferrer"
7
- class="inline-flex items-center gap-1.5 rounded-lg border border-white/10 px-3 py-1.5 text-xs text-white/40 transition-colors hover:border-white/20 hover:text-white/60">
8
- <svg class="h-3.5 w-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor">
9
- <path d="M11.5 1.5l3 3-9 9H2.5v-3l9-9z" stroke-width="1.5" stroke-linejoin="round" />
10
- </svg>
11
- Edit this page
12
- </a>
13
- </Show>
14
- )
15
- }
@@ -1,31 +0,0 @@
1
- import { Show } from 'solid-js'
2
-
3
- interface PageNavigationProps {
4
- prev?: { title: string; href: string }
5
- next?: { title: string; href: string }
6
- }
7
-
8
- export function PageNavigation(props: PageNavigationProps) {
9
- return (
10
- <Show when={props.prev || props.next}>
11
- <div class="mt-12 flex items-stretch gap-4 border-t border-white/10 pt-8">
12
- <Show when={props.prev} fallback={<div class="flex-1" />}>
13
- {(prev) => (
14
- <a href={prev().href} class="group flex flex-1 flex-col rounded-xl border border-white/10 p-4 transition-all hover:border-indigo-500/40 hover:bg-white/5">
15
- <span class="text-xs text-white/40 group-hover:text-indigo-400 transition-colors">← Previous</span>
16
- <span class="mt-1 text-sm font-medium text-white/80 group-hover:text-white transition-colors truncate">{prev().title}</span>
17
- </a>
18
- )}
19
- </Show>
20
- <Show when={props.next} fallback={<div class="flex-1" />}>
21
- {(next) => (
22
- <a href={next().href} class="group flex flex-1 flex-col items-end rounded-xl border border-white/10 p-4 text-right transition-all hover:border-indigo-500/40 hover:bg-white/5">
23
- <span class="text-xs text-white/40 group-hover:text-indigo-400 transition-colors">Next →</span>
24
- <span class="mt-1 text-sm font-medium text-white/80 group-hover:text-white transition-colors truncate">{next().title}</span>
25
- </a>
26
- )}
27
- </Show>
28
- </div>
29
- </Show>
30
- )
31
- }
@@ -1,41 +0,0 @@
1
- import { For, Show } from 'solid-js'
2
- import type { TocItem } from '@geenius-docs/shared'
3
-
4
- interface TableOfContentsProps { toc: TocItem[]; activeId?: string }
5
-
6
- function TocLink(props: { item: TocItem; activeId?: string; depth?: number }) {
7
- const depth = () => props.depth ?? 0
8
- return (
9
- <>
10
- <a
11
- href={`#${props.item.id}`}
12
- class={`block truncate border-l-2 py-1 text-[13px] transition-all duration-200 ${
13
- props.activeId === props.item.id
14
- ? 'border-indigo-500 text-indigo-300 font-medium'
15
- : 'border-transparent text-white/40 hover:text-white/70 hover:border-white/20'
16
- }`}
17
- style={{ "padding-left": `${12 + depth() * 12}px` }}
18
- >
19
- {props.item.text}
20
- </a>
21
- <For each={props.item.children}>
22
- {(child) => <TocLink item={child} activeId={props.activeId} depth={depth() + 1} />}
23
- </For>
24
- </>
25
- )
26
- }
27
-
28
- export function TableOfContents(props: TableOfContentsProps) {
29
- return (
30
- <Show when={props.toc.length > 0}>
31
- <nav class="sticky top-24">
32
- <h4 class="mb-3 text-xs font-semibold uppercase tracking-widest text-white/40">On this page</h4>
33
- <div class="flex flex-col">
34
- <For each={props.toc}>
35
- {(item) => <TocLink item={item} activeId={props.activeId} />}
36
- </For>
37
- </div>
38
- </nav>
39
- </Show>
40
- )
41
- }
@@ -1,30 +0,0 @@
1
- import { createSignal, Show, For } from 'solid-js'
2
-
3
- interface VersionSelectorProps { versions: string[]; current: string; onSelect: (v: string) => void }
4
-
5
- export function VersionSelector(props: VersionSelectorProps) {
6
- const [isOpen, setIsOpen] = createSignal(false)
7
-
8
- return (
9
- <Show when={props.versions.length > 1}>
10
- <div class="relative">
11
- <button type="button" onClick={() => setIsOpen(!isOpen())} class="flex items-center gap-1.5 rounded-lg border border-white/10 bg-white/5 px-3 py-1.5 text-xs font-medium text-white/60 transition-colors hover:border-indigo-500/30">
12
- <span>v{props.current}</span>
13
- <svg class={`h-3 w-3 transition-transform ${isOpen() ? 'rotate-180' : ''}`} viewBox="0 0 16 16"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="2" fill="none" /></svg>
14
- </button>
15
- <Show when={isOpen()}>
16
- <div class="absolute right-0 top-full z-20 mt-1 min-w-[120px] overflow-hidden rounded-lg border border-white/10 bg-[#111218] shadow-xl">
17
- <For each={props.versions}>
18
- {(v) => (
19
- <button type="button" onClick={() => { props.onSelect(v); setIsOpen(false) }}
20
- class={`flex w-full items-center px-3 py-2 text-xs transition-colors ${v === props.current ? 'bg-indigo-500/15 text-indigo-300' : 'text-white/60 hover:bg-white/5'}`}>
21
- v{v}{v === props.current && <span class="ml-auto text-[10px]">✓</span>}
22
- </button>
23
- )}
24
- </For>
25
- </div>
26
- </Show>
27
- </div>
28
- </Show>
29
- )
30
- }
@@ -1,9 +0,0 @@
1
- export { DocSidebar } from './DocSidebar'
2
- export { DocPage } from './DocPage'
3
- export { TableOfContents } from './TableOfContents'
4
- export { Breadcrumbs } from './Breadcrumbs'
5
- export { PageNavigation } from './PageNavigation'
6
- export { DocSearch } from './DocSearch'
7
- export { VersionSelector } from './VersionSelector'
8
- export { EditButton } from './EditButton'
9
- export { DocsLayout } from './DocsLayout'
@@ -1,62 +0,0 @@
1
- // @geenius-docs/solidjs — src/createDocs.ts
2
-
3
- import { createSignal, createMemo, onMount } from 'solid-js'
4
- import type { DocsPage, DocsSidebar, DocsSearchResult, DocsProvider } from '@geenius-docs/shared'
5
-
6
- /**
7
- * createDocs — SolidJS primitive wrapping a DocsProvider for docs rendering.
8
- * SolidJS equivalent of useDocs hook.
9
- */
10
- export function createDocs(provider: DocsProvider) {
11
- const [sidebar, setSidebar] = createSignal<DocsSidebar | null>(null)
12
- const [currentPage, setCurrentPage] = createSignal<DocsPage | null>(null)
13
- const [searchResults, setSearchResults] = createSignal<DocsSearchResult[]>([])
14
- const [isLoading, setIsLoading] = createSignal(false)
15
- const [searchQuery, setSearchQuery] = createSignal('')
16
-
17
- // Load sidebar on mount
18
- onMount(async () => {
19
- const sb = await provider.getSidebar()
20
- setSidebar(sb)
21
- })
22
-
23
- const loadPage = async (slug: string) => {
24
- setIsLoading(true)
25
- try {
26
- const page = await provider.getPage(slug)
27
- setCurrentPage(page)
28
- } finally {
29
- setIsLoading(false)
30
- }
31
- }
32
-
33
- const search = async (query: string) => {
34
- setSearchQuery(query)
35
- if (!query.trim()) {
36
- setSearchResults([])
37
- return
38
- }
39
- const results = await provider.search(query)
40
- setSearchResults(results)
41
- }
42
-
43
- const navigation = createMemo(() => {
44
- const page = currentPage()
45
- if (!page) return { prev: null, next: null }
46
- return {
47
- prev: page.prev ?? null,
48
- next: page.next ?? null,
49
- }
50
- })
51
-
52
- return {
53
- sidebar,
54
- currentPage,
55
- navigation,
56
- isLoading,
57
- searchResults,
58
- searchQuery,
59
- loadPage,
60
- search,
61
- }
62
- }
@@ -1,28 +0,0 @@
1
- // Primitives
2
- export { createDocs } from './primitives/createDocs'
3
- export { createDocSearch } from './primitives/createDocSearch'
4
- export { createDocsAdmin } from './primitives/createDocsAdmin'
5
- export { createTableOfContents } from './primitives/createTableOfContents'
6
-
7
- // Components
8
- export { DocSidebar } from './components/DocSidebar'
9
- export { DocPage } from './components/DocPage'
10
- export { TableOfContents } from './components/TableOfContents'
11
- export { Breadcrumbs } from './components/Breadcrumbs'
12
- export { PageNavigation } from './components/PageNavigation'
13
- export { DocSearch } from './components/DocSearch'
14
- export { VersionSelector } from './components/VersionSelector'
15
- export { EditButton } from './components/EditButton'
16
- export { DocsLayout } from './components/DocsLayout'
17
-
18
- // Pages
19
- export { DocsIndexPage } from './pages/DocsIndexPage'
20
- export { DocViewPage } from './pages/DocViewPage'
21
- export { DocSearchPage } from './pages/DocSearchPage'
22
- export { DocsAdminPage } from './pages/DocsAdminPage'
23
-
24
- // Re-export shared types
25
- export type {
26
- DocPage as DocPageType, DocSection, SearchResult, TocItem,
27
- BreadcrumbItem, DocsConfig, DocAccess, DocStatus,
28
- } from '@geenius-docs/shared'
@@ -1,72 +0,0 @@
1
- import { createMemo, Show, For } from 'solid-js'
2
- import type { DocPage, DocSection, SearchResult } from '@geenius-docs/shared'
3
- import { buildDocsIndex, searchDocs, highlightMatch } from '@geenius-docs/shared'
4
- import { createDocSearch } from '../primitives/createDocSearch'
5
-
6
- interface DocSearchPageProps {
7
- tree: () => (DocSection & { pages: DocPage[]; pageCount: number })[] | undefined
8
- onSelectPage?: (page: DocPage, section: DocSection) => void
9
- }
10
-
11
- export function DocSearchPage(props: DocSearchPageProps) {
12
- const sections = createMemo(() => props.tree() ?? [])
13
- const flatPages = createMemo(() => sections().flatMap(s => s.pages ?? []))
14
-
15
- const searchFn = (q: string): SearchResult[] => {
16
- const index = buildDocsIndex(flatPages(), sections())
17
- return searchDocs(q, index)
18
- }
19
-
20
- const { results, isSearching, query, setQuery } = createDocSearch(searchFn)
21
-
22
- return (
23
- <Show when={props.tree() !== undefined} fallback={
24
- <div class="min-h-screen bg-[#090a0f] px-6 py-16"><div class="mx-auto max-w-2xl"><div class="mb-8 h-12 animate-pulse rounded-xl bg-white/5" /></div></div>
25
- }>
26
- <div class="min-h-screen bg-[#090a0f] text-white">
27
- <div class="mx-auto max-w-2xl px-6 py-16">
28
- <h1 class="mb-8 text-2xl font-bold">Search Documentation</h1>
29
- <div class="relative mb-8">
30
- <input type="text" value={query()} onInput={e => setQuery(e.currentTarget.value)} placeholder="Type to search…" autofocus
31
- class="w-full rounded-xl border border-white/10 bg-white/5 py-3.5 pl-12 pr-4 text-sm text-white placeholder-white/30 outline-none focus:border-indigo-500/40" />
32
- <Show when={isSearching()}>
33
- <div class="absolute right-4 top-1/2 -translate-y-1/2"><div class="h-4 w-4 animate-spin rounded-full border-2 border-white/10 border-t-indigo-400" /></div>
34
- </Show>
35
- </div>
36
- <Show when={results().length > 0}>
37
- <div class="space-y-2">
38
- <For each={results()}>
39
- {(result) => {
40
- const section = () => sections().find(s => s.slug === result.sectionSlug)
41
- const page = () => flatPages().find(p => p.id === result.pageId)
42
- return (
43
- <button type="button" onClick={() => { const p = page(); const s = section(); if (p && s && props.onSelectPage) props.onSelectPage(p, s) }}
44
- class="flex w-full flex-col gap-1.5 rounded-xl border border-white/5 bg-white/[0.02] p-4 text-left transition-all hover:border-indigo-500/20 hover:bg-white/[0.05]">
45
- <div class="flex items-center gap-2">
46
- <span class="rounded bg-indigo-500/20 px-2 py-0.5 text-[10px] font-medium text-indigo-300">{result.sectionTitle}</span>
47
- <span class="text-sm font-medium text-white/90">{result.pageTitle}</span>
48
- </div>
49
- <p class="text-xs leading-relaxed text-white/40">{highlightMatch(result.highlight, query())}</p>
50
- </button>
51
- )
52
- }}
53
- </For>
54
- </div>
55
- </Show>
56
- <Show when={query().trim() && results().length === 0 && !isSearching()}>
57
- <div class="flex flex-col items-center py-16 text-center">
58
- <div class="mb-4 text-5xl opacity-30">🔍</div>
59
- <h3 class="text-lg font-medium text-white/60">No results found</h3>
60
- </div>
61
- </Show>
62
- <Show when={!query().trim()}>
63
- <div class="flex flex-col items-center py-16 text-center">
64
- <div class="mb-4 text-5xl opacity-20">📖</div>
65
- <p class="text-sm text-white/30">Start typing to search across all documentation</p>
66
- </div>
67
- </Show>
68
- </div>
69
- </div>
70
- </Show>
71
- )
72
- }