@miozu/jera 0.3.0 → 0.4.3
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/CLAUDE.md +350 -59
- package/README.md +30 -22
- package/llms.txt +37 -4
- package/package.json +8 -2
- package/src/components/docs/CodeBlock.svelte +204 -0
- package/src/components/docs/DocSection.svelte +120 -0
- package/src/components/docs/PropsTable.svelte +136 -0
- package/src/components/docs/SplitPane.svelte +98 -0
- package/src/components/docs/index.js +14 -0
- package/src/components/feedback/Alert.svelte +234 -0
- package/src/components/feedback/EmptyState.svelte +6 -6
- package/src/components/feedback/ProgressBar.svelte +8 -8
- package/src/components/feedback/Skeleton.svelte +4 -4
- package/src/components/feedback/Spinner.svelte +1 -1
- package/src/components/feedback/Toast.svelte +137 -173
- package/src/components/forms/Checkbox.svelte +10 -10
- package/src/components/forms/Dropzone.svelte +14 -14
- package/src/components/forms/FileUpload.svelte +16 -16
- package/src/components/forms/IconInput.svelte +4 -4
- package/src/components/forms/Input.svelte +14 -14
- package/src/components/forms/NumberInput.svelte +13 -13
- package/src/components/forms/PinInput.svelte +8 -8
- package/src/components/forms/Radio.svelte +8 -8
- package/src/components/forms/RangeSlider.svelte +12 -12
- package/src/components/forms/SearchInput.svelte +10 -10
- package/src/components/forms/Select.svelte +156 -158
- package/src/components/forms/Switch.svelte +4 -4
- package/src/components/forms/Textarea.svelte +9 -9
- package/src/components/navigation/Accordion.svelte +1 -1
- package/src/components/navigation/AccordionItem.svelte +6 -6
- package/src/components/navigation/NavigationContainer.svelte +344 -0
- package/src/components/navigation/Sidebar.svelte +334 -0
- package/src/components/navigation/SidebarAccountGroup.svelte +495 -0
- package/src/components/navigation/SidebarAccountItem.svelte +492 -0
- package/src/components/navigation/SidebarGroup.svelte +230 -0
- package/src/components/navigation/SidebarGroupSwitcher.svelte +262 -0
- package/src/components/navigation/SidebarItem.svelte +210 -0
- package/src/components/navigation/SidebarNavigationItem.svelte +470 -0
- package/src/components/navigation/SidebarPopover.svelte +145 -0
- package/src/components/navigation/SidebarSearch.svelte +236 -0
- package/src/components/navigation/SidebarSection.svelte +158 -0
- package/src/components/navigation/SidebarToggle.svelte +86 -0
- package/src/components/navigation/Tabs.svelte +18 -18
- package/src/components/navigation/WorkspaceMenu.svelte +416 -0
- package/src/components/navigation/blocks/NavigationAccountGroup.svelte +396 -0
- package/src/components/navigation/blocks/NavigationCustomBlock.svelte +74 -0
- package/src/components/navigation/blocks/NavigationGroupSwitcher.svelte +277 -0
- package/src/components/navigation/blocks/NavigationSearch.svelte +300 -0
- package/src/components/navigation/blocks/NavigationSection.svelte +230 -0
- package/src/components/navigation/index.js +22 -0
- package/src/components/overlays/ConfirmDialog.svelte +18 -18
- package/src/components/overlays/Dropdown.svelte +2 -2
- package/src/components/overlays/DropdownDivider.svelte +1 -1
- package/src/components/overlays/DropdownItem.svelte +5 -5
- package/src/components/overlays/Modal.svelte +13 -13
- package/src/components/overlays/Popover.svelte +3 -3
- package/src/components/primitives/Avatar.svelte +12 -12
- package/src/components/primitives/Badge.svelte +7 -7
- package/src/components/primitives/Button.svelte +126 -174
- package/src/components/primitives/Card.svelte +15 -15
- package/src/components/primitives/Divider.svelte +3 -3
- package/src/components/primitives/LazyImage.svelte +1 -1
- package/src/components/primitives/Link.svelte +2 -2
- package/src/components/primitives/Stat.svelte +197 -0
- package/src/components/primitives/StatusBadge.svelte +24 -24
- package/src/index.js +62 -7
- package/src/tokens/colors.css +96 -128
- package/src/utils/highlighter.js +124 -0
- package/src/utils/index.js +7 -2
- package/src/utils/navigation.svelte.js +423 -0
- package/src/utils/reactive.svelte.js +126 -37
- package/src/utils/sidebar.svelte.js +211 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component CodeBlock
|
|
3
|
+
|
|
4
|
+
Syntax-highlighted code block with copy-to-clipboard functionality.
|
|
5
|
+
Uses Shiki for highlighting via CSS variables for theme compatibility.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```svelte
|
|
9
|
+
<CodeBlock
|
|
10
|
+
code={`const greeting = "Hello, World!";`}
|
|
11
|
+
lang="javascript"
|
|
12
|
+
filename="example.js"
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
-->
|
|
16
|
+
<script>
|
|
17
|
+
import {getHighlighter} from '../../utils/highlighter.js';
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
/** The code to display */
|
|
21
|
+
code = '',
|
|
22
|
+
/** Language for syntax highlighting */
|
|
23
|
+
lang = 'javascript',
|
|
24
|
+
/** Optional filename to display in header */
|
|
25
|
+
filename = '',
|
|
26
|
+
/** Show line numbers */
|
|
27
|
+
showLineNumbers = false,
|
|
28
|
+
/** Additional CSS classes */
|
|
29
|
+
class: className = ''
|
|
30
|
+
} = $props();
|
|
31
|
+
|
|
32
|
+
let copied = $state(false);
|
|
33
|
+
let highlightedCode = $state('');
|
|
34
|
+
|
|
35
|
+
$effect(() => {
|
|
36
|
+
highlightCodeAsync();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
async function highlightCodeAsync() {
|
|
40
|
+
try {
|
|
41
|
+
const highlighter = await getHighlighter();
|
|
42
|
+
highlightedCode = highlighter.codeToHtml(code.trim(), {
|
|
43
|
+
lang: lang || 'text',
|
|
44
|
+
theme: 'css-variables'
|
|
45
|
+
});
|
|
46
|
+
} catch (e) {
|
|
47
|
+
highlightedCode = `<pre><code>${escapeHtml(code)}</code></pre>`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function escapeHtml(str) {
|
|
52
|
+
return str
|
|
53
|
+
.replace(/&/g, '&')
|
|
54
|
+
.replace(/</g, '<')
|
|
55
|
+
.replace(/>/g, '>');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function copyCode() {
|
|
59
|
+
try {
|
|
60
|
+
await navigator.clipboard.writeText(code.trim());
|
|
61
|
+
copied = true;
|
|
62
|
+
setTimeout(() => copied = false, 2000);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error('Failed to copy:', e);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<div class="jera-code-block {className}">
|
|
70
|
+
{#if filename}
|
|
71
|
+
<div class="code-header">
|
|
72
|
+
<span class="code-filename">{filename}</span>
|
|
73
|
+
<span class="code-lang">{lang}</span>
|
|
74
|
+
</div>
|
|
75
|
+
{/if}
|
|
76
|
+
|
|
77
|
+
<div class="code-container">
|
|
78
|
+
<button
|
|
79
|
+
class="copy-btn"
|
|
80
|
+
onclick={copyCode}
|
|
81
|
+
aria-label={copied ? 'Copied!' : 'Copy code'}
|
|
82
|
+
>
|
|
83
|
+
{#if copied}
|
|
84
|
+
<!-- Check icon (inline SVG - no external dependency) -->
|
|
85
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
|
|
86
|
+
{:else}
|
|
87
|
+
<!-- Copy icon (inline SVG - no external dependency) -->
|
|
88
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
|
|
89
|
+
{/if}
|
|
90
|
+
</button>
|
|
91
|
+
|
|
92
|
+
<div class="code-content" class:with-lines={showLineNumbers}>
|
|
93
|
+
{@html highlightedCode}
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<style>
|
|
99
|
+
.jera-code-block {
|
|
100
|
+
position: relative;
|
|
101
|
+
border-radius: var(--radius-md, 0.5rem);
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
background: var(--color-base1, var(--base1, #1a1f26));
|
|
104
|
+
border: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.code-header {
|
|
108
|
+
display: flex;
|
|
109
|
+
justify-content: space-between;
|
|
110
|
+
align-items: center;
|
|
111
|
+
padding: 0.5rem 1rem;
|
|
112
|
+
background: var(--color-base0, var(--base0, #0f1419));
|
|
113
|
+
border-bottom: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
114
|
+
font-size: 0.75rem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.code-filename {
|
|
118
|
+
color: var(--color-base5, var(--base5, #e2e8f0));
|
|
119
|
+
font-family: var(--font-mono, monospace);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.code-lang {
|
|
123
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
124
|
+
text-transform: uppercase;
|
|
125
|
+
font-size: 0.625rem;
|
|
126
|
+
letter-spacing: 0.05em;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.code-container {
|
|
130
|
+
position: relative;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.copy-btn {
|
|
134
|
+
position: absolute;
|
|
135
|
+
top: 0.75rem;
|
|
136
|
+
right: 0.75rem;
|
|
137
|
+
z-index: 10;
|
|
138
|
+
padding: 0.5rem;
|
|
139
|
+
border: none;
|
|
140
|
+
border-radius: var(--radius-sm, 0.25rem);
|
|
141
|
+
background: var(--color-base2, var(--base2, #242a33));
|
|
142
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
opacity: 0;
|
|
145
|
+
transition: opacity 0.15s, background 0.15s, color 0.15s;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.jera-code-block:hover .copy-btn {
|
|
149
|
+
opacity: 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.copy-btn:hover {
|
|
153
|
+
background: var(--color-base3, var(--base3, #4a5568));
|
|
154
|
+
color: var(--color-base6, var(--base6, #f7fafc));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.code-content {
|
|
158
|
+
overflow-x: auto;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.code-content :global(pre) {
|
|
162
|
+
margin: 0;
|
|
163
|
+
padding: 1rem;
|
|
164
|
+
background: transparent !important;
|
|
165
|
+
font-family: var(--font-mono, monospace);
|
|
166
|
+
font-size: 0.875rem;
|
|
167
|
+
line-height: 1.6;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.code-content :global(code) {
|
|
171
|
+
font-family: inherit;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Shiki CSS variables theme - compatible with both jera and selify themes */
|
|
175
|
+
.code-content {
|
|
176
|
+
--shiki-color-text: var(--color-base5, var(--base5, #e2e8f0));
|
|
177
|
+
--shiki-color-background: transparent;
|
|
178
|
+
--shiki-token-constant: var(--blue, #83d2fc);
|
|
179
|
+
--shiki-token-string: var(--green, #6dd672);
|
|
180
|
+
--shiki-token-comment: var(--base3, #565e78);
|
|
181
|
+
--shiki-token-keyword: var(--magenta, #c974e6);
|
|
182
|
+
--shiki-token-parameter: var(--peach, #ff9982);
|
|
183
|
+
--shiki-token-function: var(--blue, #83d2fc);
|
|
184
|
+
--shiki-token-string-expression: var(--green, #6dd672);
|
|
185
|
+
--shiki-token-punctuation: var(--color-base4, var(--base4, #a0aec0));
|
|
186
|
+
--shiki-token-link: var(--blue, #83d2fc);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Line numbers */
|
|
190
|
+
.with-lines :global(pre) {
|
|
191
|
+
counter-reset: line;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.with-lines :global(.line::before) {
|
|
195
|
+
counter-increment: line;
|
|
196
|
+
content: counter(line);
|
|
197
|
+
display: inline-block;
|
|
198
|
+
width: 2rem;
|
|
199
|
+
margin-right: 1rem;
|
|
200
|
+
text-align: right;
|
|
201
|
+
color: var(--color-base3, var(--base3, #4a5568));
|
|
202
|
+
user-select: none;
|
|
203
|
+
}
|
|
204
|
+
</style>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component DocSection
|
|
3
|
+
|
|
4
|
+
A documentation section with optional anchor link, title, description,
|
|
5
|
+
and content area. Useful for organizing documentation into scannable sections.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```svelte
|
|
9
|
+
<DocSection id="installation" title="Installation" description="How to install the package">
|
|
10
|
+
<CodeBlock code="npm install @miozu/jera" lang="bash" />
|
|
11
|
+
</DocSection>
|
|
12
|
+
```
|
|
13
|
+
-->
|
|
14
|
+
<script>
|
|
15
|
+
import {Link2} from '@lucide/svelte';
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
/** Unique ID for anchor links */
|
|
19
|
+
id = '',
|
|
20
|
+
/** Section title */
|
|
21
|
+
title = '',
|
|
22
|
+
/** Optional description below title */
|
|
23
|
+
description = '',
|
|
24
|
+
/** Heading level (2-6) */
|
|
25
|
+
level = 2,
|
|
26
|
+
/** Show anchor link on hover */
|
|
27
|
+
showAnchor = true,
|
|
28
|
+
/** Children content */
|
|
29
|
+
children,
|
|
30
|
+
/** Additional CSS classes */
|
|
31
|
+
class: className = ''
|
|
32
|
+
} = $props();
|
|
33
|
+
|
|
34
|
+
const Tag = `h${level}`;
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<section class="jera-doc-section {className}" {id}>
|
|
38
|
+
{#if title}
|
|
39
|
+
<div class="section-header">
|
|
40
|
+
<svelte:element this={Tag} class="section-title">
|
|
41
|
+
{title}
|
|
42
|
+
{#if showAnchor && id}
|
|
43
|
+
<a href="#{id}" class="anchor-link" aria-label="Link to {title}">
|
|
44
|
+
<Link2 size={16} />
|
|
45
|
+
</a>
|
|
46
|
+
{/if}
|
|
47
|
+
</svelte:element>
|
|
48
|
+
{#if description}
|
|
49
|
+
<p class="section-description">{description}</p>
|
|
50
|
+
{/if}
|
|
51
|
+
</div>
|
|
52
|
+
{/if}
|
|
53
|
+
|
|
54
|
+
<div class="section-content">
|
|
55
|
+
{@render children?.()}
|
|
56
|
+
</div>
|
|
57
|
+
</section>
|
|
58
|
+
|
|
59
|
+
<style>
|
|
60
|
+
.jera-doc-section {
|
|
61
|
+
margin-bottom: 2rem;
|
|
62
|
+
scroll-margin-top: 2rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.section-header {
|
|
66
|
+
margin-bottom: 1rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.section-title {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
gap: 0.5rem;
|
|
73
|
+
margin: 0 0 0.5rem 0;
|
|
74
|
+
font-weight: 600;
|
|
75
|
+
color: var(--color-base6, var(--base6, #f3f4f7));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
h2.section-title {
|
|
79
|
+
font-size: 1.5rem;
|
|
80
|
+
padding-bottom: 0.5rem;
|
|
81
|
+
border-bottom: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
h3.section-title {
|
|
85
|
+
font-size: 1.25rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
h4.section-title {
|
|
89
|
+
font-size: 1.125rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
h5.section-title,
|
|
93
|
+
h6.section-title {
|
|
94
|
+
font-size: 1rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.anchor-link {
|
|
98
|
+
opacity: 0;
|
|
99
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
100
|
+
transition: opacity 0.15s, color 0.15s;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.section-title:hover .anchor-link {
|
|
104
|
+
opacity: 1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.anchor-link:hover {
|
|
108
|
+
color: var(--color-primary, var(--magenta, #c974e6));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.section-description {
|
|
112
|
+
margin: 0;
|
|
113
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
114
|
+
line-height: 1.6;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.section-content {
|
|
118
|
+
/* Content inherits full width */
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component PropsTable
|
|
3
|
+
|
|
4
|
+
Display component/function props in a clean, readable table.
|
|
5
|
+
Commonly used for API documentation.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```svelte
|
|
9
|
+
<PropsTable props={[
|
|
10
|
+
{ name: 'variant', type: 'string', default: '"default"', description: 'Visual style' },
|
|
11
|
+
{ name: 'disabled', type: 'boolean', default: 'false', description: 'Disable interactions' },
|
|
12
|
+
{ name: 'onclick', type: 'function', required: true, description: 'Click handler' }
|
|
13
|
+
]} />
|
|
14
|
+
```
|
|
15
|
+
-->
|
|
16
|
+
<script>
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} PropDef
|
|
19
|
+
* @property {string} name - Property name
|
|
20
|
+
* @property {string} type - Type annotation
|
|
21
|
+
* @property {string} [default] - Default value
|
|
22
|
+
* @property {string} description - Description
|
|
23
|
+
* @property {boolean} [required] - Whether prop is required
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** @type {{ props: PropDef[], class?: string }} */
|
|
27
|
+
let {
|
|
28
|
+
props = [],
|
|
29
|
+
class: className = ''
|
|
30
|
+
} = $props();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class="jera-props-table {className}">
|
|
34
|
+
<table>
|
|
35
|
+
<thead>
|
|
36
|
+
<tr>
|
|
37
|
+
<th>Prop</th>
|
|
38
|
+
<th>Type</th>
|
|
39
|
+
<th>Default</th>
|
|
40
|
+
<th>Description</th>
|
|
41
|
+
</tr>
|
|
42
|
+
</thead>
|
|
43
|
+
<tbody>
|
|
44
|
+
{#each props as prop}
|
|
45
|
+
<tr>
|
|
46
|
+
<td class="prop-name">
|
|
47
|
+
<code>{prop.name}</code>
|
|
48
|
+
{#if prop.required}
|
|
49
|
+
<span class="required" title="Required">*</span>
|
|
50
|
+
{/if}
|
|
51
|
+
</td>
|
|
52
|
+
<td class="prop-type">
|
|
53
|
+
<code>{prop.type}</code>
|
|
54
|
+
</td>
|
|
55
|
+
<td class="prop-default">
|
|
56
|
+
{#if prop.default !== undefined}
|
|
57
|
+
<code>{prop.default}</code>
|
|
58
|
+
{:else}
|
|
59
|
+
<span class="muted">-</span>
|
|
60
|
+
{/if}
|
|
61
|
+
</td>
|
|
62
|
+
<td class="prop-desc">{prop.description}</td>
|
|
63
|
+
</tr>
|
|
64
|
+
{/each}
|
|
65
|
+
</tbody>
|
|
66
|
+
</table>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
.jera-props-table {
|
|
71
|
+
overflow-x: auto;
|
|
72
|
+
border: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
73
|
+
border-radius: var(--radius-md, 0.5rem);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
table {
|
|
77
|
+
width: 100%;
|
|
78
|
+
border-collapse: collapse;
|
|
79
|
+
font-size: 0.875rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
th {
|
|
83
|
+
text-align: left;
|
|
84
|
+
padding: 0.75rem 1rem;
|
|
85
|
+
background: var(--color-base1, var(--base1, #1a1f26));
|
|
86
|
+
border-bottom: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
87
|
+
font-weight: 500;
|
|
88
|
+
color: var(--color-base5, var(--base5, #e2e8f0));
|
|
89
|
+
white-space: nowrap;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
td {
|
|
93
|
+
padding: 0.75rem 1rem;
|
|
94
|
+
border-bottom: 1px solid var(--color-border, var(--base2, #2d3748));
|
|
95
|
+
vertical-align: top;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
tr:last-child td {
|
|
99
|
+
border-bottom: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.prop-name code {
|
|
103
|
+
font-family: var(--font-mono, monospace);
|
|
104
|
+
font-weight: 500;
|
|
105
|
+
color: var(--color-primary, var(--magenta, #c974e6));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.required {
|
|
109
|
+
color: var(--color-error, var(--red, #eb3137));
|
|
110
|
+
margin-left: 0.25rem;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.prop-type code {
|
|
114
|
+
font-family: var(--font-mono, monospace);
|
|
115
|
+
font-size: 0.8125rem;
|
|
116
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
117
|
+
background: var(--color-base1, var(--base1, #1a1f26));
|
|
118
|
+
padding: 0.125rem 0.375rem;
|
|
119
|
+
border-radius: 0.25rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.prop-default code {
|
|
123
|
+
font-family: var(--font-mono, monospace);
|
|
124
|
+
font-size: 0.8125rem;
|
|
125
|
+
color: var(--color-success, var(--green, #6dd672));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.muted {
|
|
129
|
+
color: var(--color-base3, var(--base3, #4a5568));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.prop-desc {
|
|
133
|
+
color: var(--color-base4, var(--base4, #a0aec0));
|
|
134
|
+
line-height: 1.5;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component SplitPane
|
|
3
|
+
|
|
4
|
+
Two-pane layout component for documentation with description on the left
|
|
5
|
+
and code/examples on the right. Responsive - stacks vertically on mobile.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```svelte
|
|
9
|
+
<SplitPane>
|
|
10
|
+
{#snippet left()}
|
|
11
|
+
<h2>Function Description</h2>
|
|
12
|
+
<p>This function does something amazing...</p>
|
|
13
|
+
{/snippet}
|
|
14
|
+
{#snippet right()}
|
|
15
|
+
<CodeBlock code={exampleCode} lang="javascript" />
|
|
16
|
+
{/snippet}
|
|
17
|
+
</SplitPane>
|
|
18
|
+
```
|
|
19
|
+
-->
|
|
20
|
+
<script>
|
|
21
|
+
let {
|
|
22
|
+
/** Left pane content (description, prose) */
|
|
23
|
+
left,
|
|
24
|
+
/** Right pane content (code, examples) */
|
|
25
|
+
right,
|
|
26
|
+
/** Ratio of left:right pane widths (e.g., '1:1', '2:1', '3:2') */
|
|
27
|
+
ratio = '1:1',
|
|
28
|
+
/** Gap between panes */
|
|
29
|
+
gap = '2rem',
|
|
30
|
+
/** Minimum height */
|
|
31
|
+
minHeight = 'auto',
|
|
32
|
+
/** Whether both panes should independently scroll */
|
|
33
|
+
stickyRight = false,
|
|
34
|
+
/** Additional CSS classes */
|
|
35
|
+
class: className = ''
|
|
36
|
+
} = $props();
|
|
37
|
+
|
|
38
|
+
// Parse ratio into flex values
|
|
39
|
+
const [leftFlex, rightFlex] = $derived.by(() => {
|
|
40
|
+
const parts = ratio.split(':').map(Number);
|
|
41
|
+
return [parts[0] || 1, parts[1] || 1];
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div
|
|
46
|
+
class="jera-split-pane {className}"
|
|
47
|
+
class:sticky-right={stickyRight}
|
|
48
|
+
style:--gap={gap}
|
|
49
|
+
style:--left-flex={leftFlex}
|
|
50
|
+
style:--right-flex={rightFlex}
|
|
51
|
+
style:--min-height={minHeight}
|
|
52
|
+
>
|
|
53
|
+
<div class="pane pane-left">
|
|
54
|
+
{@render left?.()}
|
|
55
|
+
</div>
|
|
56
|
+
<div class="pane pane-right">
|
|
57
|
+
{@render right?.()}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<style>
|
|
62
|
+
.jera-split-pane {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
gap: var(--gap);
|
|
66
|
+
min-height: var(--min-height);
|
|
67
|
+
width: 100%;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (min-width: 1024px) {
|
|
71
|
+
.jera-split-pane {
|
|
72
|
+
flex-direction: row;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.pane {
|
|
77
|
+
min-width: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.pane-left {
|
|
81
|
+
flex: var(--left-flex);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.pane-right {
|
|
85
|
+
flex: var(--right-flex);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Sticky right pane for scrollable docs */
|
|
89
|
+
@media (min-width: 1024px) {
|
|
90
|
+
.sticky-right .pane-right {
|
|
91
|
+
position: sticky;
|
|
92
|
+
top: 1rem;
|
|
93
|
+
align-self: flex-start;
|
|
94
|
+
max-height: calc(100vh - 2rem);
|
|
95
|
+
overflow-y: auto;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Documentation components for @miozu/jera
|
|
3
|
+
*
|
|
4
|
+
* Components for building documentation sites with syntax highlighting,
|
|
5
|
+
* split-pane layouts, and structured content sections.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { CodeBlock, PropsTable, SplitPane, DocSection } from '@miozu/jera';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { default as CodeBlock } from './CodeBlock.svelte';
|
|
12
|
+
export { default as PropsTable } from './PropsTable.svelte';
|
|
13
|
+
export { default as SplitPane } from './SplitPane.svelte';
|
|
14
|
+
export { default as DocSection } from './DocSection.svelte';
|