blessing-ui 0.2.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 (133) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +137 -125
  3. package/dist/blessing-ui.css +38 -2
  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.vue.d.ts +10 -0
  19. package/dist/components/BlessCodeBlock.vue_vue_type_script_setup_true_lang.js +39 -33
  20. package/dist/components/BlessCombobox.vue.d.ts +2 -0
  21. package/dist/components/BlessCombobox.vue_vue_type_script_setup_true_lang.js +3 -2
  22. package/dist/components/BlessCommand.css +1 -1
  23. package/dist/components/BlessCommand.vue.d.ts +26 -0
  24. package/dist/components/BlessCommand.vue_vue_type_script_setup_true_lang.js +137 -70
  25. package/dist/components/BlessConfetti.css +1 -0
  26. package/dist/components/BlessConfetti.js +6 -0
  27. package/dist/components/BlessConfetti.vue.d.ts +40 -0
  28. package/dist/components/BlessConfetti.vue_vue_type_script_setup_true_lang.js +77 -0
  29. package/dist/components/BlessCropper.vue.d.ts +16 -0
  30. package/dist/components/BlessCropper.vue_vue_type_script_setup_true_lang.js +47 -39
  31. package/dist/components/BlessDataTable.vue.d.ts +6 -0
  32. package/dist/components/BlessDataTable.vue_vue_type_script_setup_true_lang.js +56 -42
  33. package/dist/components/BlessDataView.vue.d.ts +7 -0
  34. package/dist/components/BlessDataView.vue_vue_type_script_setup_true_lang.js +38 -31
  35. package/dist/components/BlessDatePicker.vue.d.ts +3 -0
  36. package/dist/components/BlessDatePicker.vue_vue_type_script_setup_true_lang.js +46 -45
  37. package/dist/components/BlessDock.css +1 -0
  38. package/dist/components/BlessDock.js +6 -0
  39. package/dist/components/BlessDock.vue.d.ts +55 -0
  40. package/dist/components/BlessDock.vue_vue_type_script_setup_true_lang.js +100 -0
  41. package/dist/components/BlessEditor.vue.d.ts +2 -0
  42. package/dist/components/BlessEditor.vue_vue_type_script_setup_true_lang.js +23 -22
  43. package/dist/components/BlessFileInput.vue.d.ts +2 -0
  44. package/dist/components/BlessFileInput.vue_vue_type_script_setup_true_lang.js +3 -2
  45. package/dist/components/BlessFormula.css +1 -0
  46. package/dist/components/BlessFormula.js +6 -0
  47. package/dist/components/BlessFormula.vue.d.ts +53 -0
  48. package/dist/components/BlessFormula.vue_vue_type_script_setup_true_lang.js +111 -0
  49. package/dist/components/BlessGantt.vue.d.ts +12 -0
  50. package/dist/components/BlessGantt.vue_vue_type_script_setup_true_lang.js +74 -68
  51. package/dist/components/BlessInfiniteCanvas.css +1 -0
  52. package/dist/components/BlessInfiniteCanvas.js +6 -0
  53. package/dist/components/BlessInfiniteCanvas.vue.d.ts +91 -0
  54. package/dist/components/BlessInfiniteCanvas.vue_vue_type_script_setup_true_lang.js +232 -0
  55. package/dist/components/BlessInputNumber.vue.d.ts +5 -0
  56. package/dist/components/BlessInputNumber.vue_vue_type_script_setup_true_lang.js +39 -34
  57. package/dist/components/BlessKanban.vue.d.ts +12 -0
  58. package/dist/components/BlessKanban.vue_vue_type_script_setup_true_lang.js +127 -97
  59. package/dist/components/BlessLoadingBar.vue.d.ts +2 -0
  60. package/dist/components/BlessLoadingBar.vue_vue_type_script_setup_true_lang.js +8 -3
  61. package/dist/components/BlessMarquee.vue.d.ts +4 -0
  62. package/dist/components/BlessMarquee.vue_vue_type_script_setup_true_lang.js +32 -27
  63. package/dist/components/BlessNodeGraph.css +1 -0
  64. package/dist/components/BlessNodeGraph.js +6 -0
  65. package/dist/components/BlessNodeGraph.vue.d.ts +110 -0
  66. package/dist/components/BlessNodeGraph.vue_vue_type_script_setup_true_lang.js +321 -0
  67. package/dist/components/BlessOnboardingChecklist.css +1 -0
  68. package/dist/components/BlessOnboardingChecklist.js +6 -0
  69. package/dist/components/BlessOnboardingChecklist.vue.d.ts +72 -0
  70. package/dist/components/BlessOnboardingChecklist.vue_vue_type_script_setup_true_lang.js +157 -0
  71. package/dist/components/BlessOrderList.vue.d.ts +5 -0
  72. package/dist/components/BlessOrderList.vue_vue_type_script_setup_true_lang.js +62 -56
  73. package/dist/components/BlessPagination.vue.d.ts +2 -0
  74. package/dist/components/BlessPagination.vue_vue_type_script_setup_true_lang.js +2 -1
  75. package/dist/components/BlessPickList.vue.d.ts +5 -0
  76. package/dist/components/BlessPickList.vue_vue_type_script_setup_true_lang.js +55 -49
  77. package/dist/components/BlessRangeCalendar.css +1 -0
  78. package/dist/components/BlessRangeCalendar.js +6 -0
  79. package/dist/components/BlessRangeCalendar.vue.d.ts +51 -0
  80. package/dist/components/BlessRangeCalendar.vue_vue_type_script_setup_true_lang.js +217 -0
  81. package/dist/components/BlessScheduler.css +1 -0
  82. package/dist/components/BlessScheduler.js +6 -0
  83. package/dist/components/BlessScheduler.vue.d.ts +95 -0
  84. package/dist/components/BlessScheduler.vue_vue_type_script_setup_true_lang.js +347 -0
  85. package/dist/components/BlessShortcutRecorder.vue.d.ts +10 -0
  86. package/dist/components/BlessShortcutRecorder.vue_vue_type_script_setup_true_lang.js +50 -40
  87. package/dist/components/BlessSignaturePad.vue.d.ts +1 -1
  88. package/dist/components/BlessSliderCaptcha.vue.d.ts +5 -0
  89. package/dist/components/BlessSliderCaptcha.vue_vue_type_script_setup_true_lang.js +89 -84
  90. package/dist/components/BlessSortable.css +1 -1
  91. package/dist/components/BlessSortable.vue.d.ts +19 -1
  92. package/dist/components/BlessSortable.vue_vue_type_script_setup_true_lang.js +103 -55
  93. package/dist/components/BlessSparkline.css +1 -0
  94. package/dist/components/BlessSparkline.js +6 -0
  95. package/dist/components/BlessSparkline.vue.d.ts +28 -0
  96. package/dist/components/BlessSparkline.vue_vue_type_script_setup_true_lang.js +107 -0
  97. package/dist/components/BlessSteps.vue.d.ts +2 -0
  98. package/dist/components/BlessSteps.vue_vue_type_script_setup_true_lang.js +3 -2
  99. package/dist/components/BlessSwipeDeck.vue.d.ts +1 -1
  100. package/dist/components/BlessSwipeDeck.vue_vue_type_script_setup_true_lang.js +2 -1
  101. package/dist/components/BlessTimer.vue.d.ts +18 -0
  102. package/dist/components/BlessTimer.vue_vue_type_script_setup_true_lang.js +52 -43
  103. package/dist/components/BlessTour.vue.d.ts +1 -0
  104. package/dist/components/BlessTour.vue_vue_type_script_setup_true_lang.js +48 -42
  105. package/dist/components/BlessTreemap.css +1 -0
  106. package/dist/components/BlessTreemap.js +6 -0
  107. package/dist/components/BlessTreemap.vue.d.ts +46 -0
  108. package/dist/components/BlessTreemap.vue_vue_type_script_setup_true_lang.js +137 -0
  109. package/dist/components/BlessUploader.vue.d.ts +11 -0
  110. package/dist/components/BlessUploader.vue_vue_type_script_setup_true_lang.js +80 -69
  111. package/dist/composables/annotate.d.ts +35 -0
  112. package/dist/composables/annotate.js +33 -0
  113. package/dist/composables/canvasView.d.ts +21 -0
  114. package/dist/composables/canvasView.js +23 -0
  115. package/dist/composables/confetti.d.ts +32 -0
  116. package/dist/composables/confetti.js +23 -0
  117. package/dist/composables/dayBlocks.d.ts +11 -0
  118. package/dist/composables/dayBlocks.js +26 -0
  119. package/dist/composables/formula.d.ts +28 -0
  120. package/dist/composables/formula.js +161 -0
  121. package/dist/composables/graph.d.ts +19 -0
  122. package/dist/composables/graph.js +16 -0
  123. package/dist/composables/schedule.d.ts +27 -0
  124. package/dist/composables/schedule.js +54 -0
  125. package/dist/composables/treemap.d.ts +23 -0
  126. package/dist/composables/treemap.js +77 -0
  127. package/dist/composables/useAutoScroll.d.ts +15 -0
  128. package/dist/composables/useAutoScroll.js +32 -0
  129. package/dist/composables/useSortable.d.ts +42 -2
  130. package/dist/composables/useSortable.js +87 -14
  131. package/dist/index.d.ts +25 -1
  132. package/dist/index.js +78 -63
  133. package/package.json +4 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
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
+
3
34
  ## 0.2.0 — 2026-10-03
