vunor 0.0.30 → 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 (167) hide show
  1. package/README.md +514 -17
  2. package/dist/AppLayout.d.mts +42 -0
  3. package/dist/AppLayout.mjs +0 -0
  4. package/dist/AppToasts.d.mts +10 -0
  5. package/dist/AppToasts.mjs +112 -0
  6. package/dist/Button.d.mts +38 -0
  7. package/dist/Button.mjs +116 -0
  8. package/dist/ButtonBase.d.mts +29 -0
  9. package/dist/ButtonBase.mjs +89 -0
  10. package/dist/Calendar.d.mts +14 -0
  11. package/dist/Calendar.mjs +212 -0
  12. package/dist/Card.d.mts +23 -0
  13. package/dist/Card.mjs +68 -0
  14. package/dist/CardHeader.d.mts +18 -0
  15. package/dist/CardHeader.mjs +51 -0
  16. package/dist/CardInner.d.mts +13 -0
  17. package/dist/CardInner.mjs +22 -0
  18. package/dist/Checkbox.d.mts +32 -0
  19. package/dist/Checkbox.mjs +109 -0
  20. package/dist/Combobox.d.mts +168 -0
  21. package/dist/Combobox.mjs +755 -0
  22. package/dist/DatePicker.d.mts +81 -0
  23. package/dist/DatePicker.mjs +283 -0
  24. package/dist/DatePickerBase.d.mts +97 -0
  25. package/dist/DatePickerBase.mjs +365 -0
  26. package/dist/DatePickerInner.d.mts +7 -0
  27. package/dist/DatePickerInner.mjs +44 -0
  28. package/dist/DatePickerPopup.d.mts +8 -0
  29. package/dist/DatePickerPopup.mjs +116 -0
  30. package/dist/DelayedSwitch.d.mts +23 -0
  31. package/dist/DelayedSwitch.mjs +43 -0
  32. package/dist/DevTools.d.mts +14 -0
  33. package/dist/DevTools.mjs +612 -0
  34. package/dist/Dialog.d.mts +59 -0
  35. package/dist/Dialog.mjs +264 -0
  36. package/dist/Icon.d.mts +6 -0
  37. package/dist/Icon.mjs +22 -0
  38. package/dist/InnerLoading.d.mts +16 -0
  39. package/dist/InnerLoading.mjs +24 -0
  40. package/dist/Input.d.mts +166 -0
  41. package/dist/Input.mjs +242 -0
  42. package/dist/InputBase.d.mts +129 -0
  43. package/dist/InputBase.mjs +228 -0
  44. package/dist/Label.d.mts +13 -0
  45. package/dist/Label.mjs +20 -0
  46. package/dist/LoadingIndicator.d.mts +8 -0
  47. package/dist/LoadingIndicator.mjs +38 -0
  48. package/dist/Menu.d.mts +33 -0
  49. package/dist/Menu.mjs +136 -0
  50. package/dist/MenuItem.d.mts +9 -0
  51. package/dist/MenuItem.mjs +47 -0
  52. package/dist/OverflowContainer.d.mts +30 -0
  53. package/dist/OverflowContainer.mjs +105 -0
  54. package/dist/Pagination.d.mts +22 -0
  55. package/dist/Pagination.mjs +131 -0
  56. package/dist/Popover.d.mts +40 -0
  57. package/dist/Popover.mjs +189 -0
  58. package/dist/ProgressBar.d.mts +10 -0
  59. package/dist/ProgressBar.mjs +63 -0
  60. package/dist/RadioGroup.d.mts +40 -0
  61. package/dist/RadioGroup.mjs +139 -0
  62. package/dist/Select.d.mts +115 -0
  63. package/dist/Select.mjs +305 -0
  64. package/dist/SelectBase.d.mts +66 -0
  65. package/dist/SelectBase.mjs +263 -0
  66. package/dist/Slider.d.mts +37 -0
  67. package/dist/Slider.mjs +167 -0
  68. package/dist/Tabs.d.mts +41 -0
  69. package/dist/Tabs.mjs +113 -0
  70. package/dist/nuxt.d.mts +6 -0
  71. package/dist/nuxt.mjs +24 -63
  72. package/dist/theme.d.mts +334 -0
  73. package/dist/theme.mjs +2265 -1460
  74. package/dist/utils-Z0nPSAzb.js +42 -0
  75. package/dist/utils.d.mts +25 -0
  76. package/dist/utils.mjs +50 -20
  77. package/dist/vite.d.mts +6 -0
  78. package/dist/vite.mjs +10 -12
  79. package/dist/vunor.d.mts +125 -0
  80. package/dist/vunor.mjs +167 -152
  81. package/package.json +184 -68
  82. package/scripts/setup-skills.js +69 -0
  83. package/skills/vunor/SKILL.md +115 -0
  84. package/skills/vunor/components.md +320 -0
  85. package/skills/vunor/core.md +173 -0
  86. package/skills/vunor/forms.md +348 -0
  87. package/skills/vunor/palette.md +223 -0
  88. package/skills/vunor/rules.md +263 -0
  89. package/skills/vunor/shortcuts.md +239 -0
  90. package/skills/vunor/typography.md +204 -0
  91. package/dist/nuxt.d.ts +0 -6
  92. package/dist/theme.d.ts +0 -336
  93. package/dist/utils.d.ts +0 -25
  94. package/dist/vite.d.ts +0 -5
  95. package/dist/vunor.d.ts +0 -121
  96. package/src/components/AppLayout/AppLayout.vue +0 -130
  97. package/src/components/AppToasts/AppToasts.vue +0 -76
  98. package/src/components/AppToasts/app-toasts.ts +0 -43
  99. package/src/components/AppToasts/shortcuts.ts +0 -26
  100. package/src/components/Button/Button.vue +0 -50
  101. package/src/components/Button/ButtonBase.vue +0 -47
  102. package/src/components/Button/index.ts +0 -1
  103. package/src/components/Button/shortcuts.ts +0 -29
  104. package/src/components/Calendar/Calendar.vue +0 -70
  105. package/src/components/Calendar/shortcuts.ts +0 -38
  106. package/src/components/Card/Card.vue +0 -48
  107. package/src/components/Card/CardHeader.vue +0 -27
  108. package/src/components/Card/CardInner.vue +0 -8
  109. package/src/components/Card/index.ts +0 -3
  110. package/src/components/Card/pi.ts +0 -47
  111. package/src/components/Card/shortcuts.ts +0 -21
  112. package/src/components/Checkbox/Checkbox.vue +0 -62
  113. package/src/components/Checkbox/index.ts +0 -1
  114. package/src/components/Checkbox/shortcuts.ts +0 -27
  115. package/src/components/Combobox/Combobox.vue +0 -552
  116. package/src/components/Combobox/index.ts +0 -2
  117. package/src/components/Combobox/shortcuts.ts +0 -12
  118. package/src/components/Combobox/types.ts +0 -33
  119. package/src/components/DatePicker/DatePicker.vue +0 -31
  120. package/src/components/DatePicker/DatePickerBase.vue +0 -139
  121. package/src/components/DatePicker/DatePickerInner.vue +0 -27
  122. package/src/components/DatePicker/DatePickerPopup.vue +0 -84
  123. package/src/components/DevTools/DevTools.vue +0 -374
  124. package/src/components/Dialog/DelayedSwitch.vue +0 -51
  125. package/src/components/Dialog/Dialog.vue +0 -199
  126. package/src/components/Dialog/shortcuts.ts +0 -17
  127. package/src/components/Icon/Icon.vue +0 -9
  128. package/src/components/Icon/index.ts +0 -1
  129. package/src/components/Input/Input.vue +0 -118
  130. package/src/components/Input/InputBase.vue +0 -149
  131. package/src/components/Input/index.ts +0 -3
  132. package/src/components/Input/pi.ts +0 -18
  133. package/src/components/Input/utils.ts +0 -160
  134. package/src/components/Label/Label.vue +0 -5
  135. package/src/components/Label/index.ts +0 -1
  136. package/src/components/Loading/InnerLoading.vue +0 -14
  137. package/src/components/Loading/LoadingIndicator.vue +0 -23
  138. package/src/components/Loading/index.ts +0 -1
  139. package/src/components/Loading/shortcuts.ts +0 -11
  140. package/src/components/Menu/Menu.vue +0 -112
  141. package/src/components/Menu/MenuItem.vue +0 -21
  142. package/src/components/Menu/index.ts +0 -2
  143. package/src/components/Menu/shortcuts.ts +0 -6
  144. package/src/components/OverflowContainer/OverflowContainer.vue +0 -123
  145. package/src/components/OverflowContainer/index.ts +0 -1
  146. package/src/components/Pagination/Pagination.vue +0 -84
  147. package/src/components/Popover/Popover.vue +0 -61
  148. package/src/components/Popover/index.ts +0 -1
  149. package/src/components/ProgressBar/ProgressBar.vue +0 -22
  150. package/src/components/ProgressBar/shortcuts.ts +0 -25
  151. package/src/components/RadioGroup/RadioGroup.vue +0 -84
  152. package/src/components/RadioGroup/index.ts +0 -1
  153. package/src/components/RadioGroup/shortcuts.ts +0 -34
  154. package/src/components/Select/Select.vue +0 -102
  155. package/src/components/Select/SelectBase.vue +0 -167
  156. package/src/components/Select/index.ts +0 -3
  157. package/src/components/Select/shortcuts.ts +0 -30
  158. package/src/components/Select/types.ts +0 -30
  159. package/src/components/Slider/Slider.vue +0 -75
  160. package/src/components/Slider/index.ts +0 -1
  161. package/src/components/Slider/shortcuts.ts +0 -23
  162. package/src/components/Tabs/Tabs.vue +0 -42
  163. package/src/components/Tabs/shortcuts.ts +0 -7
  164. package/src/components/shortcuts.ts +0 -34
  165. package/src/components/utils/index.ts +0 -2
  166. package/src/components/utils/merge-class.ts +0 -31
  167. package/src/components/utils/provide-inject.ts +0 -39
