@fjell/client-api 4.4.11 → 4.4.13
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.
- package/docs/docs.config.ts +77 -0
- package/docs/package.json +5 -6
- package/docs/public/examples-README.md +237 -0
- package/docs/src/main.tsx +6 -4
- package/docs/src/types.d.ts +44 -0
- package/package.json +10 -6
- package/docs/src/App.css +0 -1237
- package/docs/src/App.test.tsx +0 -49
- package/docs/src/App.tsx +0 -513
package/docs/src/App.test.tsx
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react'
|
|
2
|
-
import { expect, test, vi } from 'vitest'
|
|
3
|
-
import App from './App'
|
|
4
|
-
|
|
5
|
-
// Mock fetch for testing
|
|
6
|
-
global.fetch = vi.fn()
|
|
7
|
-
|
|
8
|
-
const mockFetch = fetch as any
|
|
9
|
-
|
|
10
|
-
test('renders App component', () => {
|
|
11
|
-
// Setup fetch mocks
|
|
12
|
-
mockFetch.mockImplementation((url: string) => {
|
|
13
|
-
if (url.includes('package.json')) {
|
|
14
|
-
return Promise.resolve({
|
|
15
|
-
ok: true,
|
|
16
|
-
json: () => Promise.resolve({ version: '4.4.9' })
|
|
17
|
-
})
|
|
18
|
-
}
|
|
19
|
-
return Promise.resolve({
|
|
20
|
-
ok: false
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
render(<App />)
|
|
25
|
-
|
|
26
|
-
// Check if the loading text appears initially
|
|
27
|
-
expect(screen.getByText(/Loading Client API Documentation/i)).toBeInTheDocument()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test('renders header with correct branding', () => {
|
|
31
|
-
mockFetch.mockImplementation((url: string) => {
|
|
32
|
-
if (url.includes('package.json')) {
|
|
33
|
-
return Promise.resolve({
|
|
34
|
-
ok: true,
|
|
35
|
-
json: () => Promise.resolve({ version: '4.4.9' })
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
return Promise.resolve({
|
|
39
|
-
ok: false
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
render(<App />)
|
|
44
|
-
|
|
45
|
-
// Check for Fjell Client API branding
|
|
46
|
-
expect(screen.getByText('Fjell')).toBeInTheDocument()
|
|
47
|
-
expect(screen.getByText('Client API')).toBeInTheDocument()
|
|
48
|
-
expect(screen.getByText('HTTP client library for modern applications')).toBeInTheDocument()
|
|
49
|
-
})
|
package/docs/src/App.tsx
DELETED
|
@@ -1,513 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import ReactMarkdown from 'react-markdown'
|
|
3
|
-
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
|
4
|
-
import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'
|
|
5
|
-
import remarkGfm from 'remark-gfm'
|
|
6
|
-
import './App.css'
|
|
7
|
-
|
|
8
|
-
interface DocumentSection {
|
|
9
|
-
id: string;
|
|
10
|
-
title: string;
|
|
11
|
-
subtitle: string;
|
|
12
|
-
file: string;
|
|
13
|
-
content?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const documentSections: DocumentSection[] = [
|
|
17
|
-
{ id: 'overview', title: 'Foundation', subtitle: 'Core concepts & client patterns', file: '/client-api/README.md' },
|
|
18
|
-
{ id: 'getting-started', title: 'Getting Started', subtitle: 'Your first HTTP client setup', file: '/client-api/examples-README.md' },
|
|
19
|
-
{ id: 'examples', title: 'Examples', subtitle: 'API patterns & usage scenarios', file: '/client-api/examples-README.md' },
|
|
20
|
-
{ id: 'api-reference', title: 'API Reference', subtitle: 'Complete API documentation', file: '/client-api/api-reference.md' }
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
const App: React.FC = () => {
|
|
24
|
-
const [currentSection, setCurrentSection] = useState('overview')
|
|
25
|
-
const [documents, setDocuments] = useState<{ [key: string]: string }>({})
|
|
26
|
-
const [loading, setLoading] = useState(true)
|
|
27
|
-
const [sidebarOpen, setSidebarOpen] = useState(false)
|
|
28
|
-
const [version, setVersion] = useState<string>('4.4.9')
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
const loadDocuments = async () => {
|
|
32
|
-
const loadedDocs: { [key: string]: string } = {}
|
|
33
|
-
|
|
34
|
-
for (const section of documentSections) {
|
|
35
|
-
try {
|
|
36
|
-
const response = await fetch(section.file)
|
|
37
|
-
|
|
38
|
-
if (response.ok) {
|
|
39
|
-
loadedDocs[section.id] = await response.text()
|
|
40
|
-
} else {
|
|
41
|
-
// Fallback content for missing files
|
|
42
|
-
loadedDocs[section.id] = getFallbackContent(section.id)
|
|
43
|
-
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error(`Error loading ${section.file}:`, error)
|
|
46
|
-
loadedDocs[section.id] = getFallbackContent(section.id)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
setDocuments(loadedDocs)
|
|
51
|
-
setLoading(false)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const loadVersion = async () => {
|
|
55
|
-
try {
|
|
56
|
-
const response = await fetch('/client-api/package.json')
|
|
57
|
-
if (response.ok) {
|
|
58
|
-
const packageData = await response.json()
|
|
59
|
-
setVersion(packageData.version)
|
|
60
|
-
console.log('Version loaded:', packageData.version)
|
|
61
|
-
} else {
|
|
62
|
-
console.error('Failed to fetch package.json:', response.status)
|
|
63
|
-
setVersion('4.4.9') // Fallback version
|
|
64
|
-
}
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Error loading version:', error)
|
|
67
|
-
setVersion('4.4.9') // Fallback version
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
loadDocuments()
|
|
72
|
-
loadVersion()
|
|
73
|
-
}, [])
|
|
74
|
-
|
|
75
|
-
const getFallbackContent = (sectionId: string): string => {
|
|
76
|
-
switch (sectionId) {
|
|
77
|
-
case 'overview':
|
|
78
|
-
return `# Fjell Client API
|
|
79
|
-
|
|
80
|
-
A comprehensive HTTP client library for the Fjell ecosystem.
|
|
81
|
-
The Client API provides powerful abstractions for HTTP-based data operations,
|
|
82
|
-
making it easy to build robust client applications that consume REST APIs.
|
|
83
|
-
|
|
84
|
-
## Installation
|
|
85
|
-
|
|
86
|
-
\`\`\`bash
|
|
87
|
-
npm install @fjell/client-api
|
|
88
|
-
\`\`\`
|
|
89
|
-
|
|
90
|
-
## Quick Start
|
|
91
|
-
|
|
92
|
-
\`\`\`typescript
|
|
93
|
-
import { createPItemApi, createCItemApi } from '@fjell/client-api'
|
|
94
|
-
|
|
95
|
-
// Configure API endpoints
|
|
96
|
-
const apiConfig = {
|
|
97
|
-
baseUrl: 'https://api.example.com',
|
|
98
|
-
headers: { 'Authorization': 'Bearer token' }
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Create Primary Item API (independent entities)
|
|
102
|
-
const userApi = createPItemApi<User, 'user'>('user', ['users'], apiConfig)
|
|
103
|
-
|
|
104
|
-
// Create Contained Item API (hierarchical entities)
|
|
105
|
-
const taskApi = createCItemApi<Task, 'task', 'user'>('task', ['users', 'tasks'], apiConfig)
|
|
106
|
-
|
|
107
|
-
// Basic operations
|
|
108
|
-
const users = await userApi.all(query)
|
|
109
|
-
const user = await userApi.create(userData)
|
|
110
|
-
const tasks = await taskApi.all(query, [userId]) // Location-based query
|
|
111
|
-
\`\`\`
|
|
112
|
-
|
|
113
|
-
## Key Features
|
|
114
|
-
|
|
115
|
-
- **HTTP-based Operations**: Complete CRUD operations over HTTP
|
|
116
|
-
- **Type-safe APIs**: Full TypeScript support with generic type parameters
|
|
117
|
-
- **Hierarchical Data**: Support for nested resource relationships
|
|
118
|
-
- **Business Logic**: Actions and facets for complex operations
|
|
119
|
-
- **Authentication**: Built-in support for various auth patterns
|
|
120
|
-
- **Error Handling**: Comprehensive error handling and retry logic
|
|
121
|
-
|
|
122
|
-
## Architecture
|
|
123
|
-
|
|
124
|
-
The Client API is built around two main concepts:
|
|
125
|
-
|
|
126
|
-
### Primary Items (PItemApi)
|
|
127
|
-
Independent entities that exist at the top level of your API hierarchy.
|
|
128
|
-
|
|
129
|
-
### Contained Items (CItemApi)
|
|
130
|
-
Entities that belong to parent resources and require location context.
|
|
131
|
-
|
|
132
|
-
This design mirrors RESTful API patterns while providing powerful abstractions for complex business operations.`
|
|
133
|
-
|
|
134
|
-
case 'getting-started':
|
|
135
|
-
return `# Getting Started with Fjell Client API
|
|
136
|
-
|
|
137
|
-
Learn how to set up and use the Fjell Client API for HTTP-based data operations.
|
|
138
|
-
|
|
139
|
-
## Installation
|
|
140
|
-
|
|
141
|
-
\`\`\`bash
|
|
142
|
-
npm install @fjell/client-api
|
|
143
|
-
\`\`\`
|
|
144
|
-
|
|
145
|
-
## Basic Configuration
|
|
146
|
-
|
|
147
|
-
\`\`\`typescript
|
|
148
|
-
import { createPItemApi, createCItemApi } from '@fjell/client-api'
|
|
149
|
-
|
|
150
|
-
const config = {
|
|
151
|
-
baseUrl: 'https://api.example.com',
|
|
152
|
-
headers: {
|
|
153
|
-
'Content-Type': 'application/json',
|
|
154
|
-
'Authorization': 'Bearer your-token'
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
\`\`\`
|
|
158
|
-
|
|
159
|
-
## Your First API
|
|
160
|
-
|
|
161
|
-
\`\`\`typescript
|
|
162
|
-
// Define your data types
|
|
163
|
-
interface User {
|
|
164
|
-
id: string
|
|
165
|
-
name: string
|
|
166
|
-
email: string
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Create API instance
|
|
170
|
-
const userApi = createPItemApi<User, 'user'>('user', ['users'], config)
|
|
171
|
-
|
|
172
|
-
// Use the API
|
|
173
|
-
const users = await userApi.all()
|
|
174
|
-
const user = await userApi.create({ name: 'John', email: 'john@example.com' })
|
|
175
|
-
\`\`\`
|
|
176
|
-
|
|
177
|
-
See the Examples section for more detailed patterns and use cases.`
|
|
178
|
-
|
|
179
|
-
case 'examples':
|
|
180
|
-
return `# Examples
|
|
181
|
-
|
|
182
|
-
Comprehensive examples demonstrating various Client API patterns.
|
|
183
|
-
|
|
184
|
-
## Available Examples
|
|
185
|
-
|
|
186
|
-
### Simple Example
|
|
187
|
-
Basic CRUD operations with Primary and Contained APIs.
|
|
188
|
-
|
|
189
|
-
### Multi-Level Keys
|
|
190
|
-
Complex hierarchical data structures with nested relationships.
|
|
191
|
-
|
|
192
|
-
### Enterprise Example
|
|
193
|
-
Full business application with multiple interconnected entities.
|
|
194
|
-
|
|
195
|
-
Run examples locally:
|
|
196
|
-
|
|
197
|
-
\`\`\`bash
|
|
198
|
-
npx tsx examples/simple-example.ts
|
|
199
|
-
npx tsx examples/multi-level-keys.ts
|
|
200
|
-
npx tsx examples/enterprise-example.ts
|
|
201
|
-
\`\`\`
|
|
202
|
-
|
|
203
|
-
Each example includes detailed documentation and demonstrates different aspects of the Client API.`
|
|
204
|
-
|
|
205
|
-
case 'api-reference':
|
|
206
|
-
return `# API Reference
|
|
207
|
-
|
|
208
|
-
Complete reference for all Client API interfaces and methods.
|
|
209
|
-
|
|
210
|
-
## PItemApi<V, S>
|
|
211
|
-
|
|
212
|
-
Primary Item API for independent entities.
|
|
213
|
-
|
|
214
|
-
### Methods
|
|
215
|
-
|
|
216
|
-
- \`all(query?: ItemQuery): Promise<V[]>\`
|
|
217
|
-
- \`create(item: Partial<Item<S>>): Promise<V>\`
|
|
218
|
-
- \`get(key: PriKey<S>): Promise<V>\`
|
|
219
|
-
- \`update(key: PriKey<S>, updates: Partial<Item<S>>): Promise<V>\`
|
|
220
|
-
- \`remove(key: PriKey<S>): Promise<boolean>\`
|
|
221
|
-
- \`action(key: PriKey<S>, action: string, body?: any): Promise<any>\`
|
|
222
|
-
- \`facet(key: PriKey<S>, facet: string, params?: any): Promise<any>\`
|
|
223
|
-
|
|
224
|
-
## CItemApi<V, S, L1, L2, L3, L4, L5>
|
|
225
|
-
|
|
226
|
-
Contained Item API for hierarchical entities.
|
|
227
|
-
|
|
228
|
-
### Methods
|
|
229
|
-
|
|
230
|
-
All PItemApi methods plus location-aware variants:
|
|
231
|
-
|
|
232
|
-
- \`all(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V[]>\`
|
|
233
|
-
- \`create(item: Partial<Item<S>>, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V>\`
|
|
234
|
-
|
|
235
|
-
And more...`
|
|
236
|
-
|
|
237
|
-
default:
|
|
238
|
-
return `# ${sectionId}
|
|
239
|
-
|
|
240
|
-
Documentation for this section is being prepared.`
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const currentContent = documents[currentSection] || ''
|
|
245
|
-
|
|
246
|
-
const toggleSidebar = () => {
|
|
247
|
-
setSidebarOpen(!sidebarOpen)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return (
|
|
251
|
-
<div className="app">
|
|
252
|
-
<header className="header">
|
|
253
|
-
<div className="header-container">
|
|
254
|
-
<div className="brand">
|
|
255
|
-
<h1 className="brand-title">
|
|
256
|
-
<span className="brand-fjell">Fjell</span>{' '}
|
|
257
|
-
<span className="brand-client-api">Client API</span>
|
|
258
|
-
</h1>
|
|
259
|
-
<p className="brand-tagline">
|
|
260
|
-
HTTP client library for modern applications
|
|
261
|
-
</p>
|
|
262
|
-
</div>
|
|
263
|
-
|
|
264
|
-
<div className="header-actions">
|
|
265
|
-
<a
|
|
266
|
-
href="https://github.com/getfjell/client-api"
|
|
267
|
-
className="header-link"
|
|
268
|
-
target="_blank"
|
|
269
|
-
rel="noopener noreferrer"
|
|
270
|
-
>
|
|
271
|
-
GitHub
|
|
272
|
-
</a>
|
|
273
|
-
<a
|
|
274
|
-
href={`https://www.npmjs.com/package/@fjell/client-api/v/${version}`}
|
|
275
|
-
className="version-badge"
|
|
276
|
-
target="_blank"
|
|
277
|
-
rel="noopener noreferrer"
|
|
278
|
-
>
|
|
279
|
-
v{version}
|
|
280
|
-
</a>
|
|
281
|
-
<button className="menu-toggle" onClick={toggleSidebar}>
|
|
282
|
-
<div className="menu-line"></div>
|
|
283
|
-
<div className="menu-line"></div>
|
|
284
|
-
<div className="menu-line"></div>
|
|
285
|
-
</button>
|
|
286
|
-
</div>
|
|
287
|
-
</div>
|
|
288
|
-
</header>
|
|
289
|
-
|
|
290
|
-
<div className="layout">
|
|
291
|
-
<aside className={`sidebar ${sidebarOpen ? 'sidebar-open' : ''}`}>
|
|
292
|
-
<nav className="nav-content">
|
|
293
|
-
<div className="nav-sections">
|
|
294
|
-
{documentSections.map((section) => (
|
|
295
|
-
<button
|
|
296
|
-
key={section.id}
|
|
297
|
-
className={`nav-item ${currentSection === section.id ? 'active' : ''}`}
|
|
298
|
-
onClick={() => {
|
|
299
|
-
setCurrentSection(section.id)
|
|
300
|
-
setSidebarOpen(false)
|
|
301
|
-
}}
|
|
302
|
-
>
|
|
303
|
-
<div className="nav-item-content">
|
|
304
|
-
<div className="nav-item-title">{section.title}</div>
|
|
305
|
-
<div className="nav-item-subtitle">{section.subtitle}</div>
|
|
306
|
-
</div>
|
|
307
|
-
</button>
|
|
308
|
-
))}
|
|
309
|
-
</div>
|
|
310
|
-
<img
|
|
311
|
-
src="/client-api/fjell-icon.svg"
|
|
312
|
-
alt="Fjell"
|
|
313
|
-
className="fjell-logo"
|
|
314
|
-
/>
|
|
315
|
-
</nav>
|
|
316
|
-
</aside>
|
|
317
|
-
|
|
318
|
-
<main className="main">
|
|
319
|
-
<div className="content-container">
|
|
320
|
-
{loading ? (
|
|
321
|
-
<div className="loading">
|
|
322
|
-
<div className="loading-animation">
|
|
323
|
-
<div className="loading-dot"></div>
|
|
324
|
-
<div className="loading-dot"></div>
|
|
325
|
-
<div className="loading-dot"></div>
|
|
326
|
-
</div>
|
|
327
|
-
<div className="loading-text">Loading Client API Documentation</div>
|
|
328
|
-
</div>
|
|
329
|
-
) : (
|
|
330
|
-
<div className="content-wrapper">
|
|
331
|
-
<div className="content-header">
|
|
332
|
-
<div className="breadcrumb">
|
|
333
|
-
<span className="breadcrumb-home">Fjell Client API</span>
|
|
334
|
-
<span className="breadcrumb-separator">•</span>
|
|
335
|
-
<span className="breadcrumb-current">
|
|
336
|
-
{documentSections.find(s => s.id === currentSection)?.title}
|
|
337
|
-
</span>
|
|
338
|
-
</div>
|
|
339
|
-
<div className="section-header">
|
|
340
|
-
<h1 className="content-title">
|
|
341
|
-
{documentSections.find(s => s.id === currentSection)?.title}
|
|
342
|
-
</h1>
|
|
343
|
-
<p className="content-subtitle">
|
|
344
|
-
{documentSections.find(s => s.id === currentSection)?.subtitle}
|
|
345
|
-
</p>
|
|
346
|
-
</div>
|
|
347
|
-
</div>
|
|
348
|
-
|
|
349
|
-
<div className="content">
|
|
350
|
-
{currentSection === 'examples' ? (
|
|
351
|
-
<div className="examples-content">
|
|
352
|
-
<ReactMarkdown
|
|
353
|
-
remarkPlugins={[remarkGfm]}
|
|
354
|
-
components={{
|
|
355
|
-
code({ className, children, ...props }: any) {
|
|
356
|
-
const match = /language-(\w+)/.exec(className || '')
|
|
357
|
-
return !props.inline && match ? (
|
|
358
|
-
<SyntaxHighlighter
|
|
359
|
-
style={oneLight as { [key: string]: React.CSSProperties }}
|
|
360
|
-
language={match[1]}
|
|
361
|
-
PreTag="div"
|
|
362
|
-
{...props}
|
|
363
|
-
>
|
|
364
|
-
{String(children).replace(/\n$/, '')}
|
|
365
|
-
</SyntaxHighlighter>
|
|
366
|
-
) : (
|
|
367
|
-
<code className={className} {...props}>
|
|
368
|
-
{children}
|
|
369
|
-
</code>
|
|
370
|
-
)
|
|
371
|
-
},
|
|
372
|
-
h1({ children }) {
|
|
373
|
-
return <h1 className="content-h1">{children}</h1>
|
|
374
|
-
},
|
|
375
|
-
h2({ children }) {
|
|
376
|
-
return <h2 className="content-h2">{children}</h2>
|
|
377
|
-
},
|
|
378
|
-
h3({ children }) {
|
|
379
|
-
return <h3 className="content-h3">{children}</h3>
|
|
380
|
-
}
|
|
381
|
-
}}
|
|
382
|
-
>
|
|
383
|
-
{currentContent}
|
|
384
|
-
</ReactMarkdown>
|
|
385
|
-
|
|
386
|
-
<div className="examples-grid">
|
|
387
|
-
<div className="example-card">
|
|
388
|
-
<h3>Simple Example</h3>
|
|
389
|
-
<p>Basic CRUD operations with HTTP client patterns.</p>
|
|
390
|
-
<details>
|
|
391
|
-
<summary>View Code</summary>
|
|
392
|
-
<div className="example-code-block">
|
|
393
|
-
<SyntaxHighlighter
|
|
394
|
-
style={oneLight as { [key: string]: React.CSSProperties }}
|
|
395
|
-
language="bash"
|
|
396
|
-
PreTag="div"
|
|
397
|
-
>
|
|
398
|
-
npx tsx examples/simple-example.ts
|
|
399
|
-
</SyntaxHighlighter>
|
|
400
|
-
</div>
|
|
401
|
-
</details>
|
|
402
|
-
</div>
|
|
403
|
-
|
|
404
|
-
<div className="example-card">
|
|
405
|
-
<h3>Multi-Level Keys</h3>
|
|
406
|
-
<p>Complex hierarchical data models with nested relationships.</p>
|
|
407
|
-
<details>
|
|
408
|
-
<summary>View Code</summary>
|
|
409
|
-
<div className="example-code-block">
|
|
410
|
-
<SyntaxHighlighter
|
|
411
|
-
style={oneLight as { [key: string]: React.CSSProperties }}
|
|
412
|
-
language="bash"
|
|
413
|
-
PreTag="div"
|
|
414
|
-
>
|
|
415
|
-
npx tsx examples/multi-level-keys.ts
|
|
416
|
-
</SyntaxHighlighter>
|
|
417
|
-
</div>
|
|
418
|
-
</details>
|
|
419
|
-
</div>
|
|
420
|
-
|
|
421
|
-
<div className="example-card">
|
|
422
|
-
<h3>Enterprise Example</h3>
|
|
423
|
-
<p>Complete business application with e-commerce workflows.</p>
|
|
424
|
-
<details>
|
|
425
|
-
<summary>View Code</summary>
|
|
426
|
-
<div className="example-code-block">
|
|
427
|
-
<SyntaxHighlighter
|
|
428
|
-
style={oneLight as { [key: string]: React.CSSProperties }}
|
|
429
|
-
language="bash"
|
|
430
|
-
PreTag="div"
|
|
431
|
-
>
|
|
432
|
-
npx tsx examples/enterprise-example.ts
|
|
433
|
-
</SyntaxHighlighter>
|
|
434
|
-
</div>
|
|
435
|
-
</details>
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
|
-
</div>
|
|
439
|
-
) : (
|
|
440
|
-
<ReactMarkdown
|
|
441
|
-
remarkPlugins={[remarkGfm]}
|
|
442
|
-
components={{
|
|
443
|
-
code({ className, children, ...props }: any) {
|
|
444
|
-
const match = /language-(\w+)/.exec(className || '')
|
|
445
|
-
return !props.inline && match ? (
|
|
446
|
-
<SyntaxHighlighter
|
|
447
|
-
style={oneLight as { [key: string]: React.CSSProperties }}
|
|
448
|
-
language={match[1]}
|
|
449
|
-
PreTag="div"
|
|
450
|
-
{...props}
|
|
451
|
-
>
|
|
452
|
-
{String(children).replace(/\n$/, '')}
|
|
453
|
-
</SyntaxHighlighter>
|
|
454
|
-
) : (
|
|
455
|
-
<code className={className} {...props}>
|
|
456
|
-
{children}
|
|
457
|
-
</code>
|
|
458
|
-
)
|
|
459
|
-
},
|
|
460
|
-
h1({ children }) {
|
|
461
|
-
return <h1 className="content-h1">{children}</h1>
|
|
462
|
-
},
|
|
463
|
-
h2({ children }) {
|
|
464
|
-
return <h2 className="content-h2">{children}</h2>
|
|
465
|
-
},
|
|
466
|
-
h3({ children }) {
|
|
467
|
-
return <h3 className="content-h3">{children}</h3>
|
|
468
|
-
}
|
|
469
|
-
}}
|
|
470
|
-
>
|
|
471
|
-
{currentContent}
|
|
472
|
-
</ReactMarkdown>
|
|
473
|
-
)}
|
|
474
|
-
</div>
|
|
475
|
-
|
|
476
|
-
<div className="content-navigation">
|
|
477
|
-
{documentSections.map((section) => {
|
|
478
|
-
if (section.id === currentSection) return null
|
|
479
|
-
return (
|
|
480
|
-
<button
|
|
481
|
-
key={section.id}
|
|
482
|
-
className="nav-suggestion"
|
|
483
|
-
onClick={() => setCurrentSection(section.id)}
|
|
484
|
-
>
|
|
485
|
-
<span className="nav-suggestion-label">Next</span>
|
|
486
|
-
<span className="nav-suggestion-title">{section.title}</span>
|
|
487
|
-
</button>
|
|
488
|
-
)
|
|
489
|
-
}).filter(Boolean).slice(0, 1)}
|
|
490
|
-
</div>
|
|
491
|
-
</div>
|
|
492
|
-
)}
|
|
493
|
-
</div>
|
|
494
|
-
</main>
|
|
495
|
-
</div>
|
|
496
|
-
|
|
497
|
-
<footer className="footer">
|
|
498
|
-
<div className="footer-container">
|
|
499
|
-
<div className="footer-content">
|
|
500
|
-
<p className="footer-text">
|
|
501
|
-
Crafted with intention for the Fjell ecosystem
|
|
502
|
-
</p>
|
|
503
|
-
<p className="footer-license">
|
|
504
|
-
Licensed under Apache-2.0 • 2024
|
|
505
|
-
</p>
|
|
506
|
-
</div>
|
|
507
|
-
</div>
|
|
508
|
-
</footer>
|
|
509
|
-
</div>
|
|
510
|
-
)
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
export default App
|