@sprig-and-prose/sprig-ui-csr 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.
- package/README.md +120 -0
- package/biome.json +37 -0
- package/index.html +12 -0
- package/manifest.json +10711 -0
- package/package.json +29 -0
- package/src/App.svelte +202 -0
- package/src/cli.js +146 -0
- package/src/lib/components/ContentsCard.svelte +167 -0
- package/src/lib/components/FooterStatus.svelte +80 -0
- package/src/lib/components/GlobalSearch.svelte +451 -0
- package/src/lib/components/PageHeader.svelte +116 -0
- package/src/lib/components/Prose.svelte +260 -0
- package/src/lib/components/UniverseHeader.svelte +20 -0
- package/src/lib/data/universeStore.js +252 -0
- package/src/lib/format/title.js +97 -0
- package/src/lib/references/isWildcardPath.js +9 -0
- package/src/lib/references/linkForPath.js +65 -0
- package/src/lib/references/linkForRepository.js +42 -0
- package/src/lib/router.js +75 -0
- package/src/lib/stores/describeRenderMode.js +9 -0
- package/src/lib/stores/theme.js +98 -0
- package/src/main.js +143 -0
- package/src/pages/AnthologyPage.svelte +84 -0
- package/src/pages/ConceptPage.svelte +873 -0
- package/src/pages/HomePage.svelte +80 -0
- package/src/pages/SeriesPage.svelte +657 -0
- package/src/server.js +115 -0
- package/src/styles/app.css +353 -0
- package/tsconfig.json +16 -0
- package/vite.config.js +10 -0
package/src/server.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createServer } from 'http';
|
|
2
|
+
import { readFileSync, existsSync, statSync } from 'fs';
|
|
3
|
+
import { join, extname, resolve, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
|
|
9
|
+
const mimeTypes = {
|
|
10
|
+
'.html': 'text/html',
|
|
11
|
+
'.js': 'application/javascript',
|
|
12
|
+
'.json': 'application/json',
|
|
13
|
+
'.css': 'text/css',
|
|
14
|
+
'.png': 'image/png',
|
|
15
|
+
'.jpg': 'image/jpeg',
|
|
16
|
+
'.jpeg': 'image/jpeg',
|
|
17
|
+
'.gif': 'image/gif',
|
|
18
|
+
'.svg': 'image/svg+xml',
|
|
19
|
+
'.woff': 'font/woff',
|
|
20
|
+
'.woff2': 'font/woff2',
|
|
21
|
+
'.ttf': 'font/ttf',
|
|
22
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create and return the HTTP server
|
|
27
|
+
* @param {string} manifestPath - Path to manifest.json file
|
|
28
|
+
* @returns {import('http').Server}
|
|
29
|
+
*/
|
|
30
|
+
export function createAppServer(manifestPath) {
|
|
31
|
+
const distDir = resolve(__dirname, '../dist');
|
|
32
|
+
const manifestFilePath = resolve(process.cwd(), manifestPath);
|
|
33
|
+
|
|
34
|
+
const server = createServer((req, res) => {
|
|
35
|
+
const url = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
36
|
+
const pathname = url.pathname;
|
|
37
|
+
|
|
38
|
+
// Handle /_ui/* routes - serve static files from dist/
|
|
39
|
+
if (pathname.startsWith('/_ui/')) {
|
|
40
|
+
// Remove /_ui prefix to get the file path relative to dist/
|
|
41
|
+
const filePath = pathname.slice(5); // Remove '/_ui/'
|
|
42
|
+
const fullPath = join(distDir, filePath);
|
|
43
|
+
|
|
44
|
+
// Security: ensure file is within dist directory
|
|
45
|
+
const resolvedPath = resolve(fullPath);
|
|
46
|
+
if (!resolvedPath.startsWith(resolve(distDir))) {
|
|
47
|
+
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
48
|
+
res.end('Forbidden');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!existsSync(resolvedPath) || !statSync(resolvedPath).isFile()) {
|
|
53
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
54
|
+
res.end('Not Found');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const content = readFileSync(resolvedPath);
|
|
60
|
+
const ext = extname(resolvedPath);
|
|
61
|
+
const contentType = mimeTypes[ext] || 'application/octet-stream';
|
|
62
|
+
|
|
63
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
64
|
+
res.end(content);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
67
|
+
res.end('Internal Server Error');
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Handle /api/manifest route
|
|
73
|
+
if (pathname === '/api/manifest') {
|
|
74
|
+
if (!existsSync(manifestFilePath) || !statSync(manifestFilePath).isFile()) {
|
|
75
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
76
|
+
res.end(JSON.stringify({ error: 'Manifest not found' }));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const content = readFileSync(manifestFilePath, 'utf-8');
|
|
82
|
+
const headers = {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
'X-Describe-Render-Mode': 'lists',
|
|
85
|
+
};
|
|
86
|
+
res.writeHead(200, headers);
|
|
87
|
+
res.end(content);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({ error: 'Error reading manifest' }));
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// All other routes - serve index.html for client-side routing
|
|
96
|
+
const indexPath = join(distDir, 'index.html');
|
|
97
|
+
if (!existsSync(indexPath)) {
|
|
98
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
99
|
+
res.end('Not Found - dist/index.html does not exist. Run "npm run build" first.');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const content = readFileSync(indexPath, 'utf-8');
|
|
105
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
106
|
+
res.end(content);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
109
|
+
res.end('Internal Server Error');
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return server;
|
|
114
|
+
}
|
|
115
|
+
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
@import '@sprig-and-prose/sprig-design/index.css';
|
|
2
|
+
|
|
3
|
+
/* Global styles for sprig-ui-csr */
|
|
4
|
+
|
|
5
|
+
*,
|
|
6
|
+
*::before,
|
|
7
|
+
*::after {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:root {
|
|
14
|
+
/* fonts */
|
|
15
|
+
--font-ui:
|
|
16
|
+
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
17
|
+
--font-prose: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
18
|
+
|
|
19
|
+
/* Light mode - matching sprig-and-prose */
|
|
20
|
+
--text-color: #1a1a1a;
|
|
21
|
+
--text-secondary: #4a4a4a;
|
|
22
|
+
--text-tertiary: #464646;
|
|
23
|
+
--bg-color: #fafafa;
|
|
24
|
+
--border-color: #e0e0e0;
|
|
25
|
+
--dictionary-bg: #f5f5f5;
|
|
26
|
+
--code-bg: #f8f8f8;
|
|
27
|
+
--code-border: #e8e8e8;
|
|
28
|
+
|
|
29
|
+
/* Legacy variables for backward compatibility */
|
|
30
|
+
--bg: var(--bg-color);
|
|
31
|
+
--text: var(--text-color);
|
|
32
|
+
--muted: var(--text-secondary);
|
|
33
|
+
|
|
34
|
+
/* Link colors - slightly brighter than prose for discoverability */
|
|
35
|
+
--link-structural: #2a2a2a;
|
|
36
|
+
--link-exploratory: #3d3d3d;
|
|
37
|
+
--link-underline: rgba(0, 0, 0, 0.2);
|
|
38
|
+
|
|
39
|
+
/* Sprig link utilities - clearly identifiable at rest */
|
|
40
|
+
--sprig-link-fg: #2a2a2a;
|
|
41
|
+
--sprig-link-underline: rgba(0, 0, 0, 0.25);
|
|
42
|
+
--sprig-link-underline-hover: rgba(0, 0, 0, 0.4);
|
|
43
|
+
--sprig-link-anchor-fg: #1f1f1f;
|
|
44
|
+
--sprig-link-anchor-underline: rgba(0, 0, 0, 0.35);
|
|
45
|
+
--sprig-link-anchor-underline-hover: rgba(0, 0, 0, 0.5);
|
|
46
|
+
|
|
47
|
+
--card-bg: rgba(235, 225, 210, 0.8); /* Original parchment tone for light theme */
|
|
48
|
+
--card-border: var(--border-color);
|
|
49
|
+
|
|
50
|
+
--hairline: var(--border-color);
|
|
51
|
+
--hover: rgba(0, 0, 0, 0.04);
|
|
52
|
+
|
|
53
|
+
/* texture intensity */
|
|
54
|
+
--tex-a: 0.015;
|
|
55
|
+
--tex-b: 0.01;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Dark mode via system preference - using sprig grey */
|
|
59
|
+
@media (prefers-color-scheme: dark) {
|
|
60
|
+
:root {
|
|
61
|
+
--text-color: #e8e8e8;
|
|
62
|
+
--text-secondary: #b8b8b8;
|
|
63
|
+
--text-tertiary: #b4b4b4;
|
|
64
|
+
--bg-color: #24221f; /* sprig grey base */
|
|
65
|
+
--border-color: #3a3a3a;
|
|
66
|
+
--dictionary-bg: #1c1a17;
|
|
67
|
+
--code-bg: #1c1a17;
|
|
68
|
+
--code-border: #2a2a2a;
|
|
69
|
+
|
|
70
|
+
/* Legacy variables */
|
|
71
|
+
--bg: var(--bg-color);
|
|
72
|
+
--text: var(--text-color);
|
|
73
|
+
--muted: var(--text-secondary);
|
|
74
|
+
|
|
75
|
+
/* Link colors */
|
|
76
|
+
--link-structural: #e8e8e8;
|
|
77
|
+
--link-exploratory: #b8b8b8;
|
|
78
|
+
--link-underline: rgba(255, 255, 255, 0.3);
|
|
79
|
+
|
|
80
|
+
/* Sprig link utilities */
|
|
81
|
+
--sprig-link-fg: #e8e8e8;
|
|
82
|
+
--sprig-link-underline: rgba(255, 255, 255, 0.35);
|
|
83
|
+
--sprig-link-underline-hover: rgba(255, 255, 255, 0.5);
|
|
84
|
+
--sprig-link-anchor-fg: #e8e8e8;
|
|
85
|
+
--sprig-link-anchor-underline: rgba(255, 255, 255, 0.45);
|
|
86
|
+
--sprig-link-anchor-underline-hover: rgba(255, 255, 255, 0.6);
|
|
87
|
+
|
|
88
|
+
--card-bg: var(--dictionary-bg);
|
|
89
|
+
--card-border: var(--border-color);
|
|
90
|
+
|
|
91
|
+
--hairline: var(--border-color);
|
|
92
|
+
--hover: rgba(255, 255, 255, 0.06);
|
|
93
|
+
|
|
94
|
+
/* texture intensity (slightly stronger in dark) */
|
|
95
|
+
--tex-a: 0.03;
|
|
96
|
+
--tex-b: 0.02;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
html,
|
|
101
|
+
body {
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Dark mode via manual toggle (takes precedence over system preference) - using sprig grey */
|
|
107
|
+
html[data-theme="dark"] {
|
|
108
|
+
--text-color: #e8e8e8;
|
|
109
|
+
--text-secondary: #b8b8b8;
|
|
110
|
+
--text-tertiary: #b4b4b4;
|
|
111
|
+
--bg-color: #24221f; /* sprig grey base */
|
|
112
|
+
--border-color: #3a3a3a;
|
|
113
|
+
--dictionary-bg: #1c1a17;
|
|
114
|
+
--code-bg: #1c1a17;
|
|
115
|
+
--code-border: #2a2a2a;
|
|
116
|
+
|
|
117
|
+
/* Legacy variables */
|
|
118
|
+
--bg: var(--bg-color);
|
|
119
|
+
--text: var(--text-color);
|
|
120
|
+
--muted: var(--text-secondary);
|
|
121
|
+
|
|
122
|
+
/* Link colors */
|
|
123
|
+
--link-structural: #e8e8e8;
|
|
124
|
+
--link-exploratory: #b8b8b8;
|
|
125
|
+
--link-underline: rgba(255, 255, 255, 0.3);
|
|
126
|
+
|
|
127
|
+
/* Sprig link utilities */
|
|
128
|
+
--sprig-link-fg: #e8e8e8;
|
|
129
|
+
--sprig-link-underline: rgba(255, 255, 255, 0.35);
|
|
130
|
+
--sprig-link-underline-hover: rgba(255, 255, 255, 0.5);
|
|
131
|
+
--sprig-link-anchor-fg: #e8e8e8;
|
|
132
|
+
--sprig-link-anchor-underline: rgba(255, 255, 255, 0.45);
|
|
133
|
+
--sprig-link-anchor-underline-hover: rgba(255, 255, 255, 0.6);
|
|
134
|
+
|
|
135
|
+
--card-bg: var(--dictionary-bg);
|
|
136
|
+
--card-border: var(--border-color);
|
|
137
|
+
|
|
138
|
+
--hairline: var(--border-color);
|
|
139
|
+
--hover: rgba(255, 255, 255, 0.06);
|
|
140
|
+
|
|
141
|
+
/* texture intensity (slightly stronger in dark) */
|
|
142
|
+
--tex-a: 0.03;
|
|
143
|
+
--tex-b: 0.02;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Light mode via manual toggle (takes precedence over system preference) */
|
|
147
|
+
html[data-theme="light"] {
|
|
148
|
+
--text-color: #1a1a1a;
|
|
149
|
+
--text-secondary: #4a4a4a;
|
|
150
|
+
--text-tertiary: #464646;
|
|
151
|
+
--bg-color: #fafafa;
|
|
152
|
+
--border-color: #e0e0e0;
|
|
153
|
+
--dictionary-bg: #f5f5f5;
|
|
154
|
+
--code-bg: #f8f8f8;
|
|
155
|
+
--code-border: #e8e8e8;
|
|
156
|
+
|
|
157
|
+
/* Legacy variables */
|
|
158
|
+
--bg: var(--bg-color);
|
|
159
|
+
--text: var(--text-color);
|
|
160
|
+
--muted: var(--text-secondary);
|
|
161
|
+
|
|
162
|
+
/* Link colors */
|
|
163
|
+
--link-structural: #2a2a2a;
|
|
164
|
+
--link-exploratory: #3d3d3d;
|
|
165
|
+
--link-underline: rgba(0, 0, 0, 0.2);
|
|
166
|
+
|
|
167
|
+
/* Sprig link utilities */
|
|
168
|
+
--sprig-link-fg: #2a2a2a;
|
|
169
|
+
--sprig-link-underline: rgba(0, 0, 0, 0.25);
|
|
170
|
+
--sprig-link-underline-hover: rgba(0, 0, 0, 0.4);
|
|
171
|
+
--sprig-link-anchor-fg: #1f1f1f;
|
|
172
|
+
--sprig-link-anchor-underline: rgba(0, 0, 0, 0.35);
|
|
173
|
+
--sprig-link-anchor-underline-hover: rgba(0, 0, 0, 0.5);
|
|
174
|
+
|
|
175
|
+
--card-bg: rgba(235, 225, 210, 0.8); /* Original parchment tone for light theme */
|
|
176
|
+
--card-border: var(--border-color);
|
|
177
|
+
|
|
178
|
+
--hairline: var(--border-color);
|
|
179
|
+
--hover: rgba(0, 0, 0, 0.04);
|
|
180
|
+
|
|
181
|
+
/* texture intensity */
|
|
182
|
+
--tex-a: 0.015;
|
|
183
|
+
--tex-b: 0.01;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
body {
|
|
187
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
188
|
+
font-size: var(--sp-font-body);
|
|
189
|
+
line-height: var(--sp-line-body);
|
|
190
|
+
color: var(--text-color);
|
|
191
|
+
background-color: var(--bg-color);
|
|
192
|
+
-webkit-font-smoothing: antialiased;
|
|
193
|
+
-moz-osx-font-smoothing: grayscale;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Base link styles - shared foundation */
|
|
197
|
+
a {
|
|
198
|
+
color: inherit;
|
|
199
|
+
text-decoration: underline;
|
|
200
|
+
text-decoration-thickness: 1px;
|
|
201
|
+
text-underline-offset: 0.25rem;
|
|
202
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
203
|
+
transition: text-decoration-thickness 150ms ease, text-decoration-color 150ms ease;
|
|
204
|
+
cursor: pointer;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@media (prefers-color-scheme: dark) {
|
|
208
|
+
a {
|
|
209
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
html[data-theme="dark"] a {
|
|
214
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
html[data-theme="light"] a {
|
|
218
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
a:hover {
|
|
222
|
+
text-decoration-thickness: 1.5px;
|
|
223
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@media (prefers-color-scheme: dark) {
|
|
227
|
+
a:hover {
|
|
228
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
html[data-theme="dark"] a:hover {
|
|
233
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
html[data-theme="light"] a:hover {
|
|
237
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
a:focus {
|
|
241
|
+
outline: 2px solid var(--text-tertiary);
|
|
242
|
+
outline-offset: 2px;
|
|
243
|
+
border-radius: 2px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Sprig link utilities - clearly identifiable at rest */
|
|
247
|
+
a.sprig-link,
|
|
248
|
+
.sprig-link {
|
|
249
|
+
color: var(--sprig-link-fg);
|
|
250
|
+
text-decoration: underline;
|
|
251
|
+
text-decoration-thickness: 1px;
|
|
252
|
+
text-underline-offset: 3px;
|
|
253
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
254
|
+
cursor: pointer;
|
|
255
|
+
transition: text-decoration-thickness 150ms ease, text-decoration-color 150ms ease;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@media (prefers-color-scheme: dark) {
|
|
259
|
+
a.sprig-link,
|
|
260
|
+
.sprig-link {
|
|
261
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
html[data-theme="dark"] a.sprig-link,
|
|
266
|
+
html[data-theme="dark"] .sprig-link {
|
|
267
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
html[data-theme="light"] a.sprig-link,
|
|
271
|
+
html[data-theme="light"] .sprig-link {
|
|
272
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
a.sprig-link:hover,
|
|
276
|
+
.sprig-link:hover {
|
|
277
|
+
text-decoration-thickness: 1.5px;
|
|
278
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@media (prefers-color-scheme: dark) {
|
|
282
|
+
a.sprig-link:hover,
|
|
283
|
+
.sprig-link:hover {
|
|
284
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
html[data-theme="dark"] a.sprig-link:hover,
|
|
289
|
+
html[data-theme="dark"] .sprig-link:hover {
|
|
290
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
html[data-theme="light"] a.sprig-link:hover,
|
|
294
|
+
html[data-theme="light"] .sprig-link:hover {
|
|
295
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
a.sprig-link:focus-visible,
|
|
299
|
+
.sprig-link:focus-visible {
|
|
300
|
+
outline: 2px solid var(--text-tertiary);
|
|
301
|
+
outline-offset: 3px;
|
|
302
|
+
border-radius: 2px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Quiet links - lighter underline for references/secondary links */
|
|
306
|
+
a.sprig-link--quiet,
|
|
307
|
+
.sprig-link--quiet {
|
|
308
|
+
color: var(--sprig-link-fg);
|
|
309
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
310
|
+
opacity: 0.9;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@media (prefers-color-scheme: dark) {
|
|
314
|
+
a.sprig-link--quiet,
|
|
315
|
+
.sprig-link--quiet {
|
|
316
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
html[data-theme="dark"] a.sprig-link--quiet,
|
|
321
|
+
html[data-theme="dark"] .sprig-link--quiet {
|
|
322
|
+
text-decoration-color: rgba(255, 255, 255, 0.35);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
html[data-theme="light"] a.sprig-link--quiet,
|
|
326
|
+
html[data-theme="light"] .sprig-link--quiet {
|
|
327
|
+
text-decoration-color: rgba(0, 0, 0, 0.25);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
a.sprig-link--quiet:hover,
|
|
331
|
+
.sprig-link--quiet:hover {
|
|
332
|
+
text-decoration-thickness: 1.5px;
|
|
333
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
334
|
+
opacity: 1;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
@media (prefers-color-scheme: dark) {
|
|
338
|
+
a.sprig-link--quiet:hover,
|
|
339
|
+
.sprig-link--quiet:hover {
|
|
340
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
html[data-theme="dark"] a.sprig-link--quiet:hover,
|
|
345
|
+
html[data-theme="dark"] .sprig-link--quiet:hover {
|
|
346
|
+
text-decoration-color: rgba(255, 255, 255, 0.5);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
html[data-theme="light"] a.sprig-link--quiet:hover,
|
|
350
|
+
html[data-theme="light"] .sprig-link--quiet:hover {
|
|
351
|
+
text-decoration-color: rgba(0, 0, 0, 0.4);
|
|
352
|
+
}
|
|
353
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ES2020",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"checkJs": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": ["node_modules", "dist"]
|
|
15
|
+
}
|
|
16
|
+
|