@axle-lang/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/app.css +337 -0
  4. package/dist/components/Seo.svelte +38 -0
  5. package/dist/components/Seo.svelte.d.ts +8 -0
  6. package/dist/components/atoms/Badge.svelte +11 -0
  7. package/dist/components/atoms/Badge.svelte.d.ts +8 -0
  8. package/dist/components/atoms/Button.svelte +32 -0
  9. package/dist/components/atoms/Button.svelte.d.ts +12 -0
  10. package/dist/components/atoms/Callout.svelte +11 -0
  11. package/dist/components/atoms/Callout.svelte.d.ts +8 -0
  12. package/dist/components/atoms/CodeChip.svelte +11 -0
  13. package/dist/components/atoms/CodeChip.svelte.d.ts +8 -0
  14. package/dist/components/atoms/Eyebrow.svelte +9 -0
  15. package/dist/components/atoms/Eyebrow.svelte.d.ts +8 -0
  16. package/dist/components/atoms/HandNote.svelte +15 -0
  17. package/dist/components/atoms/HandNote.svelte.d.ts +9 -0
  18. package/dist/components/atoms/Icon.svelte +40 -0
  19. package/dist/components/atoms/Icon.svelte.d.ts +11 -0
  20. package/dist/components/atoms/Kbd.svelte +11 -0
  21. package/dist/components/atoms/Kbd.svelte.d.ts +8 -0
  22. package/dist/components/atoms/Logo.svelte +18 -0
  23. package/dist/components/atoms/Logo.svelte.d.ts +6 -0
  24. package/dist/components/atoms/SearchButton.svelte +23 -0
  25. package/dist/components/atoms/SearchButton.svelte.d.ts +8 -0
  26. package/dist/components/atoms/Tag.svelte +21 -0
  27. package/dist/components/atoms/Tag.svelte.d.ts +10 -0
  28. package/dist/components/atoms/ThemeToggle.svelte +30 -0
  29. package/dist/components/atoms/ThemeToggle.svelte.d.ts +6 -0
  30. package/dist/components/code/Code.svelte +22 -0
  31. package/dist/components/code/Code.svelte.d.ts +9 -0
  32. package/dist/components/code/CodeWindow.svelte +42 -0
  33. package/dist/components/code/CodeWindow.svelte.d.ts +13 -0
  34. package/dist/components/code/CopyCommand.svelte +28 -0
  35. package/dist/components/code/CopyCommand.svelte.d.ts +7 -0
  36. package/dist/components/landing/BenchExplorer.svelte +157 -0
  37. package/dist/components/landing/BenchExplorer.svelte.d.ts +7 -0
  38. package/dist/components/landing/CTASection.svelte +12 -0
  39. package/dist/components/landing/CTASection.svelte.d.ts +11 -0
  40. package/dist/components/landing/ComparisonPanel.svelte +75 -0
  41. package/dist/components/landing/ComparisonPanel.svelte.d.ts +19 -0
  42. package/dist/components/landing/FeatureCard.svelte +19 -0
  43. package/dist/components/landing/FeatureCard.svelte.d.ts +10 -0
  44. package/dist/components/landing/FeatureGrid.svelte +26 -0
  45. package/dist/components/landing/FeatureGrid.svelte.d.ts +13 -0
  46. package/dist/components/landing/Hero.svelte +23 -0
  47. package/dist/components/landing/Hero.svelte.d.ts +14 -0
  48. package/dist/components/landing/RecipeDeck.svelte +137 -0
  49. package/dist/components/landing/RecipeDeck.svelte.d.ts +19 -0
  50. package/dist/components/layout/DocLayout.svelte +36 -0
  51. package/dist/components/layout/DocLayout.svelte.d.ts +21 -0
  52. package/dist/components/layout/PageShell.svelte +15 -0
  53. package/dist/components/layout/PageShell.svelte.d.ts +7 -0
  54. package/dist/components/molecules/Card.svelte +18 -0
  55. package/dist/components/molecules/Card.svelte.d.ts +9 -0
  56. package/dist/components/molecules/DataTable.svelte +43 -0
  57. package/dist/components/molecules/DataTable.svelte.d.ts +12 -0
  58. package/dist/components/molecules/PageHeading.svelte +23 -0
  59. package/dist/components/molecules/PageHeading.svelte.d.ts +10 -0
  60. package/dist/components/molecules/Section.svelte +20 -0
  61. package/dist/components/molecules/Section.svelte.d.ts +10 -0
  62. package/dist/components/molecules/SectionHeading.svelte +27 -0
  63. package/dist/components/molecules/SectionHeading.svelte.d.ts +10 -0
  64. package/dist/components/nav/DocHeader.svelte +44 -0
  65. package/dist/components/nav/DocHeader.svelte.d.ts +7 -0
  66. package/dist/components/nav/Footer.svelte +67 -0
  67. package/dist/components/nav/Footer.svelte.d.ts +3 -0
  68. package/dist/components/nav/Header.svelte +55 -0
  69. package/dist/components/nav/Header.svelte.d.ts +6 -0
  70. package/dist/components/nav/PrevNext.svelte +27 -0
  71. package/dist/components/nav/PrevNext.svelte.d.ts +13 -0
  72. package/dist/components/nav/RightRail.svelte +30 -0
  73. package/dist/components/nav/RightRail.svelte.d.ts +11 -0
  74. package/dist/components/nav/Sidebar.svelte +33 -0
  75. package/dist/components/nav/Sidebar.svelte.d.ts +18 -0
  76. package/dist/components/reference/MethodDetail.svelte +72 -0
  77. package/dist/components/reference/MethodDetail.svelte.d.ts +7 -0
  78. package/dist/components/reference/MethodSummary.svelte +41 -0
  79. package/dist/components/reference/MethodSummary.svelte.d.ts +8 -0
  80. package/dist/i18n/index.d.ts +47 -0
  81. package/dist/i18n/index.js +23 -0
  82. package/dist/i18n/messages/en.d.ts +43 -0
  83. package/dist/i18n/messages/en.js +50 -0
  84. package/dist/index.d.ts +47 -0
  85. package/dist/index.js +54 -0
  86. package/dist/site/site.d.ts +45 -0
  87. package/dist/site/site.js +66 -0
  88. package/dist/utils/cn.d.ts +6 -0
  89. package/dist/utils/cn.js +9 -0
  90. package/dist/utils/icons.d.ts +26 -0
  91. package/dist/utils/icons.js +55 -0
  92. package/dist/utils/tokenizer.d.ts +12 -0
  93. package/dist/utils/tokenizer.js +181 -0
  94. package/dist/utils/types.d.ts +50 -0
  95. package/dist/utils/types.js +4 -0
  96. package/dist/utils/variants.d.ts +20 -0
  97. package/dist/utils/variants.js +50 -0
  98. package/package.json +77 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Axle Language
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # @axle-lang/ui
2
+
3
+ The Axle **design system** — a content-agnostic Svelte 5 + Tailwind v4
4
+ component library, shared by the Axle landing and docs sites.
5
+
6
+ It holds presentation only: components, the design tokens
7
+ (`src/lib/app.css`), the syntax tokenizer, the small utils
8
+ (`cn` / `cva` variants / icons), the cross-domain routing helpers, and
9
+ the i18n **chrome** catalog (UI labels). It contains **no page content** —
10
+ prose, the stdlib reference and benchmarks are generated in the
11
+ [`axle`](https://github.com/axle-lang/axle) repo and injected by the apps
12
+ at build time.
13
+
14
+ ```
15
+ src/lib/
16
+ ├── index.ts public barrel
17
+ ├── app.css Tailwind v4 tokens (the single source of truth)
18
+ ├── components/ atoms · molecules · code · nav · landing · layout · reference
19
+ ├── i18n/ synchronous svelte-i18n setup + chrome catalog + K keys
20
+ ├── site/ site.ts (buildSite / route / setSite / getSite) · version.ts
21
+ └── utils/ cn · variants (cva) · tokenizer · icons · types
22
+ ```
23
+
24
+ ## Consuming it
25
+
26
+ The package is **source-typed** and built with `@sveltejs/package` to
27
+ `dist/` (with `.d.ts`). Peer dependencies — `svelte`, `@sveltejs/kit`
28
+ (for the route-aware `Seo` / `Sidebar`), and `svelte-i18n` (one shared
29
+ locale store) — are provided by the consuming app.
30
+
31
+ Published to npm as a public package:
32
+
33
+ ```jsonc
34
+ // in each app's package.json
35
+ "dependencies": {
36
+ "@axle-lang/ui": "^0.1.0"
37
+ }
38
+ ```
39
+
40
+ ```js
41
+ import { Header, Footer, Seo, initI18n, setSite, buildSite, K } from '@axle-lang/ui';
42
+ import '@axle-lang/ui/app.css';
43
+ ```
44
+
45
+ i18n labels are referenced through the `K` keys object (never raw string
46
+ literals): `$t(K.nav.guide)`.
47
+
48
+ ## Develop
49
+
50
+ ```bash
51
+ pnpm install
52
+ pnpm dev # the in-repo gallery (src/routes) — visual smoke test
53
+ pnpm check # svelte-check (TypeScript)
54
+ pnpm lint # prettier --check + eslint
55
+ pnpm package # build dist/ + publint
56
+ pnpm format
57
+ ```
58
+
59
+ ## Publishing
60
+
61
+ Published to **npmjs** under the `@axle-lang` scope (public).
62
+
63
+ - **Automated** (preferred): publishing a GitHub Release triggers
64
+ `.github/workflows/publish.yml`, which runs `pnpm publish` with the
65
+ `NPM_TOKEN` repo secret. `prepare` builds `dist/` before packing and
66
+ `publishConfig.access` makes the scoped package public.
67
+ - **Manual**: `npm login` then `pnpm publish`.
68
+
69
+ Bump the version first with `npm version patch|minor|major`, then push
70
+ `--follow-tags` and cut the Release. Requires the `@axle-lang` npm org.
package/dist/app.css ADDED
@@ -0,0 +1,337 @@
1
+ /* =============================================================
2
+ Axle — Design System (Tailwind v4)
3
+ Single source of truth for tokens, fonts and primitives.
4
+ Import once in your app entry: @import "./app.css";
5
+ Works in mdbook (drop into theme/) and SvelteKit (src/app.css).
6
+ ============================================================= */
7
+
8
+ @import 'tailwindcss';
9
+
10
+ /* Dark mode is class-based: add `dark` on <html> (or any ancestor). */
11
+ @custom-variant dark (&:where(.dark, .dark *));
12
+
13
+ /* -------------------------------------------------------------
14
+ 1. Fonts
15
+ Self-host for production; the CDN links below are a quick start.
16
+ ------------------------------------------------------------- */
17
+
18
+ /* -------------------------------------------------------------
19
+ 2. Raw token values (light is the default theme)
20
+ Edit these to retheme the whole system.
21
+ ------------------------------------------------------------- */
22
+ :root {
23
+ /* Surfaces */
24
+ --canvas: #ffffff;
25
+ --surface: #faf9f7;
26
+ --surface2: #f1efea;
27
+ /* Text */
28
+ --fg: #15171c;
29
+ --muted: #5b626d;
30
+ --faint: #8b919c;
31
+ /* Lines & accent */
32
+ --line: #e9e6e0;
33
+ --accent: #ff5a1f;
34
+ --accent-soft: #fff1ea;
35
+ --ink-soft: #c2774a; /* handwritten annotation tone */
36
+ /* Code surface */
37
+ --code-strong: #0d1117;
38
+
39
+ /* Syntax (light) */
40
+ --sx-kw: #9333ea;
41
+ --sx-ty: #0e7490;
42
+ --sx-fn: #1d4ed8;
43
+ --sx-str: #15803d;
44
+ --sx-num: #b45309;
45
+ --sx-com: #9aa1ac;
46
+ --sx-p: #6b7280;
47
+ }
48
+
49
+ .dark {
50
+ --canvas: #0b0d11;
51
+ --surface: #0f1217;
52
+ --surface2: #161a21;
53
+ --fg: #e6e9ee;
54
+ --muted: #9aa2ae;
55
+ --faint: #69727f;
56
+ --line: #222831;
57
+ --accent: #ff6a33;
58
+ --accent-soft: #2a160d;
59
+ --ink-soft: #e0a071;
60
+ --code-strong: #080a0e;
61
+
62
+ --sx-kw: #c792ea;
63
+ --sx-ty: #5ccfe6;
64
+ --sx-fn: #82aaff;
65
+ --sx-str: #c3e88d;
66
+ --sx-num: #f78c6c;
67
+ --sx-com: #5c6675;
68
+ --sx-p: #8b94a3;
69
+ }
70
+
71
+ /* Code blocks always render on the dark surface, regardless of theme.
72
+ Add `.dark-code` to a code container to get the dark syntax palette. */
73
+ .dark-code {
74
+ --sx-kw: #c792ea;
75
+ --sx-ty: #5ccfe6;
76
+ --sx-fn: #82aaff;
77
+ --sx-str: #c3e88d;
78
+ --sx-num: #f78c6c;
79
+ --sx-com: #6b7587;
80
+ --sx-p: #8b94a3;
81
+ }
82
+
83
+ /* -------------------------------------------------------------
84
+ 3. Expose tokens to Tailwind utilities
85
+ Enables bg-canvas, text-fg, border-line, text-accent,
86
+ font-sans, font-mono, etc. — everywhere.
87
+ ------------------------------------------------------------- */
88
+ @theme inline {
89
+ --color-canvas: var(--canvas);
90
+ --color-surface: var(--surface);
91
+ --color-surface2: var(--surface2);
92
+ --color-fg: var(--fg);
93
+ --color-muted: var(--muted);
94
+ --color-faint: var(--faint);
95
+ --color-line: var(--line);
96
+ --color-accent: var(--accent);
97
+ --color-accent-soft: var(--accent-soft);
98
+ --color-ink-soft: var(--ink-soft);
99
+ --color-codebg: var(--code-strong);
100
+
101
+ --font-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
102
+ --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
103
+ --font-hand: 'Caveat', cursive;
104
+
105
+ /* Type scale used across docs + landing */
106
+ --text-display: clamp(36px, 5.2vw, 58px); /* hero h1 */
107
+ --text-h1: 34px; /* page title */
108
+ --text-h2: 22px; /* section */
109
+ --text-h3: 18px;
110
+ --text-body: 16px;
111
+ --text-sm: 13.5px;
112
+
113
+ /* Radii */
114
+ --radius-card: 12px; /* rounded-xl cards */
115
+ --radius-md: 8px;
116
+
117
+ /* Shadows */
118
+ --shadow-card: 0 1px 3px rgb(0 0 0 / 0.06);
119
+ --shadow-pop: 0 10px 30px rgb(0 0 0 / 0.12);
120
+ }
121
+
122
+ /* -------------------------------------------------------------
123
+ 4. Base resets
124
+ ------------------------------------------------------------- */
125
+ @layer base {
126
+ html,
127
+ body {
128
+ margin: 0;
129
+ padding: 0;
130
+ }
131
+ body {
132
+ font-family: var(--font-sans);
133
+ background: var(--canvas);
134
+ color: var(--fg);
135
+ -webkit-font-smoothing: antialiased;
136
+ text-rendering: optimizeLegibility;
137
+ }
138
+ ::selection {
139
+ background: var(--accent);
140
+ color: #fff;
141
+ }
142
+ }
143
+
144
+ /* -------------------------------------------------------------
145
+ 5. Component primitives
146
+ Reusable classes the Svelte components (and mdbook) lean on.
147
+ ------------------------------------------------------------- */
148
+ @layer components {
149
+ /* Thin scrollbar used on code/overflow areas */
150
+ .axle-scroll::-webkit-scrollbar {
151
+ width: 9px;
152
+ height: 9px;
153
+ }
154
+ .axle-scroll::-webkit-scrollbar-thumb {
155
+ background: var(--line);
156
+ border-radius: 9px;
157
+ }
158
+ .axle-scroll::-webkit-scrollbar-track {
159
+ background: transparent;
160
+ }
161
+
162
+ /* Syntax highlight token colors (pair with a tokenizer that
163
+ emits .t-kw / .t-ty / .t-fn / .t-str / .t-num / .t-com / .t-p) */
164
+ .t-kw {
165
+ color: var(--sx-kw);
166
+ font-weight: 500;
167
+ }
168
+ .t-ty {
169
+ color: var(--sx-ty);
170
+ }
171
+ .t-fn {
172
+ color: var(--sx-fn);
173
+ }
174
+ .t-str {
175
+ color: var(--sx-str);
176
+ }
177
+ .t-num {
178
+ color: var(--sx-num);
179
+ }
180
+ .t-com {
181
+ color: var(--sx-com);
182
+ font-style: italic;
183
+ }
184
+ .t-p {
185
+ color: var(--sx-p);
186
+ }
187
+ .dark-code pre code {
188
+ color: #c3cad6;
189
+ }
190
+
191
+ /* Handwritten annotation + thin hand-drawn underline */
192
+ .ink {
193
+ font-family: var(--font-hand);
194
+ color: var(--accent);
195
+ line-height: 1;
196
+ }
197
+ .note {
198
+ font-family: var(--font-hand);
199
+ color: var(--ink-soft);
200
+ line-height: 1.4;
201
+ }
202
+ .uline {
203
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 6 C 22 2, 42 9, 62 5 S 102 2, 118 6' fill='none' stroke='%23c2774a' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
204
+ background-repeat: no-repeat;
205
+ background-position: 0 100%;
206
+ background-size: 100% 0.34em;
207
+ padding-bottom: 0.16em;
208
+ }
209
+ .dark .uline {
210
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 6 C 22 2, 42 9, 62 5 S 102 2, 118 6' fill='none' stroke='%23e0a071' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
211
+ }
212
+
213
+ /* Marker swipe highlight (used on the hero word) */
214
+ .mark {
215
+ background: linear-gradient(120deg, var(--accent-soft) 0%, var(--accent-soft) 100%);
216
+ background-repeat: no-repeat;
217
+ background-position: 0 88%;
218
+ background-size: 100% 38%;
219
+ border-radius: 1px;
220
+ }
221
+ .dark .mark {
222
+ background-image: linear-gradient(
223
+ 120deg,
224
+ color-mix(in oklch, var(--accent) 32%, transparent) 0%,
225
+ color-mix(in oklch, var(--accent) 32%, transparent) 100%
226
+ );
227
+ }
228
+
229
+ /* --- Buttons --- */
230
+ .btn {
231
+ display: inline-flex;
232
+ align-items: center;
233
+ gap: 0.375rem;
234
+ height: 2.75rem;
235
+ padding-inline: 1.25rem;
236
+ border-radius: var(--radius-md);
237
+ font-size: 14px;
238
+ font-weight: 500;
239
+ cursor: pointer;
240
+ transition:
241
+ opacity 0.15s,
242
+ background-color 0.15s,
243
+ border-color 0.15s;
244
+ }
245
+ .btn-primary {
246
+ background: var(--accent);
247
+ color: #fff;
248
+ }
249
+ .btn-primary:hover {
250
+ opacity: 0.9;
251
+ }
252
+ .btn-secondary {
253
+ background: var(--canvas);
254
+ color: var(--fg);
255
+ border: 1px solid var(--line);
256
+ }
257
+ .btn-secondary:hover {
258
+ background: var(--surface);
259
+ }
260
+
261
+ /* --- Card --- */
262
+ .card {
263
+ background: var(--canvas);
264
+ border: 1px solid var(--line);
265
+ border-radius: var(--radius-card);
266
+ }
267
+ .card-muted {
268
+ background: var(--surface);
269
+ border: 1px solid var(--line);
270
+ border-radius: var(--radius-card);
271
+ }
272
+
273
+ /* --- Inline code chip --- */
274
+ .code-chip {
275
+ font-family: var(--font-mono);
276
+ font-size: 12px;
277
+ border: 1px solid var(--line);
278
+ background: var(--surface);
279
+ color: var(--muted);
280
+ border-radius: var(--radius-md);
281
+ padding: 0.25rem 0.5rem;
282
+ }
283
+
284
+ /* --- Callout (info/note banner) --- */
285
+ .callout {
286
+ display: flex;
287
+ gap: 0.75rem;
288
+ border-left: 2px solid var(--accent);
289
+ background: var(--accent-soft);
290
+ border-radius: var(--radius-card);
291
+ padding: 1rem 1.25rem;
292
+ }
293
+
294
+ /* --- Eyebrow / kicker label --- */
295
+ .eyebrow {
296
+ font-size: 12px;
297
+ font-weight: 600;
298
+ letter-spacing: 0.14em;
299
+ text-transform: uppercase;
300
+ color: var(--accent);
301
+ }
302
+ }
303
+
304
+ /* -------------------------------------------------------------
305
+ 6. Keyframes
306
+ ------------------------------------------------------------- */
307
+ @keyframes axle-blink {
308
+ 0%,
309
+ 49% {
310
+ opacity: 1;
311
+ }
312
+ 50%,
313
+ 100% {
314
+ opacity: 0;
315
+ }
316
+ }
317
+ @keyframes axle-deck-in {
318
+ 0% {
319
+ opacity: 0.4;
320
+ transform: translateY(6px);
321
+ }
322
+ 100% {
323
+ opacity: 1;
324
+ transform: none;
325
+ }
326
+ }
327
+ @keyframes axle-prog {
328
+ 0% {
329
+ width: 0;
330
+ }
331
+ 100% {
332
+ width: 100%;
333
+ }
334
+ }
335
+ .cursor-blink {
336
+ animation: axle-blink 1.05s steps(1) infinite;
337
+ }
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ // Per-page SEO head: title, description, canonical, Open Graph, Twitter.
3
+ // Canonical/OG URL is built from the site origin (injected via setSite)
4
+ // + the current path.
5
+ import { page } from '$app/state';
6
+ import { getSite } from '../site/site.js';
7
+
8
+ let {
9
+ title = '',
10
+ description = '',
11
+ image = ''
12
+ }: { title?: string; description?: string; image?: string } = $props();
13
+
14
+ const { origin = '' } = getSite();
15
+ const url = $derived(origin + page.url.pathname);
16
+ const fullTitle = $derived(
17
+ !title ? 'Axle' : title.startsWith('Axle') ? title : `${title} · Axle`
18
+ );
19
+ const card = $derived(image ? 'summary_large_image' : 'summary');
20
+ </script>
21
+
22
+ <svelte:head>
23
+ <title>{fullTitle}</title>
24
+ {#if description}<meta name="description" content={description} />{/if}
25
+ <link rel="canonical" href={url} />
26
+
27
+ <meta property="og:type" content="website" />
28
+ <meta property="og:site_name" content="Axle" />
29
+ <meta property="og:title" content={fullTitle} />
30
+ {#if description}<meta property="og:description" content={description} />{/if}
31
+ <meta property="og:url" content={url} />
32
+ {#if image}<meta property="og:image" content={image} />{/if}
33
+
34
+ <meta name="twitter:card" content={card} />
35
+ <meta name="twitter:title" content={fullTitle} />
36
+ {#if description}<meta name="twitter:description" content={description} />{/if}
37
+ {#if image}<meta name="twitter:image" content={image} />{/if}
38
+ </svelte:head>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ title?: string;
3
+ description?: string;
4
+ image?: string;
5
+ };
6
+ declare const Seo: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Seo = ReturnType<typeof Seo>;
8
+ export default Seo;
@@ -0,0 +1,11 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ /** Pill badge, e.g. version tag. */
4
+ let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
5
+ </script>
6
+
7
+ <span
8
+ class="inline-flex items-center rounded-full border border-line px-2 py-0.5 text-[11px] font-medium text-muted whitespace-nowrap {klass}"
9
+ >
10
+ {@render children?.()}
11
+ </span>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ class?: string;
4
+ children?: Snippet;
5
+ };
6
+ declare const Badge: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Badge = ReturnType<typeof Badge>;
8
+ export default Badge;
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { button } from '../../utils/variants.js';
4
+ import { cn } from '../../utils/cn.js';
5
+ /**
6
+ * Button / link. Renders <a> when `href` is set, otherwise <button>.
7
+ */
8
+ let {
9
+ variant = 'primary',
10
+ href,
11
+ onclick,
12
+ size = 'md',
13
+ class: klass = '',
14
+ children,
15
+ ...rest
16
+ }: {
17
+ variant?: 'primary' | 'secondary';
18
+ href?: string;
19
+ onclick?: (e: MouseEvent) => void;
20
+ size?: 'sm' | 'md';
21
+ class?: string;
22
+ children?: Snippet;
23
+ } = $props();
24
+
25
+ const cls = $derived(cn(button({ variant, size }), klass));
26
+ </script>
27
+
28
+ {#if href}
29
+ <a {href} class={cls} {...rest}>{@render children?.()}</a>
30
+ {:else}
31
+ <button type="button" {onclick} class={cls} {...rest}>{@render children?.()}</button>
32
+ {/if}
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ variant?: 'primary' | 'secondary';
4
+ href?: string;
5
+ onclick?: (e: MouseEvent) => void;
6
+ size?: 'sm' | 'md';
7
+ class?: string;
8
+ children?: Snippet;
9
+ };
10
+ declare const Button: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type Button = ReturnType<typeof Button>;
12
+ export default Button;
@@ -0,0 +1,11 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import Icon from './Icon.svelte';
4
+ /** Info / note banner with accent left border. */
5
+ let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
6
+ </script>
7
+
8
+ <div class="flex gap-3 rounded-xl border-l-2 border-accent bg-accent-soft px-5 py-4 {klass}">
9
+ <span class="text-accent mt-0.5 shrink-0"><Icon name="info" size={18} /></span>
10
+ <p class="text-[14px] leading-relaxed text-fg">{@render children?.()}</p>
11
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ class?: string;
4
+ children?: Snippet;
5
+ };
6
+ declare const Callout: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Callout = ReturnType<typeof Callout>;
8
+ export default Callout;
@@ -0,0 +1,11 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ /** Inline monospace code chip. */
4
+ let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
5
+ </script>
6
+
7
+ <code
8
+ class="font-mono text-[12px] rounded-md border border-line bg-surface px-2 py-1 text-muted {klass}"
9
+ >
10
+ {@render children?.()}
11
+ </code>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ class?: string;
4
+ children?: Snippet;
5
+ };
6
+ declare const CodeChip: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type CodeChip = ReturnType<typeof CodeChip>;
8
+ export default CodeChip;
@@ -0,0 +1,9 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ /** Uppercase accent kicker label. */
4
+ let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
5
+ </script>
6
+
7
+ <div class="text-[12px] font-semibold tracking-[0.14em] text-accent uppercase {klass}">
8
+ {@render children?.()}
9
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ class?: string;
4
+ children?: Snippet;
5
+ };
6
+ declare const Eyebrow: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Eyebrow = ReturnType<typeof Eyebrow>;
8
+ export default Eyebrow;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ /**
4
+ * Handwritten margin note. Wrap the keyword to underline in {#snippet} or
5
+ * pass plain text; set `underline` to the substring you want hand-underlined.
6
+ * Simplest usage: <HandNote>Because comfortable code should never cost you <span class="uline">performance</span>.</HandNote>
7
+ */
8
+ let {
9
+ size = 21,
10
+ class: klass = '',
11
+ children
12
+ }: { size?: number; class?: string; children?: Snippet } = $props();
13
+ </script>
14
+
15
+ <span class="note leading-[1.4] {klass}" style="font-size:{size}px">{@render children?.()}</span>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ size?: number;
4
+ class?: string;
5
+ children?: Snippet;
6
+ };
7
+ declare const HandNote: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type HandNote = ReturnType<typeof HandNote>;
9
+ export default HandNote;
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ import { icons } from '../../utils/icons.js';
3
+ import type { IconName } from '../../utils/icons.js';
4
+
5
+ /**
6
+ * Atomic icon. Pass either a known `name` (see lib/icons.js) or raw `paths`.
7
+ */
8
+ let {
9
+ name,
10
+ paths,
11
+ size = 16,
12
+ stroke = 1.7,
13
+ class: klass = ''
14
+ }: {
15
+ name?: IconName;
16
+ paths?: string[];
17
+ size?: number;
18
+ stroke?: number;
19
+ class?: string;
20
+ } = $props();
21
+
22
+ const d = $derived(paths ?? (name ? icons[name] : undefined) ?? []);
23
+ </script>
24
+
25
+ <svg
26
+ width={size}
27
+ height={size}
28
+ viewBox="0 0 24 24"
29
+ fill="none"
30
+ stroke="currentColor"
31
+ stroke-width={stroke}
32
+ stroke-linecap="round"
33
+ stroke-linejoin="round"
34
+ class={klass}
35
+ aria-hidden="true"
36
+ >
37
+ {#each d as p}
38
+ <path d={p} />
39
+ {/each}
40
+ </svg>
@@ -0,0 +1,11 @@
1
+ import type { IconName } from '../../utils/icons.js';
2
+ type $$ComponentProps = {
3
+ name?: IconName;
4
+ paths?: string[];
5
+ size?: number;
6
+ stroke?: number;
7
+ class?: string;
8
+ };
9
+ declare const Icon: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type Icon = ReturnType<typeof Icon>;
11
+ export default Icon;