@miozu/jera 0.0.2 → 0.3.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 (53) hide show
  1. package/CLAUDE.md +443 -0
  2. package/README.md +211 -1
  3. package/llms.txt +64 -0
  4. package/package.json +44 -14
  5. package/src/actions/index.js +375 -0
  6. package/src/components/feedback/EmptyState.svelte +179 -0
  7. package/src/components/feedback/ProgressBar.svelte +116 -0
  8. package/src/components/feedback/Skeleton.svelte +107 -0
  9. package/src/components/feedback/Spinner.svelte +77 -0
  10. package/src/components/feedback/Toast.svelte +297 -0
  11. package/src/components/forms/Checkbox.svelte +147 -0
  12. package/src/components/forms/Dropzone.svelte +248 -0
  13. package/src/components/forms/FileUpload.svelte +266 -0
  14. package/src/components/forms/IconInput.svelte +184 -0
  15. package/src/components/forms/Input.svelte +121 -0
  16. package/src/components/forms/NumberInput.svelte +225 -0
  17. package/src/components/forms/PinInput.svelte +169 -0
  18. package/src/components/forms/Radio.svelte +143 -0
  19. package/src/components/forms/RadioGroup.svelte +62 -0
  20. package/src/components/forms/RangeSlider.svelte +212 -0
  21. package/src/components/forms/SearchInput.svelte +175 -0
  22. package/src/components/forms/Select.svelte +326 -0
  23. package/src/components/forms/Switch.svelte +159 -0
  24. package/src/components/forms/Textarea.svelte +122 -0
  25. package/src/components/navigation/Accordion.svelte +65 -0
  26. package/src/components/navigation/AccordionItem.svelte +146 -0
  27. package/src/components/navigation/Tabs.svelte +239 -0
  28. package/src/components/overlays/ConfirmDialog.svelte +272 -0
  29. package/src/components/overlays/Dropdown.svelte +153 -0
  30. package/src/components/overlays/DropdownDivider.svelte +23 -0
  31. package/src/components/overlays/DropdownItem.svelte +97 -0
  32. package/src/components/overlays/Modal.svelte +232 -0
  33. package/src/components/overlays/Popover.svelte +206 -0
  34. package/src/components/primitives/Avatar.svelte +132 -0
  35. package/src/components/primitives/Badge.svelte +118 -0
  36. package/src/components/primitives/Button.svelte +262 -0
  37. package/src/components/primitives/Card.svelte +104 -0
  38. package/src/components/primitives/Divider.svelte +105 -0
  39. package/src/components/primitives/LazyImage.svelte +104 -0
  40. package/src/components/primitives/Link.svelte +122 -0
  41. package/src/components/primitives/StatusBadge.svelte +122 -0
  42. package/src/index.js +128 -0
  43. package/src/tokens/colors.css +189 -0
  44. package/src/tokens/effects.css +128 -0
  45. package/src/tokens/index.css +81 -0
  46. package/src/tokens/spacing.css +49 -0
  47. package/src/tokens/typography.css +79 -0
  48. package/src/utils/cn.svelte.js +175 -0
  49. package/src/utils/index.js +17 -0
  50. package/src/utils/reactive.svelte.js +239 -0
  51. package/jera.js +0 -135
  52. package/www/components/jera/Input/Input.svelte +0 -63
  53. package/www/components/jera/Input/index.js +0 -1
