@ryanhelsing/ry-ui 1.0.2 → 1.0.4

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 (59) hide show
  1. package/AGENT.md +460 -0
  2. package/AGENTS.md +57 -0
  3. package/README.md +45 -1
  4. package/dist/components/ry-button-group.d.ts +32 -0
  5. package/dist/components/ry-button-group.d.ts.map +1 -0
  6. package/dist/components/ry-carousel.d.ts +21 -0
  7. package/dist/components/ry-carousel.d.ts.map +1 -0
  8. package/dist/components/ry-feature.d.ts +21 -0
  9. package/dist/components/ry-feature.d.ts.map +1 -0
  10. package/dist/components/ry-field.d.ts +7 -1
  11. package/dist/components/ry-field.d.ts.map +1 -1
  12. package/dist/components/ry-hero.d.ts +16 -0
  13. package/dist/components/ry-hero.d.ts.map +1 -0
  14. package/dist/components/ry-number-select.d.ts.map +1 -1
  15. package/dist/components/ry-pricing.d.ts +21 -0
  16. package/dist/components/ry-pricing.d.ts.map +1 -0
  17. package/dist/components/ry-select.d.ts +8 -1
  18. package/dist/components/ry-select.d.ts.map +1 -1
  19. package/dist/components/ry-split.d.ts +28 -0
  20. package/dist/components/ry-split.d.ts.map +1 -0
  21. package/dist/components/ry-stat.d.ts +17 -0
  22. package/dist/components/ry-stat.d.ts.map +1 -0
  23. package/dist/components/ry-tag-input.d.ts +18 -0
  24. package/dist/components/ry-tag-input.d.ts.map +1 -0
  25. package/dist/components/ry-tag.d.ts +19 -0
  26. package/dist/components/ry-tag.d.ts.map +1 -0
  27. package/dist/core/ry-transform.d.ts.map +1 -1
  28. package/dist/css/ry-structure.css +739 -149
  29. package/dist/css/ry-theme.css +581 -180
  30. package/dist/css/ry-tokens.css +120 -24
  31. package/dist/css/ry-ui.css +4965 -1065
  32. package/dist/ry-ui.d.ts +9 -0
  33. package/dist/ry-ui.d.ts.map +1 -1
  34. package/dist/ry-ui.js +1309 -778
  35. package/dist/ry-ui.js.map +1 -1
  36. package/dist/themes/dark.css +7 -90
  37. package/dist/themes/light.css +6 -35
  38. package/dist/themes/ocean.css +22 -26
  39. package/docs/components/accordion.md +31 -0
  40. package/docs/components/button-group.md +36 -0
  41. package/docs/components/button.md +65 -0
  42. package/docs/components/color.md +84 -0
  43. package/docs/components/display.md +69 -0
  44. package/docs/components/drawer.md +36 -0
  45. package/docs/components/dropdown.md +33 -0
  46. package/docs/components/forms.md +90 -0
  47. package/docs/components/knob.md +42 -0
  48. package/docs/components/layout.md +217 -0
  49. package/docs/components/modal.md +38 -0
  50. package/docs/components/number-select.md +42 -0
  51. package/docs/components/slider.md +48 -0
  52. package/docs/components/tabs.md +30 -0
  53. package/docs/components/theme-toggle.md +36 -0
  54. package/docs/components/toast.md +27 -0
  55. package/docs/components/tooltip.md +14 -0
  56. package/docs/components/tree.md +46 -0
  57. package/docs/theming.md +182 -0
  58. package/package.json +8 -4
  59. package/USING_CDN.md +0 -591
