veloria-ui 0.1.3 → 0.1.5

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 (78) hide show
  1. package/CHANGELOG.md +596 -0
  2. package/README.md +72 -78
  3. package/dist/cli/index.js +946 -228
  4. package/dist/index.d.mts +419 -60
  5. package/dist/index.d.ts +419 -60
  6. package/dist/index.js +4604 -1510
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +4574 -1509
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/motion.d.mts +286 -0
  11. package/dist/motion.d.ts +286 -0
  12. package/dist/motion.js +655 -0
  13. package/dist/motion.js.map +1 -0
  14. package/dist/motion.mjs +601 -0
  15. package/dist/motion.mjs.map +1 -0
  16. package/dist/provider.js +288 -209
  17. package/dist/provider.js.map +1 -1
  18. package/dist/provider.mjs +288 -209
  19. package/dist/provider.mjs.map +1 -1
  20. package/dist/rhf.d.mts +202 -0
  21. package/dist/rhf.d.ts +202 -0
  22. package/dist/rhf.js +1598 -0
  23. package/dist/rhf.js.map +1 -0
  24. package/dist/rhf.mjs +1561 -0
  25. package/dist/rhf.mjs.map +1 -0
  26. package/dist/tailwind.js +9 -4
  27. package/package.json +216 -29
  28. package/src/cli/index.ts +962 -91
  29. package/src/cli/registry.ts +147 -103
  30. package/src/components/advanced-forms/MultiStepForm.tsx +445 -0
  31. package/src/components/advanced-forms/RichTextEditor.tsx +461 -0
  32. package/src/components/advanced-forms/index.tsx +6 -0
  33. package/src/components/basic/Button.tsx +13 -7
  34. package/src/components/basic/IconButton.tsx +8 -1
  35. package/src/components/basic/index.tsx +120 -92
  36. package/src/components/data-display/AuroraCard.tsx +117 -0
  37. package/src/components/data-display/DataGrid.tsx +381 -0
  38. package/src/components/data-display/FileCard.tsx +231 -0
  39. package/src/components/data-display/GaugeChart.tsx +254 -0
  40. package/src/components/data-display/PricingCard.tsx +181 -0
  41. package/src/components/data-display/RadialProgressChart.tsx +175 -0
  42. package/src/components/data-display/SparklineChart.tsx +139 -0
  43. package/src/components/data-display/index.tsx +470 -470
  44. package/src/components/feedback/StepProgress.tsx +96 -0
  45. package/src/components/feedback/index.tsx +194 -144
  46. package/src/components/forms/AvatarUpload.tsx +251 -0
  47. package/src/components/forms/DateRangePicker.tsx +355 -0
  48. package/src/components/forms/NumberInput.tsx +181 -0
  49. package/src/components/forms/index.tsx +296 -100
  50. package/src/components/overlay/CommandBar.tsx +241 -0
  51. package/src/components/overlay/index.tsx +3 -0
  52. package/src/components/utility/TypewriterText.tsx +121 -0
  53. package/src/components/utility/index.tsx +108 -95
  54. package/src/index.ts +53 -1
  55. package/src/motion/Animated.tsx +77 -0
  56. package/src/motion/MotionPresence.tsx +144 -0
  57. package/src/motion/components.tsx +203 -0
  58. package/src/motion/engine.ts +150 -0
  59. package/src/motion/index.ts +57 -0
  60. package/src/motion/presets.ts +220 -0
  61. package/src/motion/types.ts +117 -0
  62. package/src/motion/useMotion.ts +120 -0
  63. package/src/motion/withMotion.tsx +133 -0
  64. package/src/rhf/RhfCheckbox.tsx +49 -0
  65. package/src/rhf/RhfCombobox.tsx +52 -0
  66. package/src/rhf/RhfInput.tsx +44 -0
  67. package/src/rhf/RhfMultiSelect.tsx +43 -0
  68. package/src/rhf/RhfOTPInput.tsx +43 -0
  69. package/src/rhf/RhfRadioGroup.tsx +48 -0
  70. package/src/rhf/RhfRatingInput.tsx +43 -0
  71. package/src/rhf/RhfSelect.tsx +85 -0
  72. package/src/rhf/RhfSlider.tsx +68 -0
  73. package/src/rhf/RhfSwitch.tsx +48 -0
  74. package/src/rhf/RhfTextArea.tsx +44 -0
  75. package/src/rhf/index.ts +38 -0
  76. package/src/styles/veloria.css +93 -82
  77. package/src/tailwind.ts +45 -23
  78. package/dist/tailwind.d.ts +0 -25