package/README.md CHANGED
@@ -1,33 +1,530 @@
1
- # ui
1
+ # Vunor
2
2
 
3
- This template should help get you started developing with Vue 3 in Vite.
3
+ A **UnoCSS theme engine** that turns a handful of design decisions into a complete, perceptually consistent design system -- plus an optional set of 30+ Vue 3 components that use it.
4
4
 
5
- ## Recommended IDE Setup
5
+ The core value is the theme: a golden-ratio-based type and spacing scale, an Oklab-graded color palette where every hue looks equally bright at the same step, and a deeply-mergeable shortcut object system that lets you customize any visual detail without rewriting CSS. The Vue components are a bonus -- you can use the theme engine on its own with any markup.
6
6
 
7
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
7
+ ## Design Philosophy
8
8
 
9
- ## Type Support for `.vue` Imports in TS
9
+ Most design systems hard-code dozens of magic numbers for font sizes, spacing, colors, and border radii. Vunor derives **everything from a few mathematical constants**:
10
10
 
11
- TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
11
+ - **Golden ratio (1.618)** drives the typography scale, spacing tokens, and default border radius
12
+ - **Oklab color model** ensures perceptual uniformity -- `primary-500` and `error-500` look equally bright to the human eye, regardless of hue
13
+ - **Object-driven shortcuts** make every visual style surgically overridable through deep merging, not string replacement
12
14
 