4
35
 
5
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.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Vue 3 component library and design tokens. Grey-scale UI with one accent that ap
10
10
 
11
11
  Docs, with every component live: **[ui.blessing.id](https://ui.blessing.id)**
12
12
 
13
- - 164 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
14
14
  - Native platform first: `<dialog>`, Popover API, `<details>`, native form controls, `Intl` dates, scroll-snap — no positioning, date or table library
15
15
  - Accessible defaults: focus rings, ARIA tablist/dialog/tables, `prefers-reduced-motion`
16
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
@@ -86,7 +86,7 @@ import {
86
86
 
87
87
  ## Components
88
88
 
89
- 164 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.
90
90
 
91
91
  ### Primitives
92
92
 
@@ -125,124 +125,133 @@ import {
125
125
 
126
126
  ### Forms
127
127
 
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 }"` |
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` |
188
192
 
189
193
  ### Layout & navigation
190
194
 
191
- | Component | Purpose | Key props / slots |
192
- | ------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
193
- | `BlessStage` | Page shell, sidebar → drawer under 800px | `v-model:open`; `#sidebar` default `#footer` `#background` |
194
- | `BlessSidebarNav` | Vertical nav list | `items`, `active`; emits `select`; `#item` |
195
- | `BlessNavigationMenu` | Horizontal nav with panels | `items[{label,href,items[]}]`; emits `select`; `#panel` |
196
- | `BlessMenubar` | Bar of `BlessDropdownMenu`s | `label` |
197
- | `BlessSteps` | Stepper | `steps[{label,description}]`, `v-model` index, `orientation`, `clickable`; emits `select` |
198
- | `BlessTree` / `BlessTreeItem` | Nested `<details>` tree | `nodes[{label,id,href,icon,children,open,disabled}]`, `v-model:selected`; emits `select` `change` |
199
- | `BlessContainer` | Centred max-width box | `size` sm/md/lg/full, `padded`, `as` |
200
- | `BlessStack` | Flex row / column | `direction`, `gap` token, `align`, `justify`, `wrap`, `as` |
201
- | `BlessScrollTop` | Back-to-top button | `threshold`, `target`, `position`, `label` |
202
- | `BlessToolbar` | Start / center / end bar | `label`, `surface`; `#start` `#center` `#end` |
203
- | `BlessPanel` | Titled box | `title`, `toggleable`, `v-model:collapsed`, `surface`; `#actions` `#footer` |
204
- | `BlessStepper` | Steps + panels | `steps`, `v-model`, `orientation`, `labels`; `#default="{step,index,next,prev,last}"` `#actions`; emits `finish` |
205
- | `BlessSplitButton` | Button + menu | `label`, `items`, `color`, `variant`, `size`; emits `click` `select` |
206
- | `BlessDataView` | List / grid + pagination | `items`, `pageSize`, `columns`, `v-model:layout`, `rowKey`; `#default="{item,index,layout}"` `#header` `#empty` |
207
- | `BlessDeferredContent` | Mount on scroll into view | `rootMargin`, `minHeight`; `#placeholder`; emits `load` |
208
- | `BlessTreeTable` | Expandable rows | `rows` (with `children`), `columns`, `rowKey`, `treeColumn`, `v-model:expanded`, `defaultExpanded`; `#cell-*` pass through |
209
- | `BlessOrgChart` / `BlessOrgChartNode` | Node tree with connectors | `nodes`, `v-model:selected`; `#node="{node, selected}"`; emits `select` |
210
- | `BlessBottomTabs` | Mobile bottom nav / dock | `items[{label,value,icon,href,badge}]`, `v-model`, `variant` bar/dock, `inline`; emits `select` |
211
- | `BlessSpeedDial` | FAB with fan-out actions | `actions[{label,value,icon,color}]`, `direction`, `color`, `v-model:open`, `inline`; emits `select` |
212
- | `BlessVirtualScroller` | Windowed list (fixed row height) | `items`, `itemHeight`, `height`, `overscan`, `rowKey`; exposes `scrollTo(i)`; `#default="{item,index}"` |
213
- | `BlessBreadcrumb` | Trail | `items[{label,href}]`, `separator`; `#item` |
214
- | `BlessPagination` | Page list | `v-model`, `total`, `siblings`, `href(page)` |
215
- | `BlessTabs` | ARIA tablist | `tabs`, `v-model`, `activation`, `color`; `#default="{tab}"` `#tab` |
216
- | `BlessSection` / `BlessWatermark` | Titled block with a giant watermark word | `title`, `watermark`, `watermarkPosition`, `headingLevel` |
217
- | `BlessBackground` | Tiled texture layer | `src`, `offset`, `mode`, `opacity` |
218
- | `BlessCard` | Flat surface | `label`, `labelColor`, `surface`, `bordered`, `href`; `#media` `#footer` |
219
- | `BlessList` / `BlessListItem` | Divided rows | item `meta`, `badge`, `href`; `#suffix` |
220
- | `BlessCollapsible` / `BlessAccordion(Item)` | `<details>` based | `v-model:open`, `title`, `disabled`; accordion `type` single/multiple |
221
- | `BlessScrollArea` | Thin scrollbar + fade | `axis`, `fade`, `height`, `width` |
222
- | `BlessResizable` | Two-pane split | `v-model` (% of first pane), `direction`, `min`, `max`, `step`; `#a` `#b` |
223
- | `BlessTable` | Typed table, stacks on mobile | `columns`, `rows`, `rowKey`, `caption`, `striped`, `stack`; `#cell-<key>` |
224
- | `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` |
225
231
 
226
232
  ### Overlays
227
233
 
228
- | Component | Purpose | Key props / slots |
229
- | --------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
230
- | `BlessModal` | Native `<dialog>` | `v-model`, `title`, `hash` (deep link), `size`, `dismissible`; `#footer` |
231
- | `BlessAlertDialog` | Confirm dialog | `v-model`, `title`, `description`, `confirmLabel`, `cancelLabel`, `color`, `loading`; emits `confirm` `cancel` |
232
- | `BlessSheet` | Side panel | `v-model`, `side`, `title`, `size`, `handle`; `#footer` |
233
- | `BlessDrawer` | Bottom sheet with swipe-to-close | `v-model`, `title` |
234
- | `BlessPopover` | Popover API panel | `v-model:open`, `placement`, `trigger` click/hover/manual, `modal`; `#trigger` `#default="{close}"` |
235
- | `BlessTooltip` | Hover/focus tip | `text`, `placement`, `delay`; `#content` |
236
- | `BlessHoverCard` | Rich hover popover | `placement`, `openDelay`, `closeDelay`; `#trigger` |
237
- | `BlessDropdownMenu` | ARIA menu | `items` (item/checkbox/radio/separator/label/sub), `placement`, `v-model:checked`, `v-model:radios`; emits `select`; `#trigger` |
238
- | `BlessContextMenu` | Menu on right click | `items`; wraps its slot |
239
- | `BlessCommand` | ⌘K palette | `v-model:open`, `items` (groups, keywords, shortcuts), `inline`, `hotkey`; emits `select`; `#footer` |
240
- | `BlessGallery` | Thumb grid + lightbox | `items`, `v-model` index, `columns`, `loop` |
241
- | `BlessConfirmPopup` | Confirm in a popover | `message`, `title`, `confirmLabel`, `cancelLabel`, `color`, `placement`, `v-model:open`; emits `confirm` `cancel` |
242
- | `BlessDialogHost` + `useDialog()` | Programmatic modals | `open({ title, component, props, text, size, dismissible })` → Promise, `close(id, result)` |
243
- | `BlessTour` | Spotlight walkthrough | `steps[{target,title,text,placement}]`, `v-model:open`, `v-model:step`, `spotlight`, `labels`; emits `finish` `skip` |
244
- | `BlessToaster` + `useToast()` | Notifications | `position`; `toast()`, `success()`, `error()`, `warning()`, `info()`, `dismiss()` |
245
- | `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` |
246
255
 
247
256
  ### Conversation
248
257
 
@@ -257,10 +266,12 @@ import {
257
266
 
258
267
  ### Chart
259
268
 
260
- | Component | Purpose | Key props / slots |
261
- | ------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
262
- | `BlessChart` | Themed frame for any [Unovis](https://unovis.dev) chart | `title`, `description`, `height`, `legend[]`; `#header` `#legend` `#footer`, default = chart |
263
- | `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` |
264
275
 
265
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:
266
277
 
@@ -295,13 +306,14 @@ Gestures: `usePan(el, cb)` · `useSwipe(el, cb, { threshold, axis })` · `useLon
295
306
 
296
307
  ### Media
297
308
 
298
- | Component | Purpose | Key props / slots |
299
- | ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------- |
300
- | `BlessImg` | Lazy image | `src`, `alt`, `ratio`, `fit`, `loading`, `placeholder`, `srcset`, `sizes`; default slot = caption overlay; `#error` |
301
- | `BlessVideo` | Responsive embed / video | `src`, `title`, `ratio`, `native`, `poster` |
302
- | `BlessParallax` | Slow-scrolling background | `src`, `height`, `speed`; `#media` default |
303
- | `BlessCarousel` | Scroll-snap slider | `v-model`, `perView`, `gap`, `loop`, `autoplay`, `dots`, `arrows` |
304
- | `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` |
305
317
 
306
318
  ### Composables
307
319