blessing-ui 0.1.0 → 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 (200) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +139 -105
  3. package/dist/blessing-ui.css +97 -1
  4. package/dist/components/BlessAnnotator.css +1 -0
  5. package/dist/components/BlessAnnotator.js +6 -0
  6. package/dist/components/BlessAnnotator.vue.d.ts +71 -0
  7. package/dist/components/BlessAnnotator.vue_vue_type_script_setup_true_lang.js +264 -0
  8. package/dist/components/BlessAttachment.vue.d.ts +4 -1
  9. package/dist/components/BlessAttachment.vue_vue_type_script_setup_true_lang.js +3 -2
  10. package/dist/components/BlessCalendar.vue.d.ts +4 -0
  11. package/dist/components/BlessCalendar.vue_vue_type_script_setup_true_lang.js +65 -60
  12. package/dist/components/BlessCarousel.vue.d.ts +3 -0
  13. package/dist/components/BlessCarousel.vue_vue_type_script_setup_true_lang.js +10 -9
  14. package/dist/components/BlessCoachmark.css +1 -0
  15. package/dist/components/BlessCoachmark.js +6 -0
  16. package/dist/components/BlessCoachmark.vue.d.ts +40 -0
  17. package/dist/components/BlessCoachmark.vue_vue_type_script_setup_true_lang.js +74 -0
  18. package/dist/components/BlessCodeBlock.css +1 -0
  19. package/dist/components/BlessCodeBlock.js +6 -0
  20. package/dist/components/BlessCodeBlock.vue.d.ts +72 -0
  21. package/dist/components/BlessCodeBlock.vue_vue_type_script_setup_true_lang.js +140 -0
  22. package/dist/components/BlessCombobox.vue.d.ts +2 -0
  23. package/dist/components/BlessCombobox.vue_vue_type_script_setup_true_lang.js +3 -2
  24. package/dist/components/BlessCommand.css +1 -1
  25. package/dist/components/BlessCommand.vue.d.ts +26 -0
  26. package/dist/components/BlessCommand.vue_vue_type_script_setup_true_lang.js +137 -70
  27. package/dist/components/BlessConfetti.css +1 -0
  28. package/dist/components/BlessConfetti.js +6 -0
  29. package/dist/components/BlessConfetti.vue.d.ts +40 -0
  30. package/dist/components/BlessConfetti.vue_vue_type_script_setup_true_lang.js +77 -0
  31. package/dist/components/BlessCountUp.css +1 -0
  32. package/dist/components/BlessCountUp.js +6 -0
  33. package/dist/components/BlessCountUp.vue.d.ts +18 -0
  34. package/dist/components/BlessCountUp.vue_vue_type_script_setup_true_lang.js +49 -0
  35. package/dist/components/BlessCropper.css +1 -0
  36. package/dist/components/BlessCropper.js +6 -0
  37. package/dist/components/BlessCropper.vue.d.ts +70 -0
  38. package/dist/components/BlessCropper.vue_vue_type_script_setup_true_lang.js +220 -0
  39. package/dist/components/BlessDataTable.vue.d.ts +6 -0
  40. package/dist/components/BlessDataTable.vue_vue_type_script_setup_true_lang.js +56 -42
  41. package/dist/components/BlessDataView.vue.d.ts +7 -0
  42. package/dist/components/BlessDataView.vue_vue_type_script_setup_true_lang.js +38 -31
  43. package/dist/components/BlessDatePicker.vue.d.ts +3 -0
  44. package/dist/components/BlessDatePicker.vue_vue_type_script_setup_true_lang.js +46 -45
  45. package/dist/components/BlessDiff.css +1 -0
  46. package/dist/components/BlessDiff.js +6 -0
  47. package/dist/components/BlessDiff.vue.d.ts +22 -0
  48. package/dist/components/BlessDiff.vue_vue_type_script_setup_true_lang.js +148 -0
  49. package/dist/components/BlessDock.css +1 -0
  50. package/dist/components/BlessDock.js +6 -0
  51. package/dist/components/BlessDock.vue.d.ts +55 -0
  52. package/dist/components/BlessDock.vue_vue_type_script_setup_true_lang.js +100 -0
  53. package/dist/components/BlessEditor.vue.d.ts +2 -0
  54. package/dist/components/BlessEditor.vue_vue_type_script_setup_true_lang.js +23 -22
  55. package/dist/components/BlessFileInput.vue.d.ts +2 -0
  56. package/dist/components/BlessFileInput.vue_vue_type_script_setup_true_lang.js +3 -2
  57. package/dist/components/BlessFormula.css +1 -0
  58. package/dist/components/BlessFormula.js +6 -0
  59. package/dist/components/BlessFormula.vue.d.ts +53 -0
  60. package/dist/components/BlessFormula.vue_vue_type_script_setup_true_lang.js +111 -0
  61. package/dist/components/BlessGantt.css +1 -0
  62. package/dist/components/BlessGantt.js +6 -0
  63. package/dist/components/BlessGantt.vue.d.ts +81 -0
  64. package/dist/components/BlessGantt.vue_vue_type_script_setup_true_lang.js +276 -0
  65. package/dist/components/BlessGauge.css +1 -0
  66. package/dist/components/BlessGauge.js +6 -0
  67. package/dist/components/BlessGauge.vue.d.ts +36 -0
  68. package/dist/components/BlessGauge.vue_vue_type_script_setup_true_lang.js +100 -0
  69. package/dist/components/BlessHeatmapCalendar.css +1 -0
  70. package/dist/components/BlessHeatmapCalendar.js +6 -0
  71. package/dist/components/BlessHeatmapCalendar.vue.d.ts +38 -0
  72. package/dist/components/BlessHeatmapCalendar.vue_vue_type_script_setup_true_lang.js +146 -0
  73. package/dist/components/BlessHotspots.css +1 -0
  74. package/dist/components/BlessHotspots.js +6 -0
  75. package/dist/components/BlessHotspots.vue.d.ts +49 -0
  76. package/dist/components/BlessHotspots.vue_vue_type_script_setup_true_lang.js +127 -0
  77. package/dist/components/BlessInfiniteCanvas.css +1 -0
  78. package/dist/components/BlessInfiniteCanvas.js +6 -0
  79. package/dist/components/BlessInfiniteCanvas.vue.d.ts +91 -0
  80. package/dist/components/BlessInfiniteCanvas.vue_vue_type_script_setup_true_lang.js +232 -0
  81. package/dist/components/BlessInputNumber.vue.d.ts +5 -0
  82. package/dist/components/BlessInputNumber.vue_vue_type_script_setup_true_lang.js +39 -34
  83. package/dist/components/BlessKanban.css +1 -0
  84. package/dist/components/BlessKanban.js +6 -0
  85. package/dist/components/BlessKanban.vue.d.ts +67 -0
  86. package/dist/components/BlessKanban.vue_vue_type_script_setup_true_lang.js +195 -0
  87. package/dist/components/BlessLoadingBar.vue.d.ts +2 -0
  88. package/dist/components/BlessLoadingBar.vue_vue_type_script_setup_true_lang.js +8 -3
  89. package/dist/components/BlessLoupe.css +1 -0
  90. package/dist/components/BlessLoupe.js +6 -0
  91. package/dist/components/BlessLoupe.vue.d.ts +16 -0
  92. package/dist/components/BlessLoupe.vue_vue_type_script_setup_true_lang.js +93 -0
  93. package/dist/components/BlessMarquee.css +1 -0
  94. package/dist/components/BlessMarquee.js +6 -0
  95. package/dist/components/BlessMarquee.vue.d.ts +44 -0
  96. package/dist/components/BlessMarquee.vue_vue_type_script_setup_true_lang.js +69 -0
  97. package/dist/components/BlessMasonry.css +1 -0
  98. package/dist/components/BlessMasonry.js +6 -0
  99. package/dist/components/BlessMasonry.vue.d.ts +33 -0
  100. package/dist/components/BlessMasonry.vue_vue_type_script_setup_true_lang.js +79 -0
  101. package/dist/components/BlessMention.css +1 -0
  102. package/dist/components/BlessMention.js +6 -0
  103. package/dist/components/BlessMention.vue.d.ts +32 -0
  104. package/dist/components/BlessMention.vue_vue_type_script_setup_true_lang.js +116 -0
  105. package/dist/components/BlessNodeGraph.css +1 -0
  106. package/dist/components/BlessNodeGraph.js +6 -0
  107. package/dist/components/BlessNodeGraph.vue.d.ts +110 -0
  108. package/dist/components/BlessNodeGraph.vue_vue_type_script_setup_true_lang.js +321 -0
  109. package/dist/components/BlessOnboardingChecklist.css +1 -0
  110. package/dist/components/BlessOnboardingChecklist.js +6 -0
  111. package/dist/components/BlessOnboardingChecklist.vue.d.ts +72 -0
  112. package/dist/components/BlessOnboardingChecklist.vue_vue_type_script_setup_true_lang.js +157 -0
  113. package/dist/components/BlessOrderList.vue.d.ts +5 -0
  114. package/dist/components/BlessOrderList.vue_vue_type_script_setup_true_lang.js +62 -56
  115. package/dist/components/BlessPagination.vue.d.ts +2 -0
  116. package/dist/components/BlessPagination.vue_vue_type_script_setup_true_lang.js +2 -1
  117. package/dist/components/BlessPickList.vue.d.ts +5 -0
  118. package/dist/components/BlessPickList.vue_vue_type_script_setup_true_lang.js +55 -49
  119. package/dist/components/BlessRadialMenu.css +1 -0
  120. package/dist/components/BlessRadialMenu.js +6 -0
  121. package/dist/components/BlessRadialMenu.vue.d.ts +45 -0
  122. package/dist/components/BlessRadialMenu.vue_vue_type_script_setup_true_lang.js +146 -0
  123. package/dist/components/BlessRangeCalendar.css +1 -0
  124. package/dist/components/BlessRangeCalendar.js +6 -0
  125. package/dist/components/BlessRangeCalendar.vue.d.ts +51 -0
  126. package/dist/components/BlessRangeCalendar.vue_vue_type_script_setup_true_lang.js +217 -0
  127. package/dist/components/BlessScheduler.css +1 -0
  128. package/dist/components/BlessScheduler.js +6 -0
  129. package/dist/components/BlessScheduler.vue.d.ts +95 -0
  130. package/dist/components/BlessScheduler.vue_vue_type_script_setup_true_lang.js +347 -0
  131. package/dist/components/BlessShortcutRecorder.css +1 -0
  132. package/dist/components/BlessShortcutRecorder.js +6 -0
  133. package/dist/components/BlessShortcutRecorder.vue.d.ts +39 -0
  134. package/dist/components/BlessShortcutRecorder.vue_vue_type_script_setup_true_lang.js +126 -0
  135. package/dist/components/BlessSignaturePad.vue.d.ts +1 -1
  136. package/dist/components/BlessSliderCaptcha.css +1 -0
  137. package/dist/components/BlessSliderCaptcha.js +6 -0
  138. package/dist/components/BlessSliderCaptcha.vue.d.ts +38 -0
  139. package/dist/components/BlessSliderCaptcha.vue_vue_type_script_setup_true_lang.js +146 -0
  140. package/dist/components/BlessSortable.css +1 -0
  141. package/dist/components/BlessSortable.js +6 -0
  142. package/dist/components/BlessSortable.vue.d.ts +51 -0
  143. package/dist/components/BlessSortable.vue_vue_type_script_setup_true_lang.js +135 -0
  144. package/dist/components/BlessSparkline.css +1 -0
  145. package/dist/components/BlessSparkline.js +6 -0
  146. package/dist/components/BlessSparkline.vue.d.ts +28 -0
  147. package/dist/components/BlessSparkline.vue_vue_type_script_setup_true_lang.js +107 -0
  148. package/dist/components/BlessSplitView.css +1 -0
  149. package/dist/components/BlessSplitView.js +6 -0
  150. package/dist/components/BlessSplitView.vue.d.ts +61 -0
  151. package/dist/components/BlessSplitView.vue_vue_type_script_setup_true_lang.js +92 -0
  152. package/dist/components/BlessSteps.vue.d.ts +2 -0
  153. package/dist/components/BlessSteps.vue_vue_type_script_setup_true_lang.js +3 -2
  154. package/dist/components/BlessSwipeDeck.css +1 -0
  155. package/dist/components/BlessSwipeDeck.js +6 -0
  156. package/dist/components/BlessSwipeDeck.vue.d.ts +46 -0
  157. package/dist/components/BlessSwipeDeck.vue_vue_type_script_setup_true_lang.js +200 -0
  158. package/dist/components/BlessTimer.css +1 -0
  159. package/dist/components/BlessTimer.js +6 -0
  160. package/dist/components/BlessTimer.vue.d.ts +74 -0
  161. package/dist/components/BlessTimer.vue_vue_type_script_setup_true_lang.js +139 -0
  162. package/dist/components/BlessTour.vue.d.ts +1 -0
  163. package/dist/components/BlessTour.vue_vue_type_script_setup_true_lang.js +48 -42
  164. package/dist/components/BlessTreemap.css +1 -0
  165. package/dist/components/BlessTreemap.js +6 -0
  166. package/dist/components/BlessTreemap.vue.d.ts +46 -0
  167. package/dist/components/BlessTreemap.vue_vue_type_script_setup_true_lang.js +137 -0
  168. package/dist/components/BlessUploader.vue.d.ts +11 -0
  169. package/dist/components/BlessUploader.vue_vue_type_script_setup_true_lang.js +80 -69
  170. package/dist/composables/annotate.d.ts +35 -0
  171. package/dist/composables/annotate.js +33 -0
  172. package/dist/composables/canvasView.d.ts +21 -0
  173. package/dist/composables/canvasView.js +23 -0
  174. package/dist/composables/confetti.d.ts +32 -0
  175. package/dist/composables/confetti.js +23 -0
  176. package/dist/composables/cropBox.d.ts +22 -0
  177. package/dist/composables/cropBox.js +39 -0
  178. package/dist/composables/dayBlocks.d.ts +11 -0
  179. package/dist/composables/dayBlocks.js +26 -0
  180. package/dist/composables/diffLines.d.ts +10 -0
  181. package/dist/composables/diffLines.js +55 -0
  182. package/dist/composables/formula.d.ts +28 -0
  183. package/dist/composables/formula.js +161 -0
  184. package/dist/composables/graph.d.ts +19 -0
  185. package/dist/composables/graph.js +16 -0
  186. package/dist/composables/radial.d.ts +15 -0
  187. package/dist/composables/radial.js +22 -0
  188. package/dist/composables/schedule.d.ts +27 -0
  189. package/dist/composables/schedule.js +54 -0
  190. package/dist/composables/shortcut.d.ts +12 -0
  191. package/dist/composables/shortcut.js +35 -0
  192. package/dist/composables/treemap.d.ts +23 -0
  193. package/dist/composables/treemap.js +77 -0
  194. package/dist/composables/useAutoScroll.d.ts +15 -0
  195. package/dist/composables/useAutoScroll.js +32 -0
  196. package/dist/composables/useSortable.d.ts +58 -0
  197. package/dist/composables/useSortable.js +107 -0
  198. package/dist/index.d.ts +62 -1
  199. package/dist/index.js +93 -53
  200. package/package.json +22 -18