package/CHANGELOG.md CHANGED
@@ -7,6 +7,602 @@ This project follows [Semantic Versioning](https://semver.org).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.1.5] — 2026-03-17
11
+
12
+ ### `veloria-ui/motion` — Animated presence system
13
+
14
+ A new zero-dependency animation sub-path built entirely on the **Web Animations API**. No additional `npm install` required — it ships inside the `veloria-ui` package and adds `0 bytes` to your bundle unless you actually import it.
15
+
16
+ Import from `veloria-ui/motion`:
17
+
18
+ ```ts
19
+ import {
20
+ Animated, MotionPresence, withMotion, useMotion,
21
+ MotionModal, MotionDrawer, MotionCard, MotionToast,
22
+ stagger, PRESETS, DURATIONS,
23
+ } from "veloria-ui/motion";
24
+ ```
25
+
26
+ ---
27
+
28
+ #### Architecture — 9 files, one entry point
29
+
30
+ | File | Purpose |
31
+ |------|---------|
32
+ | `types.ts` | All TypeScript types — `MotionPreset`, `MotionConfig`, `MotionProps` |
33
+ | `presets.ts` | 16 named presets as WAAPI keyframe arrays. Each preset < 200 bytes. |
34
+ | `engine.ts` | Core runner — resolves config, checks `prefers-reduced-motion`, runs `element.animate()`, handles abort/cancel |
35
+ | `useMotion.ts` | React hook — attach enter/exit to a ref, tracks visible state, fires `onExitComplete` |
36
+ | `Animated.tsx` | `<Animated show motion>` — conditional element with animated enter/exit |
37
+ | `MotionPresence.tsx` | `<MotionPresence motion>` — manages enter/exit for children that mount/unmount |
38
+ | `withMotion.ts` | HOC — wraps any component to add a `motion` prop, watches `open` prop or runs on mount |
39
+ | `components.tsx` | Pre-wrapped `MotionModal`, `MotionDrawer`, `MotionToast`, `MotionCard`, etc. |
40
+ | `index.ts` | Single barrel export |
41
+
42
+ ---
43
+
44
+ #### 16 animation presets
45
+
46
+ | Preset | Description |
47
+ |--------|-------------|
48
+ | `fade` | Simple opacity fade |
49
+ | `fade-up` | Fade in from below |
50
+ | `fade-down` | Fade in from above |
51
+ | `fade-left` | Fade in from the right |
52
+ | `fade-right` | Fade in from the left |
53
+ | `fade-scale` | Fade + scale from 95% |
54
+ | `slide-up` | Translate from 100% below, no fade |
55
+ | `slide-down` | Translate from 100% above |
56
+ | `slide-left` | Translate from 100% right |
57
+ | `slide-right` | Translate from 100% left |
58
+ | `zoom` | Scale from 50% with fade |
59
+ | `zoom-out` | Scale from 110% with fade |
60
+ | `flip` | 3D Y-axis perspective flip |
61
+ | `flip-x` | 3D X-axis perspective flip |
62
+ | `bounce` | Elastic entrance with spring easing overshoot |
63
+ | `none` | No animation (useful for `prefers-reduced-motion` overrides) |
64
+
65
+ ---
66
+
67
+ #### `prefers-reduced-motion` — automatic
68
+
69
+ The engine checks `window.matchMedia("(prefers-reduced-motion: reduce)")` before every animation. When the user has requested reduced motion:
70
+
71
+ - All keyframe animations are skipped entirely
72
+ - Elements are made immediately visible/hidden instead
73
+ - No JavaScript timing or RAF overhead
74
+ - SSR-safe (returns `false` on the server)
75
+
76
+ ---
77
+
78
+ #### Pre-wrapped components
79
+
80
+ Ready-to-use `Motion*` variants of the most common Veloria UI components. Import and use as drop-in replacements — the `motion` prop is the only addition:
81
+
82
+ ```tsx
83
+ import {
84
+ MotionModal, MotionDrawer, MotionSheet, MotionDialog,
85
+ MotionPopover, MotionHoverCard,
86
+ MotionToast, MotionSnackbar, MotionBannerAlert,
87
+ MotionCard, MotionAlert,
88
+ } from "veloria-ui/motion";
89
+ ```
90
+
91
+ All wrappers are lazy — unused ones are fully tree-shaken from your bundle.
92
+
93
+ ---
94
+
95
+ #### `<Animated>` — conditional presence
96
+
97
+ ```tsx
98
+ import { Animated } from "veloria-ui/motion";
99
+
100
+ // Shorthand preset
101
+ <Animated show={isVisible} motion="fade-up">
102
+ <p>Animates in and out</p>
103
+ </Animated>
104
+
105
+ // Full config
106
+ <Animated show={isVisible} motion={{ preset: "fade-scale", duration: 300, delay: 100 }}>
107
+ <Card>Delayed entrance</Card>
108
+ </Animated>
109
+
110
+ // keepMounted — stays in DOM, just hidden
111
+ <Animated show={isVisible} motion="fade" keepMounted>
112
+ <ExpensivePanel />
113
+ </Animated>
114
+ ```
115
+
116
+ ---
117
+
118
+ #### `<MotionPresence>` — unmount with exit animation
119
+
120
+ ```tsx
121
+ import { MotionPresence } from "veloria-ui/motion";
122
+
123
+ <MotionPresence motion="zoom" onExitComplete={() => console.log("gone")}>
124
+ {isOpen && <Panel key="panel" />}
125
+ </MotionPresence>
126
+ ```
127
+
128
+ The child must have a stable `key` prop. When the child is removed from the tree, `MotionPresence` plays its exit animation before removing it from the DOM.
129
+
130
+ ---
131
+
132
+ #### `withMotion()` — HOC for your local components
133
+
134
+ ```tsx
135
+ import { withMotion } from "veloria-ui/motion";
136
+ import { Modal } from "@/components/ui/modal"; // your local copy
137
+
138
+ const MotionModal = withMotion(Modal, { visibleProp: "open" });
139
+
140
+ <MotionModal motion="fade-scale" open={isOpen} onOpenChange={setOpen} title="Hello" />
141
+ ```
142
+
143
+ `withMotion` watches the `visibleProp` (default `"open"`) and plays enter/exit when it changes. For non-overlay components, pass `{ visibleProp: null }` to animate only on mount.
144
+
145
+ ---
146
+
147
+ #### `stagger()` — staggered list animations
148
+
149
+ ```tsx
150
+ import { Animated, stagger } from "veloria-ui/motion";
151
+
152
+ {items.map((item, i) => (
153
+ <Animated key={item.id} motion={{ preset: "fade-up", delay: stagger(i, 60) }}>
154
+ <Card>{item.name}</Card>
155
+ </Animated>
156
+ ))}
157
+ // item 0: delay 0ms, item 1: delay 60ms, item 2: delay 120ms…
158
+ ```
159
+
160
+ ---
161
+
162
+ #### `useMotion()` — hook for custom elements
163
+
164
+ ```tsx
165
+ import { useMotion } from "veloria-ui/motion";
166
+
167
+ function MyPanel({ show }: { show: boolean }) {
168
+ const { ref, isVisible } = useMotion({
169
+ show,
170
+ motion: "slide-up",
171
+ onExitComplete: () => console.log("exit done"),
172
+ });
173
+
174
+ if (!isVisible) return null;
175
+
176
+ return <div ref={ref as React.RefObject<HTMLDivElement>}>Content</div>;
177
+ }
178
+ ```
179
+
180
+ ---
181
+
182
+ #### Imperative API
183
+
184
+ ```tsx
185
+ import { animate, resolveConfig } from "veloria-ui/motion";
186
+
187
+ // Run an animation directly on a DOM element — no React required
188
+ const config = resolveConfig("slide-up");
189
+ await animate({ el: document.getElementById("my-div")!, config, phase: "enter" });
190
+ ```
191
+
192
+ ---
193
+
194
+ #### `tsup.config.ts` — new motion entry
195
+
196
+ A dedicated tsup entry `{ motion: "src/motion/index.ts" }` produces `dist/motion.mjs` and `dist/motion.js`. The entry is completely separate from the main bundle so projects that don't use it pay zero cost.
197
+
198
+ ---
199
+
200
+ #### `package.json` — new `./motion` export
201
+
202
+ ```json
203
+ "./motion": {
204
+ "types": "./dist/motion.d.ts",
205
+ "import": "./dist/motion.mjs",
206
+ "require": "./dist/motion.js"
207
+ }
208
+ ```
209
+
210
+ No new `dependencies` or `peerDependencies` added — the motion system has zero runtime dependencies beyond React.
211
+
212
+ ### CLI — Three major UX enhancements
213
+
214
+ ---
215
+
216
+ #### `veloria-ui add` — Interactive component picker
217
+
218
+ Running `veloria-ui add` with no component names now launches a full interactive picker instead of printing a usage hint. The picker is a two-step flow built on `prompts` multiselect:
219
+
220
+ **Step 1 — Category select**
221
+
222
+ A multiselect showing all 10 categories with a live `installed/total` counter so you can see at a glance which areas of your project already have components:
223
+
224
+ ```
225
+ ? Which categories do you want to browse?
226
+ ❯ ◉ Basic 2/11 installed
227
+ ◯ Forms 0/14 installed
228
+ ◉ Feedback 1/16 installed
229
+ ◯ Data Display 0/22 installed
230
+ ```
231
+
232
+ **Step 2 — Component select per category**
233
+
234
+ For each chosen category, a multiselect shows every component with:
235
+ - A `✓` prefix on components that are already installed in your project
236
+ - A truncated description so you know what you're selecting
237
+ - A `[+deps]` hint on components that will auto-pull registry dependencies
238
+
239
+ ```
240
+ ? Basic components
241
+ ❯ ✓ button Solid, outline, ghost, soft, link, classic variants…
242
+ ◯ badge Compact label — solid, outline, soft, classic…
243
+ ◯ avatar-group Stacked avatars with overflow count [+deps]
244
+ ✓ tooltip Radix tooltip, all four sides…
245
+ ```
246
+
247
+ Already-installed components are pre-ticked but will be skipped (not re-copied) unless `--force` is passed. A summary line at the end tells you exactly which components were skipped and why.
248
+
249
+ **New `--dry-run` flag for `add`**
250
+
251
+ Added to both the interactive and direct modes. Shows what files would be written and which npm packages would be installed, without touching anything:
252
+
253
+ ```bash
254
+ npx veloria-ui add button modal --dry-run
255
+ npx veloria-ui add --dry-run # works with interactive picker too
256
+ ```
257
+
258
+ Output:
259
+ ```
260
+ Dry run — no files written.
261
+
262
+ Would copy to: components/ui/
263
+ button/index.tsx
264
+ modal/index.tsx
265
+
266
+ Would install: @radix-ui/react-slot, @radix-ui/react-dialog, clsx, …
267
+ ```
268
+
269
+ ---
270
+
271
+ #### `veloria-ui remove` — Uninstall components
272
+
273
+ New command (alias: `rm`) to remove installed components cleanly.
274
+
275
+ ```bash
276
+ npx veloria-ui remove button
277
+ npx veloria-ui remove button card modal
278
+ npx veloria-ui rm avatar-group # alias
279
+ ```
280
+
281
+ **Dependent check** — before removing, the CLI scans your other installed components for `registryDeps` entries that point to what you are about to remove. If any are found, it warns you:
282
+
283
+ ```
284
+ ⚠ The following installed components depend on what you're removing:
285
+
286
+ avatar-group → depends on avatar
287
+ command-palette → depends on command-dialog
288
+
289
+ Remove anyway? (dependents may break) › No
290
+ ```
291
+
292
+ Pass `--force` to skip the warning and remove unconditionally.
293
+
294
+ **File preview** — shows exactly which files and directories will be deleted before asking for confirmation:
295
+
296
+ ```
297
+ Files to be removed:
298
+ components/ui/button/index.tsx
299
+ components/ui/button/ (directory)
300
+ ```
301
+
302
+ **Lock cleanup** — removes the component entry from `veloria.lock.json` automatically, keeping your lock file accurate.
303
+
304
+ **Flags:**
305
+
306
+ | Flag | Description |
307
+ |------|-------------|
308
+ | `<components...>` | One or more component names to remove |
309
+ | `-y, --yes` | Skip confirmation prompt |
310
+ | `--force` | Remove even if other components depend on it |
311
+
312
+ ```bash
313
+ # Remove a single component
314
+ npx veloria-ui remove button
315
+
316
+ # Remove multiple at once
317
+ npx veloria-ui remove button card modal
318
+
319
+ # Remove without confirmation
320
+ npx veloria-ui remove skeleton --yes
321
+
322
+ # Remove even if dependents exist
323
+ npx veloria-ui remove avatar --force
324
+ ```
325
+
326
+ ---
327
+
328
+ #### `add` — Dependency graph display
329
+
330
+ Every `veloria-ui add` invocation (interactive or direct) now prints a structured dependency tree before the confirmation prompt. The tree shows:
331
+
332
+ - Which components you explicitly selected
333
+ - Which components are being auto-pulled via `registryDeps` (shown in yellow with an `(auto — registry dep)` label)
334
+ - Which npm packages will be installed as peer dependencies
335
+
336
+ ```
337
+ Adding 3 components (2 selected + 1 auto)
338
+
339
+ ├── command-bar
340
+ │ └── command-dialog (auto — registry dep)
341
+ └── avatar-group
342
+ └── avatar (auto — registry dep)
343
+
344
+ npm peer deps
345
+ ├── cmdk
346
+ ├── @radix-ui/react-dialog
347
+ └── @radix-ui/react-avatar
348
+ ```
349
+
350
+ For components with no registry deps or npm deps, the output is minimal:
351
+
352
+ ```
353
+ Adding 1 component
354
+
355
+ └── button
356
+
357
+ npm peer deps
358
+ ├── @radix-ui/react-slot
359
+ ├── class-variance-authority
360
+ ├── clsx
361
+ └── tailwind-merge
362
+ ```
363
+
364
+ This replaces the previous flat `Peer deps: …` line and makes the install plan fully transparent before anything is written to disk.
365
+
366
+ ---
367
+
368
+ ### Bug Fixes
369
+
370
+ - `add` with `--force` on a component that pulls `registryDeps` now correctly overwrites the dep files too, not only the top-level component.
371
+ - `upgrade` hint at the bottom of `list` now correctly says `npx veloria-ui add` (not `add <n>`) to reflect the new interactive mode.
372
+
373
+ ### React Hook Form Adapter — `veloria-ui/rhf`
374
+
375
+ A new optional sub-path export that provides zero-boilerplate `Controller` wrappers for every Veloria UI form component. Import from `veloria-ui/rhf` — requires `react-hook-form ^7.0.0` as an optional peer dependency.
376
+
377
+ **11 wrappers shipped:**
378
+
379
+ | Wrapper | Wraps | Notes |
380
+ |---------|-------|-------|
381
+ | `RhfInput` | `Input` + `FormField` | All `InputProps` forwarded (size, leftElement, rightElement…) |
382
+ | `RhfTextArea` | `TextArea` + `FormField` | Full resize/rows control |
383
+ | `RhfSelect` | Radix `Select` + `FormField` | `onValueChange` bridged to `field.onChange` |
384
+ | `RhfCheckbox` | `Checkbox` + `FormField` | Boolean field — `checked` ↔ `field.value` |
385
+ | `RhfSwitch` | `Switch` + `FormField` | Same boolean mapping as `RhfCheckbox` |
386
+ | `RhfRadioGroup` | `RadioGroup` + `FormField` | `onValueChange` → `field.onChange` |
387
+ | `RhfSlider` | `Slider` + `FormField` | Stores plain `number`, converts to `number[]` internally |
388
+ | `RhfCombobox` | `Combobox` + `FormField` | `onChange` bridged to `field.onChange` |
389
+ | `RhfMultiSelect` | `MultiSelect` + `FormField` | Field value is `string[]` |
390
+ | `RhfRatingInput` | `RatingInput` + `FormField` | Numeric value |
391
+ | `RhfOTPInput` | `OTPInput` + `FormField` | String value |
392
+
393
+ Every wrapper automatically maps `fieldState.error` to the component's `invalid` prop and renders `<FormError>` with the message. All original visual props (`size`, `placeholder`, `disabled`, `label`, etc.) pass straight through — no new API surface to learn.
394
+
395
+ **Usage:**
396
+
397
+ ```tsx
398
+ import { useForm } from "react-hook-form";
399
+ import { RhfInput, RhfSelect, RhfCheckbox } from "veloria-ui/rhf";
400
+
401
+ const { control, handleSubmit } = useForm<{ email: string; role: string; agree: boolean }>();
402
+
403
+ <form onSubmit={handleSubmit(onSubmit)}>
404
+ <RhfInput name="email" control={control} label="Email" type="email" />
405
+ <RhfSelect name="role" control={control} label="Role" options={roles} />
406
+ <RhfCheckbox name="agree" control={control} label="I agree to the terms" />
407
+ </form>
408
+ ```
409
+
410
+ ### Build
411
+
412
+ - `veloria-ui/rhf` entry added to `exports` map in `package.json`
413
+ - New tsup build target for `src/rhf/index.ts` (CJS + ESM + DTS)
414
+ - `react-hook-form` added to `sharedExternal` — never bundled
415
+ - `veloria-ui` itself added to `sharedExternal` — prevents self-resolution error during the RHF build pass
416
+ - All `Rhf*.tsx` files import from `../index` (relative source path) rather than `"veloria-ui"` package name — eliminates circular resolve during build
417
+
418
+ ### Infrastructure
419
+
420
+ - `.npmrc` added with `public-hoist-pattern[]=tsup` and `public-hoist-pattern[]=typescript` so `pnpm install` always hoists build tool binaries to `node_modules/.bin` — fixes `tsup: not found` on Replit and similar isolated-store environments
421
+ - `react-hook-form ^7.0.0` added as optional peer dependency
422
+
423
+ ### New Components (5)
424
+
425
+ **`DataGrid`** (`data-display`)
426
+ A spreadsheet-grade table built entirely without external grid libraries. Implements row virtualisation with a configurable overscan so 100k-row datasets render at 60fps. Columns are resizable by dragging the right edge of any header. Cells are editable on double-click with Tab-to-next-cell navigation and Enter/Escape to commit/cancel. Supports multi-column sorting (click header to cycle asc/desc), row selection via a `selectedRows` Set, right-click-to-copy on any cell, a `render` slot per column for custom cell content, and animated skeleton loading rows. Zero external dependencies beyond React.
427
+
428
+ ```tsx
429
+ <DataGrid
430
+ columns={[
431
+ { key: "name", header: "Name", sortable: true, editable: true, width: 200 },
432
+ { key: "email", header: "Email", sortable: true, width: 260 },
433
+ { key: "role", header: "Role", editable: true },
434
+ { key: "status", header: "Status", render: (v) => <Badge>{String(v)}</Badge> },
435
+ ]}
436
+ rows={users}
437
+ height={480}
438
+ onChange={setUsers}
439
+ selectedRows={selected}
440
+ onRowSelect={setSelected}
441
+ />
442
+ ```
443
+
444
+ **`RichTextEditor`** (`advanced-forms`)
445
+ A Tiptap-based editor styled to match the design system. Toolbar covers headings (H1–H3), bold, italic, underline, strikethrough, inline code, text alignment (left/center/right), bullet list, ordered list, blockquote, code block with syntax highlighting via `lowlight`, link, undo/redo. A `BubbleMenu` appears on text selection for quick bold/italic/link access. Controlled via `value`/`onChange` (HTML string). Supports `minHeight`, `maxHeight` (scrollable), `disabled`, `placeholder`, and `autofocus`. All toolbar icons are inline SVG — no icon library dependency.
446
+
447
+ ```tsx
448
+ <RichTextEditor
449
+ value={html}
450
+ onChange={setHtml}
451
+ placeholder="Write something…"
452
+ minHeight={300}
453
+ />
454
+ ```
455
+
456
+ **`DateRangePicker`** (`forms`)
457
+ A full custom two-calendar date range popover — not a wrapper around a native `<input type="date">`. Renders two side-by-side month grids (configurable to one with `numberOfMonths={1}`). Selection is two-click: first click sets the anchor, second sets the end. Hover preview shows the in-range highlight as you move the cursor. Edge days (from/to) get a filled primary circle; in-range days get a tinted background strip with squared-off edges connecting to the edge circles. Supports `minDate`, `maxDate`, a `disabledDates` predicate, and a `format` override for the trigger label. Clear button appears once a range is set.
458
+
459
+ ```tsx
460
+ <DateRangePicker
461
+ value={range}
462
+ onChange={setRange}
463
+ numberOfMonths={2}
464
+ placeholder="Select date range"
465
+ />
466
+ ```
467
+
468
+ **`CommandBar`** (`overlay`)
469
+ A persistent ⌘K command bar in the style of Linear/Vercel. Renders as a floating dialog at 20% from the top. Registers `Cmd+K` / `Ctrl+K` globally via a `useCommandBar` hook that can also be called standalone. Actions are grouped, searchable by label/description/keywords, and can carry keyboard shortcut hints rendered as `<kbd>` chips. The empty-state query shows recent actions (passed as `recentIds`). Built on cmdk + Radix Dialog. Footer row shows ↑↓ navigate, ↵ select, ⌘K to open.
470
+
471
+ ```tsx
472
+ <CommandBar
473
+ actions={actions}
474
+ recentIds={recentActionIds}
475
+ open={open}
476
+ onOpenChange={setOpen}
477
+ />
478
+ ```
479
+
480
+ **`MultiStepForm`** (`advanced-forms`)
481
+ A compound component that wires Stepper + form state + per-step async validation + animated slide transitions into a single coherent API. Each step definition can include a `validate` function returning an error map; the nav button won't advance until it resolves cleanly. Shared form data accumulates across steps and is handed to `onComplete` at the end. The `useMultiStepForm` hook exposes `setField`, `setError`, `clearError`, `next`, `back`, `goTo`, and `progress` to any child. The stepper renders in two layouts: `"top"` (horizontal with connector lines) and `"left"` (vertical sidebar). Completed steps are clickable to jump back. `MultiStepFormNav` renders the Back/Continue buttons with a progress bar above them.
482
+
483
+ ```tsx
484
+ <MultiStepForm steps={steps} onComplete={handleSubmit} stepperPosition="top">
485
+ <MultiStepFormStepPanel>
486
+ <AccountFields />
487
+ </MultiStepFormStepPanel>
488
+ <MultiStepFormStepPanel>
489
+ <ProfileFields />
490
+ </MultiStepFormStepPanel>
491
+ <MultiStepFormStepPanel>
492
+ <ReviewStep />
493
+ </MultiStepFormStepPanel>
494
+ <MultiStepFormNav />
495
+ </MultiStepForm>
496
+ ```
497
+
498
+ ### Registry
499
+
500
+ Five new entries added to `src/cli/registry.ts` under `// ── v0.1.7 additions`. See `registry-additions.ts` for the exact entries to splice in.
501
+
502
+ ### Dependencies added (peer, optional per component)
503
+
504
+ | Component | New deps |
505
+ |-----------|----------|
506
+ | `RichTextEditor` | `@tiptap/react`, `@tiptap/starter-kit`, `@tiptap/extension-placeholder`, `@tiptap/extension-link`, `@tiptap/extension-underline`, `@tiptap/extension-text-align`, `@tiptap/extension-code-block-lowlight`, `lowlight` |
507
+ | `DateRangePicker` | `@radix-ui/react-popover` (already peer dep) |
508
+ | `CommandBar` | `cmdk`, `@radix-ui/react-dialog` (already peer deps) |
509
+ | `DataGrid` | none |
510
+ | `MultiStepForm` | none |
511
+
512
+ ---
513
+
514
+ ## [0.1.4] — 2026-03-17
515
+
516
+ ### CLI
517
+
518
+ #### `veloria-ui upgrade` — new command
519
+
520
+ Reads `veloria.config.json`, discovers every component you have installed, checks each one against the latest upstream source on GitHub, and prompts you to upgrade those that have changed. Modelled on `npm outdated` but for copied source files — the first component library to ship this natively.
521
+
522
+ **Discovery** — scans your components directory for sub-folders matching registry names, then cross-references `veloria.lock.json` to catch any components stored at non-standard paths. No manual component list needed.
523
+
524
+ **Three-state staleness model** powered by `veloria.lock.json` (written/updated by `add` and `upgrade`):
525
+
526
+ | State | Meaning |
527
+ |-------|---------|
528
+ | `up-to-date` | Upstream hash matches the hash recorded at install time |
529
+ | `upstream-changed` | Upstream changed since install, but your local file is unmodified — safe to auto-upgrade |
530
+ | `diverged` | Both upstream and your local file have changed — warned before overwriting |
531
+ | `no-lock` | Component pre-dates the lock file; falls back to raw content comparison |
532
+
533
+ **Interactive prompt per outdated component** — shows `+N -N` change counts and offers three choices: upgrade, show full diff first (then decide), or skip.
534
+
535
+ **Flags:**
536
+
537
+ | Flag | Description |
538
+ |------|-------------|
539
+ | `[component]` | Upgrade a single named component |
540
+ | `-y, --yes` / `--all` | Upgrade all outdated non-interactively (skips diverged unless `--force`) |
541
+ | `--check` | Dry-run — report status only, make no changes |
542
+ | `--force` | Overwrite even diverged (locally modified) components |
543
+ | `--json` | Machine-readable JSON status report |
544
+
545
+ ```bash
546
+ # Check what's outdated (no changes)
547
+ npx veloria-ui upgrade --check
548
+
549
+ # Interactive upgrade — prompts per component
550
+ npx veloria-ui upgrade
551
+
552
+ # Upgrade a single component
553
+ npx veloria-ui upgrade button
554
+
555
+ # Upgrade everything non-interactively
556
+ npx veloria-ui upgrade --all
557
+
558
+ # CI status report
559
+ npx veloria-ui upgrade --check --json
560
+ ```
561
+
562
+ **`veloria.lock.json`** — new file written by `add` and updated by `upgrade`. Records the SHA-256 of each component's upstream source at install time, the upstream URL, and timestamps. Commit this file — it's what makes three-state upgrade detection possible.
563
+
564
+ #### `add` — updated
565
+
566
+ - Now fetches and writes real upstream source (not stubs) when GitHub is reachable.
567
+ - Records the upstream content hash and URL in `veloria.lock.json` at add time.
568
+ - Added `--force` flag to overwrite existing local files.
569
+
570
+ #### `diff` — updated
571
+
572
+ - The "To update" hint at the end of diff output now points to `npx veloria-ui upgrade <component>` instead of `add --force`.
573
+
574
+ ---
575
+
576
+ ## [0.1.4] — 2026-03-17
577
+
578
+ ### CLI
579
+
580
+ #### `veloria-ui diff <component>` — now fully implemented
581
+
582
+ Previously this command printed a "not implemented yet" warning. It is now a fully working line-by-line diff engine:
583
+
584
+ - **Fetches upstream source** directly from the GitHub raw API (`raw.githubusercontent.com`) — no npm registry round-trip needed.
585
+ - **Locates your local copy** automatically by reading `veloria.config.json` (falls back to `components/ui/<n>/index.tsx` and several other candidate paths).
586
+ - **Myers diff algorithm** — the same LCS-based algorithm used by Git. Produces the minimal edit set between your local file and the upstream source.
587
+ - **Unified-style terminal output** — colour-coded hunks (`+` in green, `-` in red) with configurable context lines, summary counts, and `···` separators between hunks.
588
+ - **`--json` flag** — machine-readable JSON output containing the full diff array and summary, suitable for CI pipelines or editor integrations.
589
+ - **`--context <n>` flag** — control how many context lines appear around each change (default: 3).
590
+ - **Graceful error handling** — clear messages when the component is not found locally (with an `add` hint), when the upstream fetch fails (with the checked URLs listed), or when the component name is unknown.
591
+ - **Multi-path resolution** — tries both a dedicated `<Component>.tsx` file and the category `index.tsx` to handle components that are co-located with siblings.
592
+
593
+ ```bash
594
+ # Basic usage
595
+ npx veloria-ui diff button
596
+
597
+ # More context around changes
598
+ npx veloria-ui diff modal --context 6
599
+
600
+ # CI-friendly JSON output
601
+ npx veloria-ui diff input --json
602
+ ```
603
+
604
+ ---
605
+
10
606
  ## [0.1.3] — 2026-03-16 (Edited)
11
607
 
12
608
  ### Branding & Naming