package/CLAUDE.md ADDED
@@ -0,0 +1,443 @@
1
+ # @miozu/jera - AI Context File
2
+
3
+ **Package:** @miozu/jera
4
+ **Purpose:** Minimal, reactive component library for Svelte 5
5
+ **Author:** Nicholas Glazer <glazer.nicholas@gmail.com>
6
+
7
+ ---
8
+
9
+ ## Project Structure
10
+
11
+ ```
12
+ jera/
13
+ ├── src/
14
+ │ ├── index.js # Main exports
15
+ │ ├── tokens/ # Design tokens (CSS custom properties)
16
+ │ │ ├── index.css # Bundle all tokens
17
+ │ │ ├── colors.css # Miozu Base16 palette
18
+ │ │ ├── spacing.css # 4px-based scale
19
+ │ │ ├── typography.css # Font system
20
+ │ │ └── effects.css # Shadows, radius, transitions
21
+ │ ├── utils/
22
+ │ │ ├── cn.svelte.js # cn(), cv() class utilities
23
+ │ │ └── reactive.svelte.js # ThemeState, reactive helpers
24
+ │ ├── actions/
25
+ │ │ └── index.js # Svelte actions
26
+ │ └── components/
27
+ │ ├── primitives/ # Button, Badge, Divider, Avatar
28
+ │ ├── forms/ # Input, Select, Checkbox, Switch
29
+ │ ├── feedback/ # Toast, Skeleton, ProgressBar, Spinner
30
+ │ ├── overlays/ # Modal, Popover
31
+ │ └── navigation/ # Tabs, Accordion, AccordionItem
32
+ ├── llms.txt # AI documentation index
33
+ ├── CLAUDE.md # This file
34
+ └── package.json
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Coding Standards
40
+
41
+ ### Svelte 5 Patterns (REQUIRED)
42
+ - Use `$props()` for component props (single call only)
43
+ - Use `$state()` for reactive local state
44
+ - Use `$derived()` for computed values
45
+ - Use `$effect()` sparingly, only for side effects
46
+ - Use `$bindable()` for two-way binding props
47
+
48
+ ### Component Template
49
+ ```svelte
50
+ <script>
51
+ let {
52
+ variant = 'default',
53
+ size = 'md',
54
+ disabled = false,
55
+ class: className = '',
56
+ ...rest
57
+ } = $props();
58
+
59
+ const computedClass = $derived(/* class logic */);
60
+ </script>
61
+
62
+ <element class={computedClass} {disabled} {...rest}>
63
+ {@render children?.()}
64
+ </element>
65
+ ```
66
+
67
+ ### Class Variants (cv) Pattern
68
+ ```javascript
69
+ export const componentStyles = cv({
70
+ base: 'base-classes here',
71
+ variants: {
72
+ variantName: {
73
+ option1: 'classes-for-option1',
74
+ option2: 'classes-for-option2'
75
+ }
76
+ },
77
+ compounds: [
78
+ { condition: { variant: 'x', size: 'y' }, class: 'compound-classes' }
79
+ ],
80
+ defaults: { variantName: 'option1' }
81
+ });
82
+ ```
83
+
84
+ ### Naming Conventions
85
+ - Components: PascalCase (`Button.svelte`)
86
+ - Utilities: camelCase (`createThemeContext`)
87
+ - CSS tokens: kebab-case (`--color-primary`)
88
+ - Actions: camelCase (`clickOutside`)
89
+
90
+ ---
91
+
92
+ ## Miozu Color System
93
+
94
+ ### Base Colors (Grayscale)
95
+ | Token | Hex | Usage |
96
+ |-------|-----|-------|
97
+ | `--base0` | #232733 | Darkest background |
98
+ | `--base1` | #2C3040 | Default dark bg |
99
+ | `--base2` | #3E4359 | Selection, hover |
100
+ | `--base3` | #565E78 | Comments, subtle |
101
+ | `--base4` | #737E99 | Muted text |
102
+ | `--base5` | #D0D2DB | Default text |
103
+ | `--base6` | #F3F4F7 | Light text |
104
+ | `--base7` | #FAFDFB | Lightest/white |
105
+
106
+ ### Accent Colors
107
+ | Token | Hex | Usage |
108
+ |-------|-----|-------|
109
+ | `--magenta` | #C974E6 | Primary brand |
110
+ | `--blue` | #83D2FC | Info, links |
111
+ | `--green` | #6DD672 | Success |
112
+ | `--yellow` | #E8D176 | Warning |
113
+ | `--red` | #EB3137 | Error |
114
+ | `--cyan` | #40FFE2 | Accent |
115
+ | `--orange` | #FF9837 | Attention |
116
+ | `--peach` | #FF9982 | Warm accent |
117
+
118
+ ### Semantic Mappings
119
+ ```css
120
+ --color-bg: var(--base0);
121
+ --color-surface: var(--base1);
122
+ --color-text: var(--base5);
123
+ --color-text-strong: var(--base7);
124
+ --color-primary: var(--magenta);
125
+ --color-success: var(--green);
126
+ --color-error: var(--red);
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Component API Reference
132
+
133
+ ### Button
134
+ ```svelte
135
+ <Button
136
+ variant="primary|secondary|ghost|outline|danger|success"
137
+ size="xs|sm|md|lg|xl"
138
+ disabled={boolean}
139
+ loading={boolean}
140
+ fullWidth={boolean}
141
+ href={string} // Renders as <a> if provided
142
+ onclick={function}
143
+ >
144
+ Content
145
+ </Button>
146
+ ```
147
+
148
+ ### Input
149
+ ```svelte
150
+ <Input
151
+ bind:value={string}
152
+ type="text|email|password|number|..."
153
+ placeholder={string}
154
+ disabled={boolean}
155
+ required={boolean}
156
+ oninput={function}
157
+ onchange={function}
158
+ />
159
+ ```
160
+
161
+ ### Select
162
+ ```svelte
163
+ <Select
164
+ options={[{ value, label }]}
165
+ bind:value={any}
166
+ placeholder={string}
167
+ labelKey="label"
168
+ valueKey="value"
169
+ disabled={boolean}
170
+ onchange={function}
171
+ />
172
+ ```
173
+
174
+ ### Badge
175
+ ```svelte
176
+ <Badge
177
+ variant="default|primary|secondary|success|warning|error"
178
+ size="sm|md|lg"
179
+ >
180
+ Text
181
+ </Badge>
182
+ ```
183
+
184
+ ### Toast
185
+ ```svelte
186
+ <!-- In root layout -->
187
+ <script>
188
+ import { Toast, createToastContext } from '@miozu/jera';
189
+ const toast = createToastContext();
190
+ </script>
191
+ <Toast />
192
+
193
+ <!-- Usage anywhere -->
194
+ <script>
195
+ import { getToastContext } from '@miozu/jera';
196
+ const toast = getToastContext();
197
+ toast.success('Message');
198
+ toast.error('Error message');
199
+ </script>
200
+ ```
201
+
202
+ ### Modal
203
+ ```svelte
204
+ <script>
205
+ import { Modal, Button } from '@miozu/jera';
206
+ let showModal = $state(false);
207
+ </script>
208
+
209
+ <Button onclick={() => showModal = true}>Open Modal</Button>
210
+
211
+ <Modal bind:open={showModal} title="Confirm Action" variant="danger">
212
+ <p>Are you sure you want to proceed?</p>
213
+ {#snippet footer()}
214
+ <Button variant="ghost" onclick={() => showModal = false}>Cancel</Button>
215
+ <Button variant="danger" onclick={handleConfirm}>Confirm</Button>
216
+ {/snippet}
217
+ </Modal>
218
+ ```
219
+
220
+ Props: `open`, `title`, `size` (sm/md/lg/xl), `variant` (default/danger/warning/success/info), `closeOnBackdrop`, `closeOnEscape`, `showClose`, `children`, `footer`, `icon`, `onclose`
221
+
222
+ ### Popover
223
+ ```svelte
224
+ <script>
225
+ import { Popover, Button } from '@miozu/jera';
226
+ </script>
227
+
228
+ <Popover content="Helpful tooltip text" position="top">
229
+ <Button>Hover me</Button>
230
+ </Popover>
231
+ ```
232
+
233
+ Props: `content`, `position` (top/bottom/left/right), `delay` ({show, hide}), `offset`
234
+
235
+ ### Divider
236
+ ```svelte
237
+ <Divider />
238
+ <Divider orientation="vertical" />
239
+ <Divider>or continue with</Divider>
240
+ ```
241
+
242
+ Props: `orientation` (horizontal/vertical), `thickness`, `spacing`, `children`
243
+
244
+ ### Avatar
245
+ ```svelte
246
+ <Avatar src="/user.jpg" alt="John Doe" />
247
+ <Avatar name="John Doe" />
248
+ <Avatar src="/user.jpg" status="online" size="lg" />
249
+ ```
250
+
251
+ Props: `src`, `alt`, `name`, `size` (xs/sm/md/lg/xl/2xl), `status` (online/offline/busy/away)
252
+
253
+ ### Skeleton
254
+ ```svelte
255
+ <Skeleton width="80%" />
256
+ <Skeleton variant="circle" size="48px" />
257
+ <Skeleton variant="rect" width="100%" height="200px" />
258
+ <Skeleton lines={3} />
259
+ ```
260
+
261
+ Props: `variant` (text/heading/circle/rect), `width`, `height`, `size`, `lines`, `animate`
262
+
263
+ ### ProgressBar
264
+ ```svelte
265
+ <ProgressBar value={65} />
266
+ <ProgressBar value={80} showLabel variant="success" />
267
+ <ProgressBar indeterminate />
268
+ ```
269
+
270
+ Props: `value`, `max`, `size` (sm/md/lg), `variant` (primary/success/warning/error/info), `showLabel`, `label`, `indeterminate`
271
+
272
+ ### Spinner
273
+ ```svelte
274
+ <Spinner />
275
+ <Spinner size="lg" color="var(--color-base11)" />
276
+ ```
277
+
278
+ Props: `size` (xs/sm/md/lg/xl), `color`, `label`
279
+
280
+ ### Tabs
281
+ ```svelte
282
+ <script>
283
+ import { Tabs } from '@miozu/jera';
284
+ let activeTab = $state('tab1');
285
+ </script>
286
+
287
+ <Tabs
288
+ tabs={[
289
+ { id: 'tab1', label: 'Overview' },
290
+ { id: 'tab2', label: 'Settings', badge: 3 },
291
+ { id: 'tab3', label: 'Analytics', disabled: true }
292
+ ]}
293
+ bind:active={activeTab}
294
+ variant="underline"
295
+ />
296
+ ```
297
+
298
+ Props: `tabs` (array), `active`, `variant` (default/underline/pills), `size` (sm/md/lg), `fullWidth`, `onchange`
299
+
300
+ ### Accordion
301
+ ```svelte
302
+ <script>
303
+ import { Accordion, AccordionItem } from '@miozu/jera';
304
+ </script>
305
+
306
+ <Accordion multiple>
307
+ <AccordionItem id="section1" title="Section 1">
308
+ Content for section 1
309
+ </AccordionItem>
310
+ <AccordionItem id="section2" title="Section 2">
311
+ Content for section 2
312
+ </AccordionItem>
313
+ </Accordion>
314
+ ```
315
+
316
+ Accordion props: `expanded` (array of ids), `multiple`
317
+ AccordionItem props: `id`, `title`, `disabled`
318
+
319
+ ---
320
+
321
+ ## Actions Reference
322
+
323
+ ### clickOutside
324
+ ```svelte
325
+ <div use:clickOutside={() => isOpen = false}>
326
+ ```
327
+
328
+ ### focusTrap
329
+ ```svelte
330
+ <dialog use:focusTrap={{ enabled: isOpen }}>
331
+ ```
332
+
333
+ ### portal
334
+ ```svelte
335
+ <div use:portal={'body'}>
336
+ Renders at body level
337
+ </div>
338
+ ```
339
+
340
+ ### escapeKey
341
+ ```svelte
342
+ <div use:escapeKey={() => close()}>
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Common Tasks
348
+
349
+ ### Add New Component
350
+ 1. Create file in appropriate folder (`primitives/`, `forms/`, `feedback/`)
351
+ 2. Use single `$props()` call
352
+ 3. Export styles with `cv()` if variants needed
353
+ 4. Add to `src/index.js` exports
354
+ 5. Document in this file
355
+
356
+ ### Add New Token
357
+ 1. Add to appropriate token file in `src/tokens/`
358
+ 2. Use semantic naming
359
+ 3. Add light theme variant if applicable
360
+
361
+ ### Theme Switching
362
+ ```javascript
363
+ // System preference detection
364
+ const theme = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
365
+ document.documentElement.setAttribute('data-theme', theme);
366
+
367
+ // Or use ThemeState class
368
+ import { createThemeContext } from '@miozu/jera';
369
+ const theme = createThemeContext();
370
+ theme.init(); // Reads from localStorage/system
371
+ theme.toggle();
372
+ ```
373
+
374
+ ### Supported Theme Selectors
375
+ jera supports multiple theme attribute values for flexibility:
376
+
377
+ | Theme | Selectors |
378
+ |-------|-----------|
379
+ | Dark | `[data-theme="dark"]`, `[data-theme="miozu-dark"]`, `.dark` |
380
+ | Light | `[data-theme="light"]`, `[data-theme="miozu-light"]`, `.light` |
381
+ | High Contrast | `[data-theme="high-contrast"]` |
382
+
383
+ This allows jera to integrate with any theming system. For example:
384
+ - Selify apps use `miozu-dark` / `miozu-light`
385
+ - Generic apps can use `dark` / `light`
386
+ - Class-based theming via `.dark` / `.light`
387
+
388
+ ---
389
+
390
+ ## Integration with dash.selify.ai
391
+
392
+ jera components work out-of-the-box with dash.selify.ai. The semantic tokens are already configured in both systems.
393
+
394
+ ### Required: Import jera tokens
395
+ ```css
396
+ /* In your app.css or layout */
397
+ @import '@miozu/jera/tokens/colors.css';
398
+ ```
399
+
400
+ ### Semantic Token Mapping
401
+ | jera Token | dash.selify.ai Equivalent |
402
+ |------------|---------------------------|
403
+ | `--color-bg` | `--color-base00` |
404
+ | `--color-surface` | `--color-base01` |
405
+ | `--color-surface-alt` | `--color-base02` |
406
+ | `--color-text` | `--color-base05` |
407
+ | `--color-text-strong` | `--color-base07` |
408
+ | `--color-text-muted` | `--color-base04` |
409
+ | `--color-primary` | `--color-base0D` |
410
+ | `--color-success` | `--color-base0B` |
411
+ | `--color-warning` | `--color-base0A` |
412
+ | `--color-error` | `--color-base08` |
413
+ | `--color-info` | `--color-base0C` |
414
+
415
+ ### Using jera Components in dash.selify.ai
416
+ ```svelte
417
+ <script>
418
+ import { Button, Modal, Input } from '@miozu/jera';
419
+
420
+ let showModal = $state(false);
421
+ </script>
422
+
423
+ <!-- Works with existing dash.selify.ai theme system -->
424
+ <Button variant="primary" onclick={() => showModal = true}>
425
+ Open Modal
426
+ </Button>
427
+
428
+ <Modal bind:open={showModal} title="Example">
429
+ <Input placeholder="Type here..." />
430
+ </Modal>
431
+ ```
432
+
433
+ ---
434
+
435
+ ## Rules for AI Assistants
436
+
437
+ 1. **Always use Svelte 5 runes** - No legacy `$:`, `export let`, stores
438
+ 2. **Single $props() call** - Destructure all props in one call
439
+ 3. **Use cv() for variants** - Don't hardcode conditional classes
440
+ 4. **Semantic colors** - Use `--color-*` tokens, not raw `--base*`
441
+ 5. **Accessibility first** - Include ARIA attributes, keyboard support
442
+ 6. **No TypeScript** - Pure JavaScript with JSDoc for documentation
443
+ 7. **Mobile-first** - Design for mobile, enhance for desktop
package/README.md CHANGED
@@ -1 +1,211 @@
1
- # Jera
1
+ # @miozu/jera
2
+
3
+ A minimal, reactive component library for Svelte 5.
4
+
5
+ **Jera** (ᛃ) — the rune of harvest and cycles. Build on foundations, yield results.
6
+
7
+ ## Features
8
+
9
+ - **Miozu Design Tokens** — Base16 color system, spacing, typography, effects
10
+ - **Reactive Utilities** — `cn()`, `cv()` for class composition with Svelte 5 runes
11
+ - **Accessible Components** — Button, Input, Select, Badge, Checkbox, Switch, Toast
12
+ - **Svelte Actions** — clickOutside, focusTrap, portal, escapeKey, and more
13
+ - **AI-First Documentation** — Optimized for LLM-assisted development
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @miozu/jera
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```svelte
24
+ <script>
25
+ import { Button, Input, Badge } from '@miozu/jera';
26
+ import '@miozu/jera/tokens';
27
+
28
+ let email = $state('');
29
+ </script>
30
+
31
+ <Input bind:value={email} type="email" placeholder="Enter email" />
32
+ <Button onclick={() => console.log(email)}>Submit</Button>
33
+ <Badge variant="success">Active</Badge>
34
+ ```
35
+
36
+ ## Design Tokens
37
+
38
+ Import tokens for consistent styling:
39
+
40
+ ```css
41
+ /* All tokens */
42
+ @import '@miozu/jera/tokens';
43
+
44
+ /* Individual token sets */
45
+ @import '@miozu/jera/tokens/colors';
46
+ @import '@miozu/jera/tokens/spacing';
47
+ @import '@miozu/jera/tokens/typography';
48
+ @import '@miozu/jera/tokens/effects';
49
+ ```
50
+
51
+ ### Miozu Color Palette
52
+
53
+ | Base | Hex | Accent | Hex |
54
+ |------|-----|--------|-----|
55
+ | base0 | `#232733` | magenta | `#C974E6` |
56
+ | base1 | `#2C3040` | blue | `#83D2FC` |
57
+ | base2 | `#3E4359` | green | `#6DD672` |
58
+ | base3 | `#565E78` | yellow | `#E8D176` |
59
+ | base4 | `#737E99` | red | `#EB3137` |
60
+ | base5 | `#D0D2DB` | cyan | `#40FFE2` |
61
+ | base6 | `#F3F4F7` | orange | `#FF9837` |
62
+ | base7 | `#FAFDFB` | peach | `#FF9982` |
63
+
64
+ ## Components
65
+
66
+ ### Button
67
+
68
+ ```svelte
69
+ <Button variant="primary|secondary|ghost|outline|danger|success" size="xs|sm|md|lg|xl">
70
+ Click me
71
+ </Button>
72
+ <Button href="/about">Link Button</Button>
73
+ <Button loading>Loading...</Button>
74
+ ```
75
+
76
+ ### Input
77
+
78
+ ```svelte
79
+ <Input bind:value={text} placeholder="Enter text" />
80
+ <Input type="password" disableBrowserFeatures />
81
+ <Input error={!isValid} />
82
+ ```
83
+
84
+ ### Select
85
+
86
+ ```svelte
87
+ <Select
88
+ options={[{ value: '1', label: 'Option 1' }]}
89
+ bind:value={selected}
90
+ placeholder="Choose..."
91
+ />
92
+ ```
93
+
94
+ ### Badge
95
+
96
+ ```svelte
97
+ <Badge variant="default|primary|secondary|success|warning|error|info">
98
+ Status
99
+ </Badge>
100
+ ```
101
+
102
+ ### Checkbox & Switch
103
+
104
+ ```svelte
105
+ <Checkbox bind:checked={agreed}>I agree</Checkbox>
106
+ <Switch bind:checked={enabled}>Enable notifications</Switch>
107
+ ```
108
+
109
+ ### Toast
110
+
111
+ ```svelte
112
+ <!-- Root layout -->
113
+ <script>
114
+ import { Toast, createToastContext } from '@miozu/jera';
115
+ createToastContext();
116
+ </script>
117
+ <Toast />
118
+
119
+ <!-- Any component -->
120
+ <script>
121
+ import { getToastContext } from '@miozu/jera';
122
+ const toast = getToastContext();
123
+ toast.success('Saved!');
124
+ </script>
125
+ ```
126
+
127
+ ## Utilities
128
+
129
+ ### cn() — Class concatenation
130
+
131
+ ```javascript
132
+ import { cn } from '@miozu/jera';
133
+
134
+ cn('base', condition && 'conditional', ['array', 'classes']);
135
+ // => "base conditional array classes"
136
+ ```
137
+
138
+ ### cv() — Class variants
139
+
140
+ ```javascript
141
+ import { cv } from '@miozu/jera';
142
+
143
+ const button = cv({
144
+ base: 'inline-flex items-center',
145
+ variants: {
146
+ variant: { primary: 'bg-primary', secondary: 'bg-surface' },
147
+ size: { sm: 'h-8', md: 'h-10' }
148
+ },
149
+ defaults: { variant: 'primary', size: 'md' }
150
+ });
151
+
152
+ button({ variant: 'secondary' }); // => "inline-flex items-center bg-surface h-10"
153
+ ```
154
+
155
+ ## Actions
156
+
157
+ ```svelte
158
+ <script>
159
+ import { clickOutside, focusTrap, escapeKey, portal } from '@miozu/jera/actions';
160
+ </script>
161
+
162
+ <div use:clickOutside={() => close()}>
163
+ <dialog use:focusTrap={{ enabled: isOpen }}>
164
+ <div use:escapeKey={() => close()}>
165
+ Content
166
+ </div>
167
+ </dialog>
168
+ </div>
169
+
170
+ <div use:portal={'body'}>Renders at body level</div>
171
+ ```
172
+
173
+ ## Theming
174
+
175
+ Dark theme is default. Switch themes with `data-theme` attribute:
176
+
177
+ ```html
178
+ <html data-theme="dark"> <!-- Dark (default) -->
179
+ <html data-theme="light"> <!-- Light -->
180
+ ```
181
+
182
+ Or use ThemeState:
183
+
184
+ ```javascript
185
+ import { createThemeContext } from '@miozu/jera';
186
+
187
+ const theme = createThemeContext();
188
+ theme.init(); // Reads from localStorage/system preference
189
+ theme.toggle(); // Switch between light/dark
190
+ ```
191
+
192
+ ## AI-First Design
193
+
194
+ This library includes AI-optimized documentation:
195
+
196
+ - `llms.txt` — Structured index for LLM consumption
197
+ - `CLAUDE.md` — Detailed context for AI assistants
198
+ - JSDoc comments throughout the codebase
199
+
200
+ ## Browser Support
201
+
202
+ - Chrome 88+
203
+ - Firefox 78+
204
+ - Safari 14+
205
+ - Edge 88+
206
+
207
+ Requires Svelte 5.0+
208
+
209
+ ## License
210
+
211
+ MIT © [Nicholas Glazer](https://miozu.com)
package/llms.txt ADDED
@@ -0,0 +1,64 @@
1
+ # @miozu/jera
2
+
3
+ > A minimal, reactive component library for Svelte 5. Provides design tokens (Miozu Base16 color system), utility functions (cn, cv), Svelte actions, and accessible components. Designed for AI-assisted development with clear, predictable APIs.
4
+
5
+ ## Quick Start
6
+ - [Installation](#installation): `pnpm add @miozu/jera`
7
+ - [Basic Usage](#usage): Import components and tokens
8
+
9
+ ## Design Tokens
10
+ - [Colors](/src/tokens/colors.css): Miozu Base16 palette with dark/light themes
11
+ - [Spacing](/src/tokens/spacing.css): 4px-based spacing scale
12
+ - [Typography](/src/tokens/typography.css): Font scales and weights
13
+ - [Effects](/src/tokens/effects.css): Shadows, radius, transitions, z-index
14
+
15
+ ## Utilities
16
+ - [cn()](/src/utils/cn.svelte.js): Class name concatenation with falsy filtering
17
+ - [cv()](/src/utils/cn.svelte.js): Class variants for type-safe variant composition
18
+ - [ThemeState](/src/utils/reactive.svelte.js): SSR-safe theme management
19
+
20
+ ## Components
21
+ - [Button](/src/components/primitives/Button.svelte): Polymorphic button with 6 variants, 5 sizes
22
+ - [Input](/src/components/forms/Input.svelte): Text input with validation support
23
+ - [Select](/src/components/forms/Select.svelte): Accessible dropdown with keyboard navigation
24
+ - [Badge](/src/components/primitives/Badge.svelte): Status tags with semantic variants
25
+ - [Checkbox](/src/components/forms/Checkbox.svelte): Checkbox input
26
+ - [Switch](/src/components/forms/Switch.svelte): Toggle switch
27
+ - [Toast](/src/components/feedback/Toast.svelte): Notification system
28
+
29
+ ## Actions
30
+ - [clickOutside](/src/actions/index.js): Detect clicks outside element
31
+ - [focusTrap](/src/actions/index.js): Trap focus within element
32
+ - [portal](/src/actions/index.js): Render element in different DOM location
33
+ - [escapeKey](/src/actions/index.js): Handle escape key press
34
+
35
+ ## API Patterns
36
+
37
+ ### Component Props Pattern
38
+ All components accept these common props:
39
+ - `class`: Additional CSS classes (always merged)
40
+ - `disabled`: Boolean to disable interaction
41
+ - Event handlers: `onclick`, `onchange`, etc.
42
+
43
+ ### Class Variants Pattern
44
+ ```javascript
45
+ import { cv } from '@miozu/jera';
46
+
47
+ const button = cv({
48
+ base: 'inline-flex items-center',
49
+ variants: {
50
+ variant: { primary: 'bg-primary', secondary: 'bg-surface' },
51
+ size: { sm: 'h-8 px-3', md: 'h-10 px-4' }
52
+ },
53
+ defaults: { variant: 'primary', size: 'md' }
54
+ });
55
+
56
+ // Usage: button({ variant: 'secondary', size: 'sm' })
57
+ ```
58
+
59
+ ### Theme Usage Pattern
60
+ ```javascript
61
+ import { ThemeState, createThemeContext } from '@miozu/jera';
62
+ const theme = createThemeContext(); // In root layout
63
+ theme.toggle(); // Switch between light/dark
64
+ ```