package/CHANGELOG.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 — 2026-10-10
4
+
5
+ 12 new components, 176 in all, and a round of hardening across the existing ones. Every new component has a docs page, tests, a keyboard path for what the pointer does, and passes axe in light and dark and the end-to-end flows in Chromium, Firefox and WebKit. No breaking changes.
6
+
7
+ **New components**
8
+
9
+ - `BlessSparkline`: tiny inline line, bar or win/loss chart, named with a summary for screen readers
10
+ - `BlessConfetti`: canvas burst fired with `fire()`; click-through, and silent under reduced motion
11
+ - `BlessInfiniteCanvas`: pan and zoom surface (drag, Ctrl+wheel, pinch, keys); children can `inject(blessCanvasKey)`
12
+ - `BlessNodeGraph`: draggable nodes and links on the canvas, keyboard linking (L, arrows, Enter), `acyclic`
13
+ - `BlessTreemap`: squarified part-to-whole with drill-down and arrow-key navigation
14
+ - `BlessCoachmark`: a "new" dot with a bubble, seen once (remembered by `id`)
15
+ - `BlessOnboardingChecklist`: first steps with real checkboxes, progress, collapse, dismiss and optional persistence
16
+ - `BlessDock`: magnifying icon strip; off for touch and reduced motion
17
+ - `BlessFormula`: typed calculation parsed without `eval`, live result, exact errors, "did you mean", variable chips; `evaluateFormula` is exported
18
+ - `BlessRangeCalendar`: paint many days by dragging, with keyboard painting
19
+ - `BlessAnnotator`: boxes and pins on an image, as fractions of it
20
+ - `BlessScheduler`: day or week grid; drag to create, move and resize, with overlap lanes
21
+
22
+ **Existing components**
23
+
24
+ - `BlessSortable` takes a `group`: lists with the same name trade items by drag or Alt+←/→ (Esc restores every list), with a new `transfer` event. A held grip near the window's top or bottom scrolls the page.
25
+ - `BlessKanban`: a held card near the board's edge scrolls it (`useAutoScroll` is exported).
26
+ - `BlessCommand`: `recent` puts items chosen before at the top while the search is empty (`v-model:history`, `recentLimit`, `persist`), and `scopes` lets a leading `@` or `#` narrow the search to one group, with a chip and a hint. Both are off unless asked for.
27
+ - **Fix:** `BlessTour` could not hydrate in a server-rendered app (its teleport to `body`); it now renders after mount.
28
+
29
+ **Wording**
30
+
31
+ - `labels` on Sortable, Kanban, Timer, SliderCaptcha, Cropper, ShortcutRecorder, CodeBlock, Gantt, Calendar, InputNumber, DataTable, DataView, OrderList, PickList, Marquee, Uploader and Editor (by tool key), so buttons, hints and screen-reader announcements can be written in another language.
32
+ - Single strings: `clearLabel` (DatePicker), `dotsLabel` (Carousel), `label` (LoadingBar), `errorText` (Attachment), `removeLabel` (Combobox, FileInput), `pageLabel` (Pagination), `goLabel` (Steps); DataView and SwipeDeck empty states take `labels.empty`.
33
+
34
+ ## 0.2.0 — 2026-10-03
35
+
36
+ 20 new components, 164 in all. Every one has a docs page, tests, a keyboard path for what the pointer does, and passes axe in light and dark and the end-to-end flows in Chromium, Firefox and WebKit.
37
+
38
+ **Direct manipulation**
39
+
40
+ - `BlessSortable` (and `useSortable`): drag a grip to reorder a list or grid; Space, arrows, Esc from the keyboard
41
+ - `BlessKanban`: columns of cards, drag or keys between columns, per-column limits
42
+ - `BlessCropper`: crop and rotate an image, export the cropped pixels with `toBlob`
43
+ - `BlessHotspots`: numbered pins on an image or diagram with popovers; editable
44
+ - `BlessSwipeDeck`: judge a stack of cards by swiping, keys or buttons, with undo
45
+ - `BlessSliderCaptcha`: slide the piece into the gap (a speed bump, not security)
46
+ - `BlessRadialMenu`: ring of actions from a right-click, a long touch or the menu key
47
+ - `BlessLoupe`: magnifier over an image by hover, touch-drag or arrow keys
48
+
49
+ **Time and numbers**
50
+
51
+ - `BlessCountUp`: a number that counts to its value, or rolls as an odometer
52
+ - `BlessTimer`: countdown, stopwatch and interval timer
53
+ - `BlessGauge`: zoned meter as a half circle or a bar
54
+ - `BlessGantt`: task bars on a day axis with progress, dependency arrows and a today line; drag bars to move or resize them
55
+ - `BlessHeatmapCalendar`: one square per day, a year of activity at a glance
56
+
57
+ **Text and input**
58
+
59
+ - `BlessMention`: `@` and `#` suggestions inside a textarea
60
+ - `BlessShortcutRecorder`: press a key combo to record it, with conflict detection (`shortcutFromEvent`, `matchShortcut` exported)
61
+ - `BlessDiff`: line diff, inline or side by side, with folding (`diffLines` exported)
62
+ - `BlessCodeBlock`: copy button, line marks, file tabs; bring your own highlighter
63
+ - `BlessMarquee`: seamless ticker that pauses on hover, focus and a button
64
+
65
+ **Layout**
66
+
67
+ - `BlessMasonry`: variable-height cards packed into columns, in reading order
68
+ - `BlessSplitView`: master / detail with a draggable divider, one pane at a time when narrow
69
+
70
+ No breaking changes to existing components.
71
+
3
72
  ## 0.1.0 — 2026-09-27