13
- ## Customize configuration
15
+ The result: change one seed color or one scale factor, and the entire system recalculates consistently.
14
16
 
15
- See [Vite Configuration Reference](https://vitejs.dev/config/).
17
+ ---
16
18
 
17
- ## Project Setup
19
+ ## Perceptual Color Palette
18
20
 
19
- ```sh
20
- pnpm install
21
+ Vunor generates its full color system using [`@prostojs/palitra`](https://github.com/prostojs/palitra), a palette generator built on the **Oklab perceptual color model**.
22
+
23
+ ### Why Oklab?
24
+
25
+ Traditional RGB/HSL-based palette generators produce steps that _look_ uneven: yellow-500 appears much brighter than blue-500 at the same lightness value, because RGB lightness doesn't match human perception. Oklab solves this -- it grades colors by how people actually see them. When palitra generates `primary-500` and `secondary-500`, they sit at the same perceptual luminance regardless of their hue. This means:
26
+
27
+ - Swapping your primary color from blue to green doesn't break visual hierarchy
28
+ - Numbered steps (50..900) have visually equal spacing between them
29
+ - Dark/light mode palettes stay balanced without manual correction
30
+
31
+ ### How It Works
32
+
33
+ You provide up to 7 semantic seed colors. Palitra takes each one and generates:
34
+
35
+ 1. **Main palette** (10 steps: 50, 100..900) -- luminance-graded from light to dark with perceptually uniform steps, optional saturation and hue-shift (vivid) adjustments at the extremes
36
+ 2. **Layer palette** (5 steps: 0..4) -- desaturated variants for backgrounds that subtly tint without overwhelming content
37
+
38
+ All values are emitted as CSS custom properties, ready for use in any CSS-based system.
39
+
40
+ ### Semantic Colors
41
+
42
+ | Name | Default | Purpose |
43
+ |------|---------|---------|
44
+ | `primary` | `#004eaf` | Main brand color |
45
+ | `secondary` | `#edd812` | Accent / highlight |
46
+ | `good` | `#7bc76a` | Success / positive |
47
+ | `warn` | `#ef9421` | Warning |
48
+ | `error` | `#bf5a5f` | Error / negative |
49
+ | `grey` | `#858892` | Neutral greys |
50
+ | `neutral` | `#5da0c5` | Alternative neutral |
51
+
52
+ ### Per-Color Fine-Tuning
53
+
54
+ Each color can be a simple hex string or an object with saturation/vivid controls:
55
+
56
+ ```ts
57
+ palette: {
58
+ colors: {
59
+ primary: '#6B4EFF', // simple swap
60
+ error: {
61
+ color: '#DC2626',
62
+ vivid: { dark: 0.3, light: 0.3 }, // boost hue rotation at palette edges
63
+ saturate: { dark: -0.1, light: -0.1 }, // desaturate slightly
64
+ },
65
+ },
66
+ }
67
+ ```
68
+
69
+ ### Advanced Palette Controls
70
+
71
+ Fine-tune the global palette generation curves:
72
+
73
+ ```ts
74
+ palette: {
75
+ lightest: 0.97, // max luminance for the lightest step (0-1)
76
+ darkest: 0.24, // min luminance for the darkest step (0-1)
77
+ layersDepth: 0.08, // brightness step between layer-0 and layer-4
78
+
79
+ mainPalette: {
80
+ luminance: { dark: 0.26, middle: 0.62, light: 0.97 },
81
+ saturate: { dark: -0.25, light: -0.25 },
82
+ vivid: { dark: 0.1, light: 0.2 }, // hue rotation at edges
83
+ },
84
+ layerPalette: {
85
+ desaturate: 0.2, // pre-desaturate before generating layers
86
+ luminance: { dark: 0.24, light: 0.32 },
87
+ },
88
+ }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Golden-Ratio Typography & Spacing
94
+
95
+ All dimensions in Vunor derive from the golden ratio (`k = 1.618`).
96
+
97
+ ### Typography Scale
98
+
99
+ Font sizes, line heights, and letter spacing are computed from powers of `k`:
100
+
101
+ | Name | Size | Weight | Bold | Line Height |
102
+ |------|------|--------|------|-------------|
103
+ | `h1` | k^3.5 | 400 | 700 | k^0.5 |
104
+ | `h2` | k^2.5 | 400 | 700 | k^0.5 |
105
+ | `h3` | k^2 | 400 | 700 | k^0.5 |
106
+ | `h4` | k^1 | 400 | 600 | k^0.5 |
107
+ | `h5` | k^0.5 | 400 | 600 | k^0.5 |
108
+ | `h6` | k^0.25 | 600 | 700 | k^0.5 |
109
+ | `body` | 1 | 400 | 600 | k^0.75 |
110
+ | `body-s` | k^-0.5 | 400 | 600 | k^1 |
111
+ | `label` | k^-0.25 | 500 | 700 | k^0.5 |
112
+ | `caption` | k^-0.5 | 400 | 600 | k^0.5 |
113
+
114
+ Applied as UnoCSS utilities: `text-h1`, `text-body`, `text-label`, etc. Each sets `--font-size`, `--font-bold`, `--font-corrected` (actual rendered glyph height), line-height, letter-spacing, and top/bottom trim correction CSS vars.
115
+
116
+ Every entry is individually overridable:
117
+
118
+ ```ts
119
+ typography: {
120
+ h1: { size: 4, weight: 300, boldWeight: 700 },
121
+ body: { height: 1.75 }, // taller line-height
122
+ label: { weight: 600 },
123
+ }
124
+ ```
125
+
126
+ ### Spacing Scale
127
+
128
+ Spacing tokens follow the same golden-ratio progression:
129
+
130
+ | Token | Scale | ~Value |
131
+ |-------|-------|--------|
132
+ | `$xxs` | 1/k^3 | 0.24em |
133
+ | `$xs` | 1/k^2 | 0.38em |
134
+ | `$s` | 1/k | 0.62em |
135
+ | `$m` | 1 | 1em |
136
+ | `$l` | k | 1.62em |
137
+ | `$xl` | k^2 | 2.62em |
138
+ | `$xxl` | k^3 | 4.24em |
139
+
140
+ Used as `p-$m`, `m-$l`, `gap-$s`, etc. Text-aware margin utilities (`text-mt-$m`, `text-mb-$s`) compensate for line-height to maintain optically correct spacing.
141
+
142
+ ### Other Derived Values
143
+
144
+ - **Border radius**: defaults to `0.618em` (1/golden-ratio), configurable via `baseRadius`
145
+ - **Touch targets** (`fingertip-xs` through `fingertip-xl`): sized using `sqrt(k)` progressions
146
+ - **Card spacing**: `card-{typography}` sets `--card-spacing` proportional to the heading's corrected size; `card-dense` switches to 0.6x
147
+
148
+ ---
149
+
150
+ ## Object-Driven Shortcuts
151
+
152
+ This is Vunor's approach to component styling. Instead of flat UnoCSS shortcut strings, Vunor uses **structured nested objects** where keys are variant prefixes and values are the classes to apply. This makes styles readable, deeply mergeable, and surgically overridable.
153
+
154
+ ### How It Works
155
+
156
+ `defineShortcuts()` creates shortcut objects:
157
+
158
+ ```ts
159
+ import { defineShortcuts } from 'vunor/theme'
160
+
161
+ const shortcuts = defineShortcuts({
162
+ // 'btn' is the shortcut name (used as a CSS class)
163
+ 'btn': {
164
+ '': 'h-fingertip flex items-center', // base classes (no prefix)
165
+ 'hover:': 'bg-current/05', // → "hover:bg-current/05"
166
+ 'dark:': 'text-white', // → "dark:text-white"
167
+ '[&.btn-round]:': 'rounded-full', // → "[&.btn-round]:rounded-full"
168
+ },
169
+ })
170
+ ```
171
+
172
+ Each key is a **variant prefix** that gets prepended to every class in the value. At build time, `toUnoShortcut()` flattens the object into a single UnoCSS shortcut string:
173
+
174
+ ```
175
+ h-fingertip flex items-center hover:bg-current/05 dark:text-white [&.btn-round]:rounded-full
176
+ ```
177
+
178
+ Wherever you use `class="btn"`, UnoCSS applies all those classes. The nesting is purely for readability and mergeability.
179
+
180
+ ### Compound Variants
181
+
182
+ Nesting can go deeper for compound variants:
183
+
184
+ ```ts
185
+ defineShortcuts({
186
+ 'c8-filled': {
187
+ '': 'current-bg-scope-color-500 text-white rounded-base',
188
+ 'hover:': 'current-bg-scope-color-400',
189
+ 'dark:': {
190
+ '': 'text-white/90',
191
+ 'hover:': 'current-bg-scope-color-600 border-solid',
192
+ // produces: "dark:text-white/90 dark:hover:current-bg-scope-color-600 dark:hover:border-solid"
193
+ },
194
+ },
195
+ })
196
+ ```
197
+
198
+ ### Why Objects Instead of Strings?
199
+
200
+ **Because they merge.** When two shortcut objects define the same key, `mergeVunorShortcuts()` deep-merges them with later entries winning. This is the key to Vunor's customization model: you can surgically override a single variant of a built-in style without rewriting the whole shortcut.
201
+
202
+ For example, to make all filled buttons pill-shaped while keeping every other variant (hover, active, dark mode, disabled) intact:
203
+
204
+ ```ts
205
+ import { vunorShortcuts, defineShortcuts } from 'vunor/theme'
206
+
207
+ const myOverrides = defineShortcuts({
208
+ 'c8-filled': {
209
+ '': 'rounded-full', // only overrides base classes
210
+ },
211
+ 'i8-flat': {
212
+ '': 'border-b-2', // only overrides base classes
213
+ },
214
+ })
215
+
216
+ export default defineConfig({
217
+ presets: [presetVunor()],
218
+ shortcuts: [vunorShortcuts(myOverrides)],
219
+ })
220
+ ```
221
+
222
+ Your `'c8-filled'.'':` replaces only the base classes of `c8-filled`, while all its `hover:`, `dark:`, `active:` variants remain intact from the defaults. Everything flows through a single merge pipeline, producing consistent CSS passed to UnoCSS.
223
+
224
+ `vunorShortcuts()` returns the merged default shortcuts for all built-in styles (c8, i8, card, dialog, etc.). Pass your overrides as the first argument -- they take priority.
225
+
226
+ ---
227
+
228
+ ## Semantic CSS Classes
229
+
230
+ All visual styling uses UnoCSS class strings -- no CSS files or scoped styles. Component appearance is defined through shortcuts, rules, and CSS custom properties.
231
+
232
+ ### Layers (`layer-0` .. `layer-4`)
233
+
234
+ Layers provide full background + text + icon styling that automatically adapts to light/dark mode:
235
+
236
+ ```html
237
+ <div class="layer-0 scope-primary">
238
+ <!-- Light: lightest bg, dark text. Dark mode: darkest bg, light text. -->
239
+ <div class="layer-1">
240
+ <!-- One step deeper -->
241
+ </div>
242
+ </div>
243
+ ```
244
+
245
+ - `layer-0` is the outermost (lightest in light mode, darkest in dark)
246
+ - Each subsequent layer steps progressively toward the opposite extreme
247
+ - Apply `scope-{color}` to set which palette the layers use
248
+
249
+ ### Surfaces
250
+
251
+ Surfaces apply specific palette stops as background + text + icon:
252
+
253
+ ```html
254
+ <div class="scope-primary surface-100">Lightly tinted</div>
255
+ <div class="scope-error surface-500">Bold error banner</div>
21
256
  ```
22
257
 
23
- ### Compile and Hot-Reload for Development
258
+ `surface-0` through `surface-4` map to the layer scale. `surface-50` through `surface-900` map to the main 10-step palette. Custom surfaces can be defined in `palette.surfaces`.
24
259
 
25
- ```sh
26
- pnpm dev
260
+ ### Current-Color System
261
+
262
+ Fine-grained color control via CSS custom properties:
263
+
264
+ ```html
265
+ <div class="current-bg-primary-500 bg-current text-current">
266
+ Colored via CSS vars
267
+ </div>
268
+ ```
269
+
270
+ - `scope-{color}` sets `--scope-color-*` vars for a palette
271
+ - `current-bg-{color}-{step}` sets `--current-bg`
272
+ - `bg-current` / `text-current` / `icon-current` apply the current-scoped colors
273
+
274
+ ### Clickable Styles (`c8`)
275
+
276
+ Button and clickable element design variants:
277
+
278
+ | Class | Description |
279
+ |-------|-------------|
280
+ | `c8-filled` | Solid background, white text |
281
+ | `c8-flat` | Transparent background, colored text |
282
+ | `c8-outlined` | Border + colored text, transparent fill |
283
+ | `c8-light` | Light tinted background, colored text |
284
+
285
+ Each includes hover, active, focus, and disabled states. Apply on any element alongside `scope-{color}`:
286
+
287
+ ```html
288
+ <button class="scope-primary c8-filled">Save</button>
289
+ <button class="scope-error c8-flat">Cancel</button>
290
+ ```
291
+
292
+ ### Inputable Styles (`i8`)
293
+
294
+ Input field design variants:
295
+
296
+ | Class | Description |
297
+ |-------|-------------|
298
+ | `i8-flat` | Bottom border only (minimal) |
299
+ | `i8-filled` | Full border with background |
300
+ | `i8-round` | Pill-shaped (fully rounded) |
301
+
302
+ Common sub-shortcuts: `i8-input`, `i8-label` (floating label), `i8-hint`, `i8-prepend` / `i8-append`, `i8-before` / `i8-after`.
303
+
304
+ ---
305
+
306
+ ## Full Configuration Example
307
+
308
+ ```ts
309
+ import { defineConfig } from 'unocss'
310
+ import { presetVunor, vunorShortcuts } from 'vunor/theme'
311
+
312
+ export default defineConfig({
313
+ presets: [
314
+ presetVunor({
315
+ // -- Perceptual color palette --
316
+ palette: {
317
+ colors: {
318
+ primary: '#6B4EFF',
319
+ secondary: '#FF6B4E',
320
+ good: '#22C55E',
321
+ error: {
322
+ color: '#DC2626',
323
+ vivid: { dark: 0.3, light: 0.3 },
324
+ saturate: { dark: -0.1, light: -0.1 },
325
+ },
326
+ },
327
+ lightest: 0.97,
328
+ darkest: 0.24,
329
+ layersDepth: 0.08,
330
+ },
331
+
332
+ // -- Golden-ratio spacing --
333
+ spacingFactor: 1.618,
334
+
335
+ // -- Global border radius --
336
+ baseRadius: '0.5em', // default: 0.618em (1/golden-ratio)
337
+
338
+ // -- Typography overrides --
339
+ typography: {
340
+ h1: { size: 4, weight: 300, boldWeight: 700 },
341
+ body: { height: 1.75 },
342
+ label: { weight: 600 },
343
+ },
344
+
345
+ // -- Font rendering --
346
+ actualFontHeightFactor: 0.76,
347
+ actualFontHeightTopBottomRatio: 0.5,
348
+
349
+ // -- Touch targets --
350
+ fingertip: {
351
+ xs: '1.25em',
352
+ s: '2em',
353
+ m: '3em',
354
+ l: '3.5em',
355
+ xl: '4em',
356
+ },
357
+
358
+ // -- Card padding multipliers --
359
+ cardSpacingFactor: {
360
+ regular: 1,
361
+ dense: 0.6,
362
+ },
363
+
364
+ // -- Layer direction --
365
+ layers: {
366
+ reverseDark: false,
367
+ reverseLight: false,
368
+ },
369
+ }),
370
+ ],
371
+ shortcuts: [vunorShortcuts()],
372
+ })
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Quick Start
378
+
379
+ ### Vue 3 + Vite
380
+
381
+ ```bash
382
+ pnpm add vunor
27
383
  ```
28
384
 
29
- ### Type-Check, Compile and Minify for Production
385
+ **vite.config.ts**
30
386
 
31
- ```sh
32
- pnpm build
387
+ ```ts
388
+ import { defineConfig } from 'vite'
389
+ import vue from '@vitejs/plugin-vue'
390
+ import UnoCSS from 'unocss/vite'
391
+ import Components from 'unplugin-vue-components/vite'
392
+ import { VunorVueResolver } from 'vunor/vite'
393
+
394
+ export default defineConfig({
395
+ plugins: [
396
+ vue(),
397
+ UnoCSS(),
398
+ Components({
399
+ resolvers: [VunorVueResolver],
400
+ }),
401
+ ],
402
+ })
33
403
  ```
404
+
405
+ **uno.config.ts**
406
+
407
+ ```ts
408
+ import { defineConfig } from 'unocss'
409
+ import { presetVunor, vunorShortcuts } from 'vunor/theme'
410
+
411
+ export default defineConfig({
412
+ presets: [presetVunor()],
413
+ shortcuts: [vunorShortcuts()],
414
+ })
415
+ ```
416
+
417
+ **main.ts**
418
+
419
+ ```ts
420
+ import { createApp } from 'vue'
421
+ import '@unocss/reset/tailwind.css'
422
+ import 'virtual:uno.css'
423
+ import App from './App.vue'
424
+
425
+ createApp(App).mount('#app')
426
+ ```
427
+
428
+ No `safelist` is needed. The UnoCSS preset includes a built-in extractor that detects `<VuButton>`, `<VuInput>`, etc. in your templates and automatically includes the required component CSS classes.
429
+
430
+ ### Nuxt 3
431
+
432
+ ```ts
433
+ // nuxt.config.ts
434
+ export default defineNuxtConfig({
435
+ modules: ['vunor/nuxt'],
436
+ })
437
+ ```
438
+
439
+ The Nuxt module auto-registers all `Vu*` components.
440
+
441
+ ---
442
+
443
+ ## Vue Components (Optional)
444
+
445
+ Vunor ships 30+ accessible Vue 3 components built on Reka UI. All use the `Vu` prefix in templates. Auto-import via `VunorVueResolver` or the Nuxt module.
446
+
447
+ The components are consumers of the theme system described above -- they use `c8`, `i8`, layers, surfaces, and the typography scale. You can use the theme engine without any of these components, or use them as-is, or override their styles through the shortcut object system.
448
+
449
+ ### Layout
450
+
451
+ | Component | Description |
452
+ |-----------|-------------|
453
+ | `VuAppLayout` | App shell with header, sidebar, footer slots |
454
+ | `VuCard` | Card container with typography-driven spacing |
455
+ | `VuCardHeader` | Card header with title and actions |
456
+ | `VuCardInner` | Nested card section |
457
+ | `VuTabs` | Tabbed content panels |
458
+ | `VuDialog` | Modal dialog with overlay |
459
+ | `VuPopover` | Floating popover anchored to a trigger |
460
+
461
+ ### Form Inputs
462
+
463
+ | Component | Description |
464
+ |-----------|-------------|
465
+ | `VuInput` | Text / textarea input with floating label |
466
+ | `VuSelect` | Dropdown select |
467
+ | `VuCombobox` | Searchable dropdown with filtering |
468
+ | `VuCheckbox` | Checkbox with indeterminate state |
469
+ | `VuRadioGroup` | Radio button group |
470
+ | `VuSlider` | Range slider |
471
+ | `VuDatePicker` | Date picker with calendar popup |
472
+ | `VuLabel` | Form label |
473
+
474
+ ### Actions
475
+
476
+ | Component | Description |
477
+ |-----------|-------------|
478
+ | `VuButton` | Button with icon, loading, and link support |
479
+ | `VuMenu` | Navigation / command menu |
480
+ | `VuMenuItem` | Menu item |
481
+ | `VuPagination` | Page navigation |
482
+
483
+ ### Feedback
484
+
485
+ | Component | Description |
486
+ |-----------|-------------|
487
+ | `VuAppToasts` | Toast notification container |
488
+ | `VuProgressBar` | Progress bar |
489
+ | `VuLoadingIndicator` | Circular loading spinner |
490
+ | `VuInnerLoading` | Overlay loading within a container |
491
+
492
+ ### Utility
493
+
494
+ | Component | Description |
495
+ |-----------|-------------|
496
+ | `VuIcon` | Icon display (integrates with UnoCSS icons) |
497
+ | `VuOverflowContainer` | Handles content overflow |
498
+ | `VuCalendar` | Standalone calendar grid |
499
+
500
+ ## Package Exports
501
+
502
+ ```
503
+ vunor PI composables (provide/inject helpers)
504
+ vunor/theme UnoCSS preset, shortcuts, palette, component classes
505
+ vunor/utils mergeCssClasses, useProvideInject
506
+ vunor/vite VunorVueResolver for unplugin-vue-components
507
+ vunor/nuxt Nuxt 3 module
508
+ vunor/{Name} Individual Vue components (e.g. vunor/Button)
509
+ ```
510
+
511
+ ## AI Agent Skills
512
+
513
+ `vunor` ships an AI agent skill for Claude Code, Cursor, Windsurf, Codex and other compatible agents.
514
+ The skill teaches your agent the library's APIs, patterns, and best practices — so it can help you write correct code without hallucinating.
515
+
516
+ **Install the skill into your agent:**
517
+
518
+ ```bash
519
+ # Project-local (recommended — commits with your repo)
520
+ npx vunor setup-skills
521
+
522
+ # Global (available in all your projects)
523
+ npx vunor setup-skills --global
524
+ ```
525
+
526
+ Restart your agent after installing. The skill is version-locked to the package — re-run after upgrading.
527
+
528
+ ## License
529
+
530
+ MIT
@@ -0,0 +1,42 @@
1
+ type __VLS_Props = {
2
+ maxW?: string;
3
+ headerH?: string;
4
+ footerH?: string;
5
+ leftW?: string;
6
+ rightW?: string;
7
+ footer?: boolean;
8
+ header?: boolean;
9
+ left?: boolean;
10
+ right?: boolean;
11
+ headerClass?: string | Record<string, boolean>;
12
+ footerClass?: string | Record<string, boolean>;
13
+ leftClass?: string | Record<string, boolean>;
14
+ rightClass?: string | Record<string, boolean>;
15
+ mainClass?: string | Record<string, boolean>;
16
+ scrollTopOnChangeView?: boolean;
17
+ };
18
+ declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
19
+ type __VLS_Slots = {} & {
20
+ header?: (props: typeof __VLS_1) => any;
21
+ } & {
22
+ left?: (props: typeof __VLS_3) => any;
23
+ } & {
24
+ default?: (props: typeof __VLS_5) => any;
25
+ } & {
26
+ right?: (props: typeof __VLS_7) => any;
27
+ };
28
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
29
+ maxW: string;
30
+ headerH: string;
31
+ footerH: string;
32
+ leftW: string;
33
+ rightW: string;
34
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
35
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
36
+ declare const _default: typeof __VLS_export;
37
+ export default _default;
38
+ type __VLS_WithSlots<T, S> = T & {
39
+ new (): {
40
+ $slots: S;
41
+ };
42
+ };
Binary file
@@ -0,0 +1,10 @@
1
+ import type { ToastProviderProps } from 'reka-ui';
2
+ import type { TVueCssClass } from 'vunor/utils';
3
+ type __VLS_Props = ToastProviderProps & {
4
+ class?: TVueCssClass;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
7
+ swipeDirection: "left" | "right" | "down" | "up";
8
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;