@@ -0,0 +1,42 @@
1
+ # Knob
2
+
3
+ ## `<ry-knob>`
4
+
5
+ Rotary dial control. Great for audio/settings UIs.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `min` | number | Minimum (default: 0) |
10
+ | `max` | number | Maximum (default: 100) |
11
+ | `step` | number | Step (default: 0 = smooth) |
12
+ | `value` | number | Current value |
13
+ | `label` | string | Label below knob |
14
+ | `labels` | string | Comma-separated labels for discrete steps |
15
+ | `description` | string | Tooltip on hover |
16
+ | `color` | primary \| secondary \| success \| warning \| danger | Track color |
17
+ | `size` | sm \| lg | Size |
18
+ | `disabled` | boolean | Disable |
19
+
20
+ Events: `ry:input` (during drag), `ry:change` (on release)
21
+
22
+ ```html
23
+ <ry-knob min="0" max="100" value="50" label="Volume"></ry-knob>
24
+ <ry-knob min="0" max="3" step="1" value="1" labels="Off,Low,Med,High" label="Mode"></ry-knob>
25
+ <ry-knob value="60" color="warning" label="Warning"></ry-knob>
26
+ <ry-knob size="sm" value="25" label="Small"></ry-knob>
27
+ ```
28
+
29
+ JS:
30
+ ```js
31
+ const knob = document.querySelector('ry-knob');
32
+
33
+ knob.addEventListener('ry:input', (e) => {
34
+ updateVolume(e.detail.value); // fires during drag
35
+ });
36
+ knob.addEventListener('ry:change', (e) => {
37
+ saveSettings({ volume: e.detail.value }); // fires on release
38
+ });
39
+
40
+ knob.value; // 50
41
+ knob.value = 75;
42
+ ```
@@ -0,0 +1,217 @@
1
+ # Layout Components
2
+
3
+ CSS-only layout primitives. No JavaScript needed.
4
+
5
+ ## `<ry-page>`
6
+
7
+ Top-level page shell. Contains header, main, footer.
8
+
9
+ ```html
10
+ <ry-page>
11
+ <ry-header sticky>...</ry-header>
12
+ <ry-main>...</ry-main>
13
+ <ry-footer>...</ry-footer>
14
+ </ry-page>
15
+ ```
16
+
17
+ ## `<ry-header>`
18
+
19
+ | Attribute | Values | Description |
20
+ |-----------|--------|-------------|
21
+ | `sticky` | boolean | Sticks to top of viewport |
22
+
23
+ Horizontal flex with space-between. Two direct children = left and right.
24
+
25
+ ```html
26
+ <ry-header sticky>
27
+ <ry-cluster><strong>App</strong></ry-cluster>
28
+ <ry-cluster><ry-theme-toggle themes="light,dark"></ry-theme-toggle></ry-cluster>
29
+ </ry-header>
30
+ ```
31
+
32
+ ## `<ry-grid>`
33
+
34
+ | Attribute | Values | Description |
35
+ |-----------|--------|-------------|
36
+ | `cols` | 1–6 | Number of columns |
37
+
38
+ ```html
39
+ <ry-grid cols="3">
40
+ <ry-card>One</ry-card>
41
+ <ry-card>Two</ry-card>
42
+ <ry-card>Three</ry-card>
43
+ </ry-grid>
44
+ ```
45
+
46
+ ## `<ry-stack>`
47
+
48
+ Vertical flex layout.
49
+
50
+ | Attribute | Values | Description |
51
+ |-----------|--------|-------------|
52
+ | `gap` | sm \| md \| lg | Vertical spacing |
53
+
54
+ ```html
55
+ <ry-stack gap="sm">
56
+ <p>Item 1</p>
57
+ <p>Item 2</p>
58
+ </ry-stack>
59
+ ```
60
+
61
+ ## `<ry-cluster>`
62
+
63
+ Horizontal flex, wraps.
64
+
65
+ | Attribute | Values | Description |
66
+ |-----------|--------|-------------|
67
+ | `gap` | sm \| md \| lg | Horizontal spacing |
68
+
69
+ ```html
70
+ <ry-cluster>
71
+ <ry-badge>A</ry-badge>
72
+ <ry-badge>B</ry-badge>
73
+ </ry-cluster>
74
+ ```
75
+
76
+ ## `<ry-card>`
77
+
78
+ Content container with padding and border. Use `<ry-actions>` inside for button groups.
79
+
80
+ ```html
81
+ <ry-card>
82
+ <h3>Title</h3>
83
+ <p>Content.</p>
84
+ <ry-actions>
85
+ <ry-button>Save</ry-button>
86
+ <ry-button variant="ghost">Cancel</ry-button>
87
+ </ry-actions>
88
+ </ry-card>
89
+ ```
90
+
91
+ ## `<ry-section>`
92
+
93
+ Content section block. Adds bottom margin between sections, removed on last child.
94
+
95
+ ```html
96
+ <ry-main>
97
+ <ry-section><h2>Section 1</h2><p>Content.</p></ry-section>
98
+ <ry-section><h2>Section 2</h2><p>Content.</p></ry-section>
99
+ </ry-main>
100
+ ```
101
+
102
+ ## `<ry-aside>`
103
+
104
+ Sidebar / secondary content block.
105
+
106
+ ```html
107
+ <ry-split>
108
+ <ry-main>Primary content</ry-main>
109
+ <ry-aside>Sidebar content</ry-aside>
110
+ </ry-split>
111
+ ```
112
+
113
+ ## `<ry-split>`
114
+
115
+ Two-pane layout: content (flexible) + sidebar (fixed). Stacks vertically on mobile (<768px).
116
+
117
+ | Attribute | Values | Description |
118
+ |-----------|--------|-------------|
119
+ | `resizable` | boolean | Enables drag handle between panes |
120
+ | `persist` | string | localStorage key — saves/restores width as `ry-split:{key}` |
121
+
122
+ CSS custom properties:
123
+
124
+ | Property | Default | Description |
125
+ |----------|---------|-------------|
126
+ | `--ry-split-width` | `300px` | Sidebar width |
127
+ | `--ry-split-min-width` | `100px` | Minimum width during resize |
128
+ | `--ry-split-max-width` | `80%` | Maximum width during resize |
129
+
130
+ Events: `ry:resize` — `e.detail.width`
131
+
132
+ ```html
133
+ <!-- Basic -->
134
+ <ry-split>
135
+ <div>Main content (flex: 1)</div>
136
+ <div>Sidebar (300px)</div>
137
+ </ry-split>
138
+
139
+ <!-- Resizable with persistence -->
140
+ <ry-split resizable persist="sidebar" style="--ry-split-width: 400px">
141
+ <main>Content</main>
142
+ <aside>Resizable sidebar</aside>
143
+ </ry-split>
144
+ ```
145
+
146
+ Resize interaction:
147
+ - **Drag** handle between panes (mouse + touch)
148
+ - **Arrow keys** ±10px, **Shift+Arrow** ±50px
149
+ - **Home/End** jump to min/max
150
+ - **Double-click** handle to reset to default
151
+
152
+ ## `<ry-center>`
153
+
154
+ Centers content both horizontally and vertically.
155
+
156
+ ```html
157
+ <ry-center>
158
+ <h1>Centered title</h1>
159
+ <p>Centered paragraph</p>
160
+ </ry-center>
161
+ ```
162
+
163
+ ## `<ry-nav>`
164
+
165
+ Horizontal navigation links. Use `aria-current="page"` to highlight the active link.
166
+
167
+ ```html
168
+ <ry-nav>
169
+ <a href="/" aria-current="page">Home</a>
170
+ <a href="/about">About</a>
171
+ <a href="/contact">Contact</a>
172
+ </ry-nav>
173
+ ```
174
+
175
+ ## `<ry-logo>`
176
+
177
+ Inline logo element. Bold, large text. Typically used inside `<ry-header>`.
178
+
179
+ ```html
180
+ <ry-header>
181
+ <ry-logo>My App</ry-logo>
182
+ <ry-nav>...</ry-nav>
183
+ </ry-header>
184
+ ```
185
+
186
+ ## `<ry-actions>`
187
+
188
+ Horizontal button group. Use inside cards, modals, or any container.
189
+
190
+ ```html
191
+ <ry-actions>
192
+ <ry-button>Primary</ry-button>
193
+ <ry-button variant="ghost">Cancel</ry-button>
194
+ </ry-actions>
195
+ ```
196
+
197
+ ## `<ry-divider>`
198
+
199
+ Horizontal or vertical separator line.
200
+
201
+ | Attribute | Values | Description |
202
+ |-----------|--------|-------------|
203
+ | `vertical` | boolean | Vertical orientation (for use inside flex rows) |
204
+
205
+ ```html
206
+ <ry-stack>
207
+ <p>Above</p>
208
+ <ry-divider></ry-divider>
209
+ <p>Below</p>
210
+ </ry-stack>
211
+
212
+ <ry-cluster>
213
+ <span>Left</span>
214
+ <ry-divider vertical></ry-divider>
215
+ <span>Right</span>
216
+ </ry-cluster>
217
+ ```
@@ -0,0 +1,38 @@
1
+ # Modal
2
+
3
+ ## `<ry-modal>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `id` | string | Identifier (match button's `modal` attr) |
8
+ | `title` | string | Header title |
9
+
10
+ Put `close` attribute on any button inside to dismiss. Uses focus trapping.
11
+
12
+ Events: `ry:open`, `ry:close`
13
+ API: `.open()`, `.close()`, `.state`
14
+
15
+ ```html
16
+ <ry-button modal="demo">Open</ry-button>
17
+
18
+ <ry-modal id="demo" title="Confirm">
19
+ <p>Are you sure?</p>
20
+ <ry-actions slot="footer">
21
+ <ry-button variant="ghost" close>Cancel</ry-button>
22
+ <ry-button>OK</ry-button>
23
+ </ry-actions>
24
+ </ry-modal>
25
+ ```
26
+
27
+ JS:
28
+ ```js
29
+ const modal = document.querySelector('ry-modal');
30
+
31
+ modal.addEventListener('ry:open', () => console.log('opened'));
32
+ modal.addEventListener('ry:close', () => console.log('closed'));
33
+
34
+ // Programmatic
35
+ modal.open();
36
+ modal.close();
37
+ modal.state; // "open" or "closed"
38
+ ```
@@ -0,0 +1,42 @@
1
+ # Number Select
2
+
3
+ ## `<ry-number-select>`
4
+
5
+ Numeric stepper with increment/decrement buttons and optional drag-to-adjust.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `min` | number | Minimum (default: 0) |
10
+ | `max` | number | Maximum (default: 100) |
11
+ | `step` | number | Step (default: 1) |
12
+ | `value` | number | Current value |
13
+ | `arrows` | both \| start \| end \| stacked \| stacked-end \| stacked-start \| none | Button placement |
14
+ | `icons` | plus-minus \| chevron \| arrow | Icon style |
15
+ | `drag` | x \| y \| none | Drag direction |
16
+ | `prefix` | string | Before value ("$") |
17
+ | `suffix` | string | After value ("°", "%") |
18
+ | `editable` | boolean | Allow typing directly |
19
+ | `wrap` | boolean | Wrap around min/max |
20
+ | `size` | xs \| sm \| lg | Size |
21
+ | `disabled` | boolean | Disable |
22
+
23
+ Events: `ry:input` (during drag), `ry:change` (on commit)
24
+
25
+ ```html
26
+ <ry-number-select min="0" max="100" value="50"></ry-number-select>
27
+ <ry-number-select min="0" max="360" value="90" suffix="°" arrows="stacked" icons="chevron"></ry-number-select>
28
+ <ry-number-select min="0" max="1000" value="50" prefix="$" editable></ry-number-select>
29
+ <ry-number-select min="0" max="7" value="3" wrap></ry-number-select>
30
+ ```
31
+
32
+ JS:
33
+ ```js
34
+ const ns = document.querySelector('ry-number-select');
35
+
36
+ ns.addEventListener('ry:input', (e) => console.log(e.detail.value));
37
+ ns.addEventListener('ry:change', (e) => console.log(e.detail.value));
38
+
39
+ ns.value; // 50
40
+ ns.value = 75;
41
+ ns.step = 5;
42
+ ```
@@ -0,0 +1,48 @@
1
+ # Slider
2
+
3
+ ## `<ry-slider>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `min` | number | Minimum (default: 0) |
8
+ | `max` | number | Maximum (default: 100) |
9
+ | `step` | number | Step (default: 1, 0 = smooth) |
10
+ | `value` | number | Current value (single mode) |
11
+ | `start` / `end` | number | Range values (with `range`) |
12
+ | `range` | boolean | Dual-handle mode |
13
+ | `labeled` | boolean | Show min/max labels |
14
+ | `ticked` | boolean | Show tick marks |
15
+ | `tooltip` | boolean | Show value on hover |
16
+ | `vertical` | boolean | Vertical orientation |
17
+ | `reversed` | boolean | Reverse direction |
18
+ | `color` | primary \| secondary \| success \| warning \| danger \| info | Track color |
19
+ | `size` | sm \| lg | Size |
20
+ | `disabled` | boolean | Disable |
21
+
22
+ Events: `ry:input` (during drag), `ry:change` (on release)
23
+
24
+ ```html
25
+ <ry-slider min="0" max="100" value="50"></ry-slider>
26
+ <ry-slider min="0" max="100" start="25" end="75" range labeled></ry-slider>
27
+ <ry-slider min="0" max="10" step="1" value="5" ticked labeled tooltip></ry-slider>
28
+ <ry-slider min="0" max="100" value="60" color="success"></ry-slider>
29
+ ```
30
+
31
+ JS:
32
+ ```js
33
+ const slider = document.querySelector('ry-slider');
34
+
35
+ slider.addEventListener('ry:input', (e) => {
36
+ console.log(e.detail.value); // fires during drag
37
+ });
38
+ slider.addEventListener('ry:change', (e) => {
39
+ saveValue(e.detail.value); // fires on release
40
+ });
41
+
42
+ slider.value; // 50
43
+ slider.value = 75;
44
+
45
+ // Range slider
46
+ rangeSlider.start; // 25
47
+ rangeSlider.end; // 75
48
+ ```
@@ -0,0 +1,30 @@
1
+ # Tabs
2
+
3
+ ## `<ry-tabs>`
4
+
5
+ | Attribute (on tab) | Values | Description |
6
+ |---------------------|--------|-------------|
7
+ | `title` | string | Tab label |
8
+ | `active` | boolean | Initially selected |
9
+
10
+ Events: `ry:change` — `e.detail.index`, `e.detail.title`
11
+
12
+ ```html
13
+ <ry-tabs>
14
+ <ry-tab title="Overview" active><p>Overview content.</p></ry-tab>
15
+ <ry-tab title="Settings"><p>Settings content.</p></ry-tab>
16
+ </ry-tabs>
17
+ ```
18
+
19
+ JS:
20
+ ```js
21
+ const tabs = document.querySelector('ry-tabs');
22
+
23
+ tabs.addEventListener('ry:change', (e) => {
24
+ console.log(e.detail.index); // 0, 1, 2...
25
+ console.log(e.detail.title); // "Overview"
26
+ });
27
+
28
+ // Switch programmatically
29
+ tabs.activeIndex = 1;
30
+ ```
@@ -0,0 +1,36 @@
1
+ # Theme Toggle
2
+
3
+ ## `<ry-theme-toggle>`
4
+
5
+ Cycles through themes on click. Sets `data-ry-theme` on `<html>`.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `themes` | string | Comma-separated theme names (default: "light,dark") |
10
+
11
+ Events: `ry:theme-change` — `e.detail.theme`
12
+ API: `.theme` (get/set), `.toggle()`
13
+
14
+ ```html
15
+ <ry-theme-toggle themes="light,dark"></ry-theme-toggle>
16
+ <ry-theme-toggle themes="light,dark,ocean"></ry-theme-toggle>
17
+ ```
18
+
19
+ JS:
20
+ ```js
21
+ const toggle = document.querySelector('ry-theme-toggle');
22
+
23
+ toggle.addEventListener('ry:theme-change', (e) => {
24
+ console.log(e.detail.theme); // "dark"
25
+ });
26
+
27
+ // Programmatic
28
+ toggle.theme; // "light"
29
+ toggle.theme = 'dark';
30
+ toggle.toggle(); // cycles to next
31
+ ```
32
+
33
+ Or skip the component and set the theme directly:
34
+ ```js
35
+ document.documentElement.dataset.ryTheme = 'dark';
36
+ ```
@@ -0,0 +1,27 @@
1
+ # Toast
2
+
3
+ ## `RyToast` (programmatic API)
4
+
5
+ No HTML element needed. Call globally after ry-ui loads.
6
+
7
+ ```js
8
+ RyToast.success('Saved!');
9
+ RyToast.error('Something went wrong');
10
+ RyToast.warning('Please review');
11
+ RyToast.info('New update available');
12
+
13
+ // With options
14
+ RyToast.success('Done!', { duration: 5000 }); // default: 3000ms
15
+ ```
16
+
17
+ Common pattern:
18
+ ```js
19
+ async function saveData() {
20
+ try {
21
+ await api.save(data);
22
+ RyToast.success('Saved!');
23
+ } catch (err) {
24
+ RyToast.error(err.message);
25
+ }
26
+ }
27
+ ```
@@ -0,0 +1,14 @@
1
+ # Tooltip
2
+
3
+ ## `<ry-tooltip>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `content` | string | Tooltip text |
8
+ | `position` | top \| bottom \| left \| right | Position |
9
+
10
+ ```html
11
+ <ry-tooltip content="Save changes" position="top">
12
+ <ry-button>Save</ry-button>
13
+ </ry-tooltip>
14
+ ```
@@ -0,0 +1,46 @@
1
+ # Tree
2
+
3
+ ## `<ry-tree>`
4
+
5
+ File-tree / nested list with expand/collapse and optional drag-and-drop.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `sortable` | boolean | Enable drag-and-drop (on tree) |
10
+ | `no-animate` | boolean | Disable animation |
11
+ | `label` | string | Item label (on tree-item) |
12
+ | `open` | boolean | Expanded folder (on tree-item with children) |
13
+ | `selected` | boolean | Selected item (on leaf tree-item) |
14
+
15
+ Events: `ry:select` (file click), `ry:toggle` (folder expand/collapse), `ry:move` (drag-drop)
16
+ API: `.toJSON()`, `.value`, `RyTree.from(json)`
17
+
18
+ ```html
19
+ <ry-tree sortable>
20
+ <ry-tree-item label="src" open>
21
+ <ry-tree-item label="app">
22
+ <ry-tree-item label="page.tsx"></ry-tree-item>
23
+ </ry-tree-item>
24
+ <ry-tree-item label="utils.ts"></ry-tree-item>
25
+ </ry-tree-item>
26
+ </ry-tree>
27
+ ```
28
+
29
+ JS:
30
+ ```js
31
+ const tree = document.querySelector('ry-tree');
32
+
33
+ tree.addEventListener('ry:select', (e) => {
34
+ console.log(e.detail.label); // "page.tsx"
35
+ });
36
+ tree.addEventListener('ry:toggle', (e) => {
37
+ console.log(e.detail.label, e.detail.open);
38
+ });
39
+ tree.addEventListener('ry:move', (e) => {
40
+ console.log(`Moved "${e.detail.item}" ${e.detail.position} "${e.detail.target}"`);
41
+ });
42
+
43
+ // Serialize/deserialize
44
+ tree.toJSON(); // [{ label: "src", open: true, children: [...] }]
45
+ const copy = RyTree.from(tree.toJSON());
46
+ ```