4
73
 
5
74
  First public release.
package/README.md CHANGED
@@ -4,11 +4,13 @@
4
4
 
5
5
  # Blessing UI
6
6
 
7
+ [![npm](https://img.shields.io/npm/v/blessing-ui)](https://www.npmjs.com/package/blessing-ui) [![ci](https://github.com/danceinthefake/blessing-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/danceinthefake/blessing-ui/actions/workflows/ci.yml)
8
+
7
9
  Vue 3 component library and design tokens. Grey-scale UI with one accent that appears only on what someone has chosen; square, upright plates that lean when you engage them; thin oversized watermark type; opacity-fade hovers. The rules come from a [design language](docs/design/index.md); the look was re-derived from one anime's official site, ideas only — the [story](docs/design/story.md) says which, what was kept, and what was not taken.
8
10
 
9
11
  Docs, with every component live: **[ui.blessing.id](https://ui.blessing.id)**
10
12
 
11
- - 144 components — from button to data table to chat — styled only through `--bless-*` custom properties, no Tailwind dependency
13
+ - 176 components — from button to data table to chat — styled only through `--bless-*` custom properties, no Tailwind dependency
12
14
  - Native platform first: `<dialog>`, Popover API, `<details>`, native form controls, `Intl` dates, scroll-snap — no positioning, date or table library
13
15
  - Accessible defaults: focus rings, ARIA tablist/dialog/tables, `prefers-reduced-motion`
14
16
  - ESM, tree-shakable, `vue` as the only required peer (`@tiptap/vue-3` optional, for `BlessEditor`). One component (`BlessButton`) costs ~1 KB gzip of JS and ~2.6 KB of CSS (tokens + its own styles); everything is ~64 KB + 27 KB. CSS is split per component and pulled in by the import, so you never pay for styles you don't use
@@ -84,7 +86,7 @@ import {
84
86
 
85
87
  ## Components
86
88
 
87
- 144 components across eight groups. Every one styles itself from `--bless-*` tokens and ships with a test and a docs page.
89
+ 176 components across eight groups. Every one styles itself from `--bless-*` tokens and ships with a test and a docs page.
88
90
 
89
91
  ### Primitives
90
92
 
@@ -123,104 +125,133 @@ import {
123
125
 
124
126
  ### Forms
125
127
 
126
- | Component | Purpose | Key props / slots |
127
- | ---------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
128
- | `BlessLabel` | `<label>` with required mark and hint | `for`, `required`, `hint` |
129
- | `BlessInput` | Text-like input | `v-model`, `type`, `size`, `invalid`, `description`, `error`; `#prefix` `#suffix` |
130
- | `BlessInputGroup` | Shared surface: addons + any control | `size`, `disabled`; `#prefix` `#suffix` (text or `BlessButton`), default = `BlessInput`/`BlessSelect` |
131
- | `BlessTextarea` | Auto-growing textarea | `v-model`, `rows`, `autogrow`, `maxlength`, `counter`, `error` |
132
- | `BlessCheckbox` | Native checkbox | `v-model` (bool or array), `value`, `indeterminate`, `description` |
133
- | `BlessRadioGroup` / `BlessRadio` | Native radios | group `v-model`, `label`, `orientation`; radio `value`, `description` |
134
- | `BlessSwitch` | `role=switch` toggle | `v-model`, `size`, `labelPosition` |
135
- | `BlessRating` | Star rating on native radios | `v-model`, `max`, `icon`, `size`, `readonly` |
136
- | `BlessFileInput` | File input + drop zone | `v-model` File[], `accept`, `multiple`, `hint`, `list`, `invalid` |
137
- | `BlessColorPicker` | `<input type=color>` + swatches | `v-model` hex, `swatches[]`, `showValue` |
138
- | `BlessPasswordMeter` | Strength `<meter>` from rules | `value`, `rules[{label,test}]`, `labels`, `showRules` |
139
- | `BlessListbox` | `role=listbox`, keyboard + typeahead | `v-model` (array when `multiple`), `options`, `rows`, `label`; `#default="{option, selected}"` |
140
- | `BlessKnob` | Rotary dial on `<input type=range>` | `v-model`, `min`, `max`, `step`, `size`, `sweep`, `format`, `label` |
141
- | `BlessSignaturePad` | Canvas signature | `v-model` data URL, `height`, `lineWidth`, `color`, `type`; emits `end`; exposes `clear()` `isEmpty()` |
142
- | `BlessEditor` | Rich text toolbar for Tiptap | `editor` (from `useEditor`), `tools[]`, `minHeight`; default slot = `<EditorContent>`; `#toolbar` `#footer`. Optional peer `@tiptap/vue-3` |
143
- | `BlessRange` | Two-thumb range | `v-model` [lo, hi], `min`, `max`, `step`, `gap`, `label`, `showValue`, `format` |
144
- | `BlessTimePicker` | `<input type=time>` + datalist | `v-model` "HH:MM", `step` (minutes), `min`, `max`, `hour12`, `seconds`, `size` |
145
- | `BlessUploader` | Upload queue | `url`, `field`, `headers`, `accept`, `multiple`, `auto`, `maxSize`; emits `upload(item, progress, done, fail)` `done` `error`; exposes `start()` `clear()` |
146
- | `BlessInputNumber` | Number with ± and Intl format | `v-model` number, `min`, `max`, `step`, `buttons`, `prefix`, `suffix`, `format`, `locale` |
147
- | `BlessPasswordInput` | Password + reveal + meter | `v-model`, `meter`; wraps `BlessInput` |
148
- | `BlessInputTags` | Free-text tags | `v-model` string[], `separators`, `max`, `duplicates` |
149
- | `BlessFloatLabel` | Floating / in-field label | `label`, `for`, `variant` over/in; wrap a control with `placeholder=" "` |
150
- | `BlessFieldset` | `<fieldset>` + legend | `legend`, `toggleable`, `v-model:collapsed`, `disabled` |
151
- | `BlessInplace` | Click to edit | `v-model:active`, `closable`; `#display` `#content="{close}"` |
152
- | `BlessCompare` | Before / after slider | `v-model` 0–100, `orientation`; `#before` `#after` |
153
- | `BlessCascadeSelect` | Nested options, one column per level | `v-model`, `options[{value,label,children}]`, `showPath`, `separator`, `size`; emits `select(option, path)` |
154
- | `BlessTreeSelect` | Tree in a popover | `v-model` id or id[], `nodes`, `multiple`, `leafOnly`, `size`; emits `select` |
155
- | `BlessInputMask` | Pattern-masked `BlessInput` | `v-model` masked, `mask` (`#` digit `A` letter `*` either), `placeholder`; emits `update:raw` |
156
- | `BlessOrderList` | Reorderable list | `v-model` items, `rowKey`, `buttons`; drag, ↑↓, Alt+arrows; emits `move`; `#default="{item,index}"` |
157
- | `BlessPickList` | Transfer between two listboxes | `v-model:source`, `v-model:target`, `sourceLabel`, `targetLabel`, `rows` |
158
- | `BlessSelect` | Styled native `<select>` (picker styled too on Chrome 135+) | `v-model`, `options` (groups ok), `placeholder`, `size`, `error` |
159
- | `BlessSlider` | Native range | `v-model`, `min`, `max`, `step`, `showValue`, `format` |
160
- | `BlessToggle` / `BlessToggleGroup` | Pressed buttons | toggle `v-model:pressed`, `value`; group `v-model`, `type` single/multiple |
161
- | `BlessCombobox` | Searchable select | `v-model`, `options`, `multiple`, `creatable` (emits `create`), `size` |
162
- | `BlessDatePicker` | Calendar in a popover | `v-model` ISO string or `[start,end]`, `range`, `min`, `max`, `locale`, `nativeOnTouch` |
163
- | `BlessCalendar` | Month grid | same as DatePicker plus `weekStart`, `disabledDates`, `month` |
164
- | `BlessInputOTP` | One-time code cells | `v-model`, `length`, `numeric`, `separators`, `masked`; emits `complete` |
165
- | `BlessForm` / `BlessField` | Constraint-API form + field wiring | form emits `submit(FormData)` / `invalid`; field `label`, `required`, `description`, `error`; `#default="{ id, error, describedby }"` |
128
+ | Component | Purpose | Key props / slots |
129
+ | ---------------------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
130
+ | `BlessLabel` | `<label>` with required mark and hint | `for`, `required`, `hint` |
131
+ | `BlessInput` | Text-like input | `v-model`, `type`, `size`, `invalid`, `description`, `error`; `#prefix` `#suffix` |
132
+ | `BlessInputGroup` | Shared surface: addons + any control | `size`, `disabled`; `#prefix` `#suffix` (text or `BlessButton`), default = `BlessInput`/`BlessSelect` |
133
+ | `BlessTextarea` | Auto-growing textarea | `v-model`, `rows`, `autogrow`, `maxlength`, `counter`, `error` |
134
+ | `BlessCheckbox` | Native checkbox | `v-model` (bool or array), `value`, `indeterminate`, `description` |
135
+ | `BlessRadioGroup` / `BlessRadio` | Native radios | group `v-model`, `label`, `orientation`; radio `value`, `description` |
136
+ | `BlessSwitch` | `role=switch` toggle | `v-model`, `size`, `labelPosition` |
137
+ | `BlessRating` | Star rating on native radios | `v-model`, `max`, `icon`, `size`, `readonly` |
138
+ | `BlessFileInput` | File input + drop zone | `v-model` File[], `accept`, `multiple`, `hint`, `list`, `invalid` |
139
+ | `BlessColorPicker` | `<input type=color>` + swatches | `v-model` hex, `swatches[]`, `showValue` |
140
+ | `BlessPasswordMeter` | Strength `<meter>` from rules | `value`, `rules[{label,test}]`, `labels`, `showRules` |
141
+ | `BlessListbox` | `role=listbox`, keyboard + typeahead | `v-model` (array when `multiple`), `options`, `rows`, `label`; `#default="{option, selected}"` |
142
+ | `BlessKnob` | Rotary dial on `<input type=range>` | `v-model`, `min`, `max`, `step`, `size`, `sweep`, `format`, `label` |
143
+ | `BlessSignaturePad` | Canvas signature | `v-model` data URL, `height`, `lineWidth`, `color`, `type`; emits `end`; exposes `clear()` `isEmpty()` |
144
+ | `BlessEditor` | Rich text toolbar for Tiptap | `editor` (from `useEditor`), `tools[]`, `minHeight`; default slot = `<EditorContent>`; `#toolbar` `#footer`. Optional peer `@tiptap/vue-3` |
145
+ | `BlessRange` | Two-thumb range | `v-model` [lo, hi], `min`, `max`, `step`, `gap`, `label`, `showValue`, `format` |
146
+ | `BlessTimePicker` | `<input type=time>` + datalist | `v-model` "HH:MM", `step` (minutes), `min`, `max`, `hour12`, `seconds`, `size` |
147
+ | `BlessUploader` | Upload queue | `url`, `field`, `headers`, `accept`, `multiple`, `auto`, `maxSize`; emits `upload(item, progress, done, fail)` `done` `error`; exposes `start()` `clear()` |
148
+ | `BlessInputNumber` | Number with ± and Intl format | `v-model` number, `min`, `max`, `step`, `buttons`, `prefix`, `suffix`, `format`, `locale` |
149
+ | `BlessPasswordInput` | Password + reveal + meter | `v-model`, `meter`; wraps `BlessInput` |
150
+ | `BlessInputTags` | Free-text tags | `v-model` string[], `separators`, `max`, `duplicates` |
151
+ | `BlessFloatLabel` | Floating / in-field label | `label`, `for`, `variant` over/in; wrap a control with `placeholder=" "` |
152
+ | `BlessFieldset` | `<fieldset>` + legend | `legend`, `toggleable`, `v-model:collapsed`, `disabled` |
153
+ | `BlessInplace` | Click to edit | `v-model:active`, `closable`; `#display` `#content="{close}"` |
154
+ | `BlessCompare` | Before / after slider | `v-model` 0–100, `orientation`; `#before` `#after` |
155
+ | `BlessCascadeSelect` | Nested options, one column per level | `v-model`, `options[{value,label,children}]`, `showPath`, `separator`, `size`; emits `select(option, path)` |
156
+ | `BlessTreeSelect` | Tree in a popover | `v-model` id or id[], `nodes`, `multiple`, `leafOnly`, `size`; emits `select` |
157
+ | `BlessInputMask` | Pattern-masked `BlessInput` | `v-model` masked, `mask` (`#` digit `A` letter `*` either), `placeholder`; emits `update:raw` |
158
+ | `BlessOrderList` | Reorderable list | `v-model` items, `rowKey`, `buttons`; drag, ↑↓, Alt+arrows; emits `move`; `#default="{item,index}"` |
159
+ | `BlessCountUp` | Number that counts up to its value, optionally as odometer reels | `value`, `duration`, `locale`, `options` (Intl), `appear`, `odometer` |
160
+ | `BlessTimer` | Countdown, stopwatch or interval timer with Start / Pause / Reset | `mode`, `duration`, `phases[{label,seconds}]`, `rounds`, `autostart`, `controls`, `v-model:running`; emits `finish` `phase`; exposes `start` `pause` `reset` `toggle` |
161
+ | `BlessGauge` | Read-only gauge with zones, as a half circle or a bar (role=meter) | `value`, `min`, `max`, `zones[{to,color,label}]`, `variant` arc/linear, `label`, `format` |
162
+ | `BlessGantt` | Schedule: task bars on a day axis with progress, dependencies and a today line; draggable when `editable` | `v-model:tasks` `[{id,label,start,end,progress,after}]`, `editable`, `dayWidth`, `rowHeight`, `from`, `to`, `locale`, `labelWidth`, `v-model:selected`; emits `select` `change` |
163
+ | `BlessShortcutRecorder` | Press-to-record key combo with conflict detection | `v-model` e.g. `Ctrl+K`, `taken` (list or `{combo: name}`), `allowBare`, `label`, `placeholder`; emits `conflict` |
164
+ | `BlessDiff` | Line diff of two texts, inline or side by side, with folding | `a`, `b`, `mode` inline/split, `context`, `lineNumbers`, `labelA`, `labelB`, `label` |
165
+ | `BlessCodeBlock` | Code listing with copy, line marks, line numbers and file tabs; you bring the highlighter | `code`, `lang`, `filename`, `files[{name,code,lang}]`, `v-model:active`, `lines` "2,4-6", `lineNumbers`, `copy`, `wrap`; emits `copy`; `#code="{code,lang,lines}"` |
166
+ | `BlessMarquee` | Seamless ticker; pauses on hover, focus and a button; still under reduced motion | `speed`, `reverse`, `pauseOnHover`, `controls`, `v-model:paused`, `label` |
167
+ | `BlessMasonry` | Variable-height cards packed into columns, in reading order | `items`, `rowKey`, `columns`, `minWidth`, `gap`, `label`; `#default="{item,index}"` |
168
+ | `BlessSplitView` | Master / detail: draggable divider when wide, one pane at a time when narrow | `v-model` master width %, `v-model:detail` (stacked), `breakpoint`, `min`, `max`, `storageKey`, `backLabel`; emits `back`; `#master="{open}"` `#detail` |
169
+ | `BlessRadialMenu` | Round menu around the pointer: right-click, long touch (slide and release) or the menu key | `items[{id,label,icon,disabled}]`, `v-model:open`, `radius`, `holdMs`, `disabled`, `label`; emits `select`; default slot is the target, `#item="{item,index}"` |
170
+ | `BlessLoupe` | Magnifier lens over an image: hover, touch-drag or arrow keys | `src`, `alt`, `zoomSrc`, `zoom`, `size` |
171
+ | `BlessSliderCaptcha` | Slide the piece into the gap (a human check, not security) | `v-model:verified`, `src`, `tolerance`, `label`; emits `verify({ms})` `fail`; exposes `reset()`; ←→ + Enter from the keyboard |
172
+ | `BlessSwipeDeck` | Stack of cards: swipe or press to accept / reject / skip | `v-model` remaining cards, `rowKey`, `label`, `controls`, `threshold`, `labels`; emits `decide(item, decision)` `undo(item)`; `#card` `#empty`; exposes `accept` `reject` `skip` `undo` |
173
+ | `BlessHotspots` | Numbered pins on an image or diagram, each with a popover | `v-model` spots `[{id,x,y,label}]` (percent), `v-model:active`, `src`, `alt`, `editable`, `placement`; emits `add` `remove`; `#spot="{spot,index}"`, default slot for a diagram |
174
+ | `BlessCropper` | Crop and rotate an image; exports the cropped pixels | `src`, `aspect`, `crossorigin`, `controls`, `label`; `v-model` rect `{x,y,width,height,rotation}`; `toBlob({type,quality,maxWidth})`; emits `ready` `error` |
175
+ | `BlessKanban` | Board: columns of cards, drag or keys between columns | `v-model` columns `[{id,title,items,limit}]`, `rowKey`, `label`; emits `move(item, from, to)`; `#card="{item,column,index}"` `#header="{column}"` |
176
+ | `BlessMention` | Textarea with `@` / `#` suggestions | `v-model`, `options` (list or `{trigger: list}`), `triggers`, `limit`, `label`; other props go to `BlessTextarea`; emits `select(option, trigger)` |
177
+ | `BlessHeatmapCalendar` | Activity grid, one square per day | `data` {iso: count}, `end`, `weeks`, `weekStart`, `levels`, `max`, `locale`, `unit`, `legend`; `v-model` picked day; arrows move by day / week |
178
+ | `BlessSortable` | Reorder a list or grid by drag handle or keyboard | `v-model` items, `rowKey`, `label`, `columns`; drag, Space + arrows, Esc cancels; emits `move`; `#default="{item,index}"` |
179
+ | `BlessPickList` | Transfer between two listboxes | `v-model:source`, `v-model:target`, `sourceLabel`, `targetLabel`, `rows` |
180
+ | `BlessSelect` | Styled native `<select>` (picker styled too on Chrome 135+) | `v-model`, `options` (groups ok), `placeholder`, `size`, `error` |
181
+ | `BlessSlider` | Native range | `v-model`, `min`, `max`, `step`, `showValue`, `format` |
182
+ | `BlessToggle` / `BlessToggleGroup` | Pressed buttons | toggle `v-model:pressed`, `value`; group `v-model`, `type` single/multiple |
183
+ | `BlessCombobox` | Searchable select | `v-model`, `options`, `multiple`, `creatable` (emits `create`), `size` |
184
+ | `BlessDatePicker` | Calendar in a popover | `v-model` ISO string or `[start,end]`, `range`, `min`, `max`, `locale`, `nativeOnTouch` |
185
+ | `BlessCalendar` | Month grid | same as DatePicker plus `weekStart`, `disabledDates`, `month` |
186
+ | `BlessInputOTP` | One-time code cells | `v-model`, `length`, `numeric`, `separators`, `masked`; emits `complete` |
187
+ | `BlessForm` / `BlessField` | Constraint-API form + field wiring | form emits `submit(FormData)` / `invalid`; field `label`, `required`, `description`, `error`; `#default="{ id, error, describedby }"` |
188
+ | `BlessNodeGraph` | Editable node-and-link diagram; keyboard linking, acyclic option | `v-model:nodes` `{id,x,y,label}`, `v-model:edges` `{from,to}`, `v-model:selected`, `v-model:view`, `snap`, `acyclic`, `editable`, `nodeWidth`, `nodeHeight`, `label`, `labels`; `#node`; `connect` `disconnect` `move` `remove` |
189
+ | `BlessFormula` | Safe expression field: live result, exact errors, did-you-mean, variable chips | `v-model`, `variables` `{name,label?,value}`, `functions`, `label`, `placeholder`, `disabled`, `locale`, `labels`; `result` |
190
+ | `BlessRangeCalendar` | Month where drags add or remove days (availability); keyboard painting, blocks summary | `v-model` `string[]` (YYYY-MM-DD), `month`, `weekStart`, `locale`, `min`, `max`, `disabledDates`, `label`, `labels`; `#summary`; `change` |
191
+ | `BlessScheduler` | Day/week time grid; drag to create/move/resize, overlap lanes, keyboard, snap | `v-model` events `{id,title,date,start,end}` (minutes), `v-model:date`, `v-model:selected`, `view`, `weekStart`, `dayStart`, `dayEnd`, `snap`, `hourHeight`, `locale`, `editable`, `label`, `labels`; `create` `change` `remove` |
166
192
 
167
193
  ### Layout & navigation
168
194
 
169
- | Component | Purpose | Key props / slots |
170
- | ------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
171
- | `BlessStage` | Page shell, sidebar → drawer under 800px | `v-model:open`; `#sidebar` default `#footer` `#background` |
172
- | `BlessSidebarNav` | Vertical nav list | `items`, `active`; emits `select`; `#item` |
173
- | `BlessNavigationMenu` | Horizontal nav with panels | `items[{label,href,items[]}]`; emits `select`; `#panel` |
174
- | `BlessMenubar` | Bar of `BlessDropdownMenu`s | `label` |
175
- | `BlessSteps` | Stepper | `steps[{label,description}]`, `v-model` index, `orientation`, `clickable`; emits `select` |
176
- | `BlessTree` / `BlessTreeItem` | Nested `<details>` tree | `nodes[{label,id,href,icon,children,open,disabled}]`, `v-model:selected`; emits `select` |
177
- | `BlessContainer` | Centred max-width box | `size` sm/md/lg/full, `padded`, `as` |
178
- | `BlessStack` | Flex row / column | `direction`, `gap` token, `align`, `justify`, `wrap`, `as` |
179
- | `BlessScrollTop` | Back-to-top button | `threshold`, `target`, `position`, `label` |
180
- | `BlessToolbar` | Start / center / end bar | `label`, `surface`; `#start` `#center` `#end` |
181
- | `BlessPanel` | Titled box | `title`, `toggleable`, `v-model:collapsed`, `surface`; `#actions` `#footer` |
182
- | `BlessStepper` | Steps + panels | `steps`, `v-model`, `orientation`, `labels`; `#default="{step,index,next,prev,last}"` `#actions`; emits `finish` |
183
- | `BlessSplitButton` | Button + menu | `label`, `items`, `color`, `variant`, `size`; emits `click` `select` |
184
- | `BlessDataView` | List / grid + pagination | `items`, `pageSize`, `columns`, `v-model:layout`, `rowKey`; `#default="{item,index,layout}"` `#header` `#empty` |
185
- | `BlessDeferredContent` | Mount on scroll into view | `rootMargin`, `minHeight`; `#placeholder`; emits `load` |
186
- | `BlessTreeTable` | Expandable rows | `rows` (with `children`), `columns`, `rowKey`, `treeColumn`, `v-model:expanded`, `defaultExpanded`; `#cell-*` pass through |
187
- | `BlessOrgChart` / `BlessOrgChartNode` | Node tree with connectors | `nodes`, `v-model:selected`; `#node="{node, selected}"`; emits `select` |
188
- | `BlessBottomTabs` | Mobile bottom nav / dock | `items[{label,value,icon,href,badge}]`, `v-model`, `variant` bar/dock, `inline`; emits `select` |
189
- | `BlessSpeedDial` | FAB with fan-out actions | `actions[{label,value,icon,color}]`, `direction`, `color`, `v-model:open`, `inline`; emits `select` |
190
- | `BlessVirtualScroller` | Windowed list (fixed row height) | `items`, `itemHeight`, `height`, `overscan`, `rowKey`; exposes `scrollTo(i)`; `#default="{item,index}"` |
191
- | `BlessBreadcrumb` | Trail | `items[{label,href}]`, `separator`; `#item` |
192
- | `BlessPagination` | Page list | `v-model`, `total`, `siblings`, `href(page)` |
193
- | `BlessTabs` | ARIA tablist | `tabs`, `v-model`, `activation`, `color`; `#default="{tab}"` `#tab` |
194
- | `BlessSection` / `BlessWatermark` | Titled block with a giant watermark word | `title`, `watermark`, `watermarkPosition`, `headingLevel` |
195
- | `BlessBackground` | Tiled texture layer | `src`, `offset`, `mode`, `opacity` |
196
- | `BlessCard` | Flat surface | `label`, `labelColor`, `surface`, `bordered`, `href`; `#media` `#footer` |
197
- | `BlessList` / `BlessListItem` | Divided rows | item `meta`, `badge`, `href`; `#suffix` |
198
- | `BlessCollapsible` / `BlessAccordion(Item)` | `<details>` based | `v-model:open`, `title`, `disabled`; accordion `type` single/multiple |
199
- | `BlessScrollArea` | Thin scrollbar + fade | `axis`, `fade`, `height`, `width` |
200
- | `BlessResizable` | Two-pane split | `v-model` (% of first pane), `direction`, `min`, `max`, `step`; `#a` `#b` |
201
- | `BlessTable` | Typed table, stacks on mobile | `columns`, `rows`, `rowKey`, `caption`, `striped`, `stack`; `#cell-<key>` |
202
- | `BlessDataTable` | Table + sort/search/select/paginate | `columns` (+`sortable`, `hideable`), `rows`, `rowKey`, `selectable`, `searchable`, `pageSize`; `#toolbar` `#cell-<key>` |
195
+ | Component | Purpose | Key props / slots |
196
+ | ------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | `BlessStage` | Page shell, sidebar → drawer under 800px | `v-model:open`; `#sidebar` default `#footer` `#background` |
198
+ | `BlessSidebarNav` | Vertical nav list | `items`, `active`; emits `select`; `#item` |
199
+ | `BlessNavigationMenu` | Horizontal nav with panels | `items[{label,href,items[]}]`; emits `select`; `#panel` |
200
+ | `BlessMenubar` | Bar of `BlessDropdownMenu`s | `label` |
201
+ | `BlessSteps` | Stepper | `steps[{label,description}]`, `v-model` index, `orientation`, `clickable`; emits `select` |
202
+ | `BlessTree` / `BlessTreeItem` | Nested `<details>` tree | `nodes[{label,id,href,icon,children,open,disabled}]`, `v-model:selected`; emits `select` `change` |
203
+ | `BlessContainer` | Centred max-width box | `size` sm/md/lg/full, `padded`, `as` |
204
+ | `BlessStack` | Flex row / column | `direction`, `gap` token, `align`, `justify`, `wrap`, `as` |
205
+ | `BlessScrollTop` | Back-to-top button | `threshold`, `target`, `position`, `label` |
206
+ | `BlessToolbar` | Start / center / end bar | `label`, `surface`; `#start` `#center` `#end` |
207
+ | `BlessPanel` | Titled box | `title`, `toggleable`, `v-model:collapsed`, `surface`; `#actions` `#footer` |
208
+ | `BlessStepper` | Steps + panels | `steps`, `v-model`, `orientation`, `labels`; `#default="{step,index,next,prev,last}"` `#actions`; emits `finish` |
209
+ | `BlessSplitButton` | Button + menu | `label`, `items`, `color`, `variant`, `size`; emits `click` `select` |
210
+ | `BlessDataView` | List / grid + pagination | `items`, `pageSize`, `columns`, `v-model:layout`, `rowKey`; `#default="{item,index,layout}"` `#header` `#empty` |
211
+ | `BlessDeferredContent` | Mount on scroll into view | `rootMargin`, `minHeight`; `#placeholder`; emits `load` |
212
+ | `BlessTreeTable` | Expandable rows | `rows` (with `children`), `columns`, `rowKey`, `treeColumn`, `v-model:expanded`, `defaultExpanded`; `#cell-*` pass through |
213
+ | `BlessOrgChart` / `BlessOrgChartNode` | Node tree with connectors | `nodes`, `v-model:selected`; `#node="{node, selected}"`; emits `select` |
214
+ | `BlessBottomTabs` | Mobile bottom nav / dock | `items[{label,value,icon,href,badge}]`, `v-model`, `variant` bar/dock, `inline`; emits `select` |
215
+ | `BlessSpeedDial` | FAB with fan-out actions | `actions[{label,value,icon,color}]`, `direction`, `color`, `v-model:open`, `inline`; emits `select` |
216
+ | `BlessVirtualScroller` | Windowed list (fixed row height) | `items`, `itemHeight`, `height`, `overscan`, `rowKey`; exposes `scrollTo(i)`; `#default="{item,index}"` |
217
+ | `BlessBreadcrumb` | Trail | `items[{label,href}]`, `separator`; `#item` |
218
+ | `BlessPagination` | Page list | `v-model`, `total`, `siblings`, `href(page)` |
219
+ | `BlessTabs` | ARIA tablist | `tabs`, `v-model`, `activation`, `color`; `#default="{tab}"` `#tab` |
220
+ | `BlessSection` / `BlessWatermark` | Titled block with a giant watermark word | `title`, `watermark`, `watermarkPosition`, `headingLevel` |
221
+ | `BlessBackground` | Tiled texture layer | `src`, `offset`, `mode`, `opacity` |
222
+ | `BlessCard` | Flat surface | `label`, `labelColor`, `surface`, `bordered`, `href`; `#media` `#footer` |
223
+ | `BlessList` / `BlessListItem` | Divided rows | item `meta`, `badge`, `href`; `#suffix` |
224
+ | `BlessCollapsible` / `BlessAccordion(Item)` | `<details>` based | `v-model:open`, `title`, `disabled`; accordion `type` single/multiple |
225
+ | `BlessScrollArea` | Thin scrollbar + fade | `axis`, `fade`, `height`, `width` |
226
+ | `BlessResizable` | Two-pane split | `v-model` (% of first pane), `direction`, `min`, `max`, `step`; `#a` `#b` |
227
+ | `BlessTable` | Typed table, stacks on mobile | `columns`, `rows`, `rowKey`, `caption`, `striped`, `stack`; `#cell-<key>` |
228
+ | `BlessDataTable` | Table + sort/search/select/paginate | `columns` (+`sortable`, `hideable`), `rows`, `rowKey`, `selectable`, `searchable`, `pageSize`; `#toolbar` `#cell-<key>` |
229
+ | `BlessInfiniteCanvas` | Pan / zoom surface; Ctrl+wheel and pinch zoom, arrows and +/− from the keyboard | `v-model:view` `{x,y,zoom}`, `minZoom`, `maxZoom`, `grid`, `controls`, `wheelZoom`, `label`, `labels`; exposes `fit` `centerOn` `zoomBy` `reset` `toWorld` |
230
+ | `BlessDock` | Magnifying icon dock; toolbar keys, links or buttons, badge; off for touch and reduced motion | `items` `{id,label,icon?,href?,badge?,disabled?}`, `position`, `size`, `magnification`, `radius`, `label`; `#item`; `select` |
203
231
 
204
232
  ### Overlays
205
233
 
206
- | Component | Purpose | Key props / slots |
207
- | --------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
208
- | `BlessModal` | Native `<dialog>` | `v-model`, `title`, `hash` (deep link), `size`, `dismissible`; `#footer` |
209
- | `BlessAlertDialog` | Confirm dialog | `v-model`, `title`, `description`, `confirmLabel`, `cancelLabel`, `color`, `loading`; emits `confirm` `cancel` |
210
- | `BlessSheet` | Side panel | `v-model`, `side`, `title`, `size`, `handle`; `#footer` |
211
- | `BlessDrawer` | Bottom sheet with swipe-to-close | `v-model`, `title` |
212
- | `BlessPopover` | Popover API panel | `v-model:open`, `placement`, `trigger` click/hover/manual, `modal`; `#trigger` `#default="{close}"` |
213
- | `BlessTooltip` | Hover/focus tip | `text`, `placement`, `delay`; `#content` |
214
- | `BlessHoverCard` | Rich hover popover | `placement`, `openDelay`, `closeDelay`; `#trigger` |
215
- | `BlessDropdownMenu` | ARIA menu | `items` (item/checkbox/radio/separator/label/sub), `placement`, `v-model:checked`, `v-model:radios`; emits `select`; `#trigger` |
216
- | `BlessContextMenu` | Menu on right click | `items`; wraps its slot |
217
- | `BlessCommand` | ⌘K palette | `v-model:open`, `items` (groups, keywords, shortcuts), `inline`, `hotkey`; emits `select`; `#footer` |
218
- | `BlessGallery` | Thumb grid + lightbox | `items`, `v-model` index, `columns`, `loop` |
219
- | `BlessConfirmPopup` | Confirm in a popover | `message`, `title`, `confirmLabel`, `cancelLabel`, `color`, `placement`, `v-model:open`; emits `confirm` `cancel` |
220
- | `BlessDialogHost` + `useDialog()` | Programmatic modals | `open({ title, component, props, text, size, dismissible })` → Promise, `close(id, result)` |
221
- | `BlessTour` | Spotlight walkthrough | `steps[{target,title,text,placement}]`, `v-model:open`, `v-model:step`, `spotlight`, `labels`; emits `finish` `skip` |
222
- | `BlessToaster` + `useToast()` | Notifications | `position`; `toast()`, `success()`, `error()`, `warning()`, `info()`, `dismiss()` |
223
- | `BlessSplash` | First-visit overlay | `once`, `duration`, `skipLabel`; emits `done` |
234
+ | Component | Purpose | Key props / slots |
235
+ | --------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
236
+ | `BlessModal` | Native `<dialog>` | `v-model`, `title`, `hash` (deep link), `size`, `dismissible`; `#footer` |
237
+ | `BlessAlertDialog` | Confirm dialog | `v-model`, `title`, `description`, `confirmLabel`, `cancelLabel`, `color`, `loading`; emits `confirm` `cancel` |
238
+ | `BlessSheet` | Side panel | `v-model`, `side`, `title`, `size`, `handle`; `#footer` |
239
+ | `BlessDrawer` | Bottom sheet with swipe-to-close | `v-model`, `title` |
240
+ | `BlessPopover` | Popover API panel | `v-model:open`, `placement`, `trigger` click/hover/manual, `modal`; `#trigger` `#default="{close}"` |
241
+ | `BlessTooltip` | Hover/focus tip | `text`, `placement`, `delay`; `#content` |
242
+ | `BlessHoverCard` | Rich hover popover | `placement`, `openDelay`, `closeDelay`; `#trigger` |
243
+ | `BlessDropdownMenu` | ARIA menu | `items` (item/checkbox/radio/separator/label/sub), `placement`, `v-model:checked`, `v-model:radios`; emits `select`; `#trigger` |
244
+ | `BlessContextMenu` | Menu on right click | `items`; wraps its slot |
245
+ | `BlessCommand` | ⌘K palette | `v-model:open`, `v-model:history`, `items` (groups, keywords, shortcuts), `scopes`, `recent`, `recentLimit`, `persist`, `labels`, `inline`, `hotkey`; emits `select`; `#footer` |
246
+ | `BlessGallery` | Thumb grid + lightbox | `items`, `v-model` index, `columns`, `loop` |
247
+ | `BlessConfirmPopup` | Confirm in a popover | `message`, `title`, `confirmLabel`, `cancelLabel`, `color`, `placement`, `v-model:open`; emits `confirm` `cancel` |
248
+ | `BlessDialogHost` + `useDialog()` | Programmatic modals | `open({ title, component, props, text, size, dismissible })` → Promise, `close(id, result)` |
249
+ | `BlessTour` | Spotlight walkthrough | `steps[{target,title,text,placement}]`, `v-model:open`, `v-model:step`, `spotlight`, `labels`; emits `finish` `skip` |
250
+ | `BlessToaster` + `useToast()` | Notifications | `position`; `toast()`, `success()`, `error()`, `warning()`, `info()`, `dismiss()` |
251
+ | `BlessSplash` | First-visit overlay | `once`, `duration`, `skipLabel`; emits `done` |
252
+ | `BlessConfetti` | Confetti burst fired with `fire(from?, angle?)`; off under reduced motion | `count`, `colors`, `duration`, `spread`, `power`, `gravity`; `done` |
253
+ | `BlessCoachmark` | Pulsing new-dot with a bubble; remembers dismissal by id | `text`, `id`, `placement`, `dismissOnUse`, `v-model:dismissed`, `labels`; `dismiss` |
254
+ | `BlessOnboardingChecklist` | Getting-started checklist: real checkboxes, progress, collapse, dismiss, persisted | `items` `{id,label,description?,action?}`, `v-model:done`, `v-model:collapsed`, `v-model:dismissed`, `title`, `persist`, `floating`, `dismissible`, `labels`; `#complete`; `select` `complete` `dismiss` |
224
255
 
225
256
  ### Conversation
226
257
 
@@ -235,10 +266,12 @@ import {
235
266
 
236
267
  ### Chart
237
268
 
238
- | Component | Purpose | Key props / slots |
239
- | ------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
240
- | `BlessChart` | Themed frame for any [Unovis](https://unovis.dev) chart | `title`, `description`, `height`, `legend[]`; `#header` `#legend` `#footer`, default = chart |
241
- | `BlessQrCode` | QR SVG from a module matrix ([uqr](https://github.com/unjs/uqr)) | `matrix` boolean[][], `value`, `size`, `border`, `color`, `background`, `frame` |
269
+ | Component | Purpose | Key props / slots |
270
+ | ---------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
271
+ | `BlessChart` | Themed frame for any [Unovis](https://unovis.dev) chart | `title`, `description`, `height`, `legend[]`; `#header` `#legend` `#footer`, default = chart |
272
+ | `BlessQrCode` | QR SVG from a module matrix ([uqr](https://github.com/unjs/uqr)) | `matrix` boolean[][], `value`, `size`, `border`, `color`, `background`, `frame` |
273
+ | `BlessSparkline` | Tiny inline trend: line, bar or win/loss | `data`, `type`, `width`, `height`, `color`, `negativeColor`, `fill`, `dot`, `label`, `format` |
274
+ | `BlessTreemap` | Squarified treemap of a tree of sizes; drill-down path and keyboard | `data` `{id,label,value?,children?,color?}`, `v-model:path`, `height`, `format`, `label`, `labels`; `select` |
242
275
 
243
276
  Blessing does not bundle a chart library. `BlessChart` maps `--bless-color-chart-{1..5}`, type and dark mode onto Unovis' `--vis-*` variables, and adds a legend. Install Unovis yourself:
244
277
 
@@ -273,13 +306,14 @@ Gestures: `usePan(el, cb)` · `useSwipe(el, cb, { threshold, axis })` · `useLon
273
306
 
274
307
  ### Media
275
308
 
276
- | Component | Purpose | Key props / slots |
277
- | ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------- |
278
- | `BlessImg` | Lazy image | `src`, `alt`, `ratio`, `fit`, `loading`, `placeholder`, `srcset`, `sizes`; default slot = caption overlay; `#error` |
279
- | `BlessVideo` | Responsive embed / video | `src`, `title`, `ratio`, `native`, `poster` |
280
- | `BlessParallax` | Slow-scrolling background | `src`, `height`, `speed`; `#media` default |
281
- | `BlessCarousel` | Scroll-snap slider | `v-model`, `perView`, `gap`, `loop`, `autoplay`, `dots`, `arrows` |
282
- | `BlessAudioPlayer` | Track list player | `tracks`, `v-model` index, `color`; emits `play` `pause` `ended` |
309
+ | Component | Purpose | Key props / slots |
310
+ | ------------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
311
+ | `BlessImg` | Lazy image | `src`, `alt`, `ratio`, `fit`, `loading`, `placeholder`, `srcset`, `sizes`; default slot = caption overlay; `#error` |
312
+ | `BlessVideo` | Responsive embed / video | `src`, `title`, `ratio`, `native`, `poster` |
313
+ | `BlessParallax` | Slow-scrolling background | `src`, `height`, `speed`; `#media` default |
314
+ | `BlessCarousel` | Scroll-snap slider | `v-model`, `perView`, `gap`, `loop`, `autoplay`, `dots`, `arrows` |
315
+ | `BlessAudioPlayer` | Track list player | `tracks`, `v-model` index, `color`; emits `play` `pause` `ended` |
316
+ | `BlessAnnotator` | Draw / move / resize boxes and pins on an image; regions as fractions; keyboard | `v-model` regions `{id,x,y,w?,h?,label}`, `v-model:selected`, `v-model:tool`, `src`, `alt`, `editable`, `label`, `labels` |
283
317
 
284
318
  ### Composables
285
319