@synopackageland/ui 0.25.0 → 0.25.1

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.
@@ -30,7 +30,7 @@ These rules keep pages built from `@synopackageland/ui` consistent. The componen
30
30
  - In a dialog or a side `Sheet`, keep the default `direction="auto"`: as in DSM, the labels sit in a left column whenever the form is at least 400px wide (a 420–480px sheet) and stack above their controls only below that (a phone). Size the column with `Form label-width` (about 120px for short labels); a long label wraps inside it and stays level with its control's first line, whether that is a field, a select, a switch, a toggle group or a segment control.
31
31
  - Size a field by its content: number fields are 128px; text fields use `fieldWidth`; in a narrow row that stacks its label (a phone), `md` and `lg` fill the column. Put two short fields side by side rather than stretching one across the page.
32
32
  - A checkbox's text sits on the same line as its box. Do not apply `display: grid` to `label` in App CSS; `Checkbox` renders its own label.
33
- - For 2–4 mutually exclusive settings, use `RadioGroup` (vertical by default, `orientation="horizontal"` when labels fit). In a wizard step, `variant="card"` draws the options as choice cards with an optional `icon` each. A checkbox enables an independent option; a switch turns a feature on or off immediately. Keep the circular radio with a dot, square checkbox with a tick, and pill switch with a moving thumb.
33
+ - For 2–4 mutually exclusive settings, use `RadioGroup` (vertical by default, `orientation="horizontal"` when labels fit). In a wizard step, `variant="card"` draws the options as choice cards with an optional `icon` each. The 2–4 count is a guide, not a limit: the cards wrap, but five or more short options (or longer ones, even three) read better as a vertical radio list. A checkbox enables an independent option; a switch turns a feature on or off immediately. Keep the circular radio with a dot, square checkbox with a tick, and pill switch with a moving thumb.
34
34
  - Reserve `SegmentControl` for toolbar view switching: its selected item is a primary-filled capsule. `variant="sheet"` and `SectionTabs` are navigation tabs. Do not use either as a form value selector.
35
35
  - Choices side by side are 34px apart (`--ui-choice-inline-gap`, DSM's Task Scheduler) and share one top whether checked or not. For a set of checkboxes use `CheckboxGroup` (`orientation="horizontal"` for a row, `v-model` an array of values), as `RadioGroup` for one choice; Checkboxes written one after another get the same gap. Do not add margins between them.
36
36
  - A password field has a show/hide toggle; `Input type="password"` adds it.
@@ -190,6 +190,17 @@ component rule overrides them.
190
190
  IconButton draw their own pressed state (`data-variant`), so they're
191
191
  skipped. A component that sets its own shadow or `active:` style also keeps
192
192
  its own.
193
+ - Press feedback on a phone (`phone.css`, a coarse pointer in the mobile
194
+ presentation): a Button or an IconButton takes the `--ui-state-pressed`
195
+ layer over its own active colour and settles to `scale(0.98)` in 100ms
196
+ (`cubic-bezier(0.24, 1, 0.4, 1)`), springing back on release. The scale is
197
+ a transform, so nothing around the control moves. A ghost Button or
198
+ IconButton already fills with the layer and a link button fades, so neither
199
+ takes a second layer. A list row, a tab and a menu item keep the layer
200
+ alone: a row that shrank would pull away from its hairlines. A disabled
201
+ control takes nothing. Reduced motion and `data-ui-motion="off"` keep the
202
+ layer and drop the scale. A DSM window, a desktop page and a touch tablet
203
+ are unchanged.
193
204
  - Hover: every hand-written `:hover` rule in the theme sits inside
194
205
  `@media (hover: hover)`, so a tap leaves no stuck hover look. Tailwind's
195
206
  `hover:` utilities already do this.
@@ -468,7 +479,11 @@ contain`, a pinned footer and safe-area padding. The top corners use
468
479
  overrides that.
469
480
 
470
481
  `Dialog` on a phone (an app 640px or narrower) renders as a `BottomSheet`:
471
- `auto`, or `full` for `fullscreen` and for a form with more than 3 fields. The
482
+ `auto`, or `full` for `fullscreen` and for a form with more than 3 fields.
483
+ `presentation="modal"` keeps a centred window instead, with the phone's
484
+ dialog corner and dim scrim, as tall as its content up to its `height` inside
485
+ the safe area (only a longer body scrolls); `WizardDialog` uses it by default, as a DSM
486
+ wizard opens, and `presentation="adaptive"` gives it the bottom sheet. The
472
487
  CSS-only dialog-as-sheet in `adaptive.css` is gone. `Sheet side="bottom"` is
473
488
  a `BottomSheet` everywhere; without `size` it fits its content. Left and right
474
489
  sheets are unchanged, and their footer keeps clear of the home indicator.
@@ -8,7 +8,7 @@ checks through the optional build-isolation wrapper.
8
8
 
9
9
  | Entry point | Default | Explicit full |
10
10
  | --- | --- | --- |
11
- | `npm run gates`, `scripts/gates.mjs` | Internal-content checks, build, lint, typecheck, unit tests, notices, isolated pack and tarball content audit | Adds Chromium and WebKit installation, responsive/adaptive/date-picker/JSON/host/switch/layout/InfoTip/motion/short-viewport/phone-layout/phone-bars (Chromium and WebKit)/focus-restore browser checks, Histoire build, exact-tarball registry consumer smoke |
11
+ | `npm run gates`, `scripts/gates.mjs` | Internal-content checks, build, lint, typecheck, unit tests, notices, isolated pack and tarball content audit | Adds Chromium and WebKit installation, responsive/adaptive/date-picker/JSON/host/switch/layout/InfoTip/motion/short-viewport/phone-layout/phone-bars (Chromium and WebKit)/press/focus-restore browser checks, Histoire build, exact-tarball registry consumer smoke |
12
12
  | `pnpm check`, `check:fast` | Basic, with optional Docker host build isolation | `SPL_FULL_GATE=1` selects the same full plan |
13
13
  | `fast-ci.yml`, composite verify action | Basic | No automatic extended checks |
14
14
  | Disabled CI/release workflow templates | Basic, version/tag/ancestry checks, stage, pack and actual archive audit | No implicit browser or registry consumer smoke |
package/docs/wizard.md CHANGED
@@ -57,15 +57,20 @@ const open = ref(false)
57
57
  does not stack its children with a gap. Several blocks go in one `Form`
58
58
  (fields one field gap apart) or a `<Space direction="column">`; a lone
59
59
  Callout, paragraph or card grid needs no wrapper.
60
- - **Choices.** A step's 2–4 options are choice cards:
60
+ - **Choices.** Options that each need an icon and a line are choice cards:
61
61
  `<RadioGroup variant="card" orientation="horizontal" :options>`. Each card
62
62
  shows the option's `icon` in a tile, its label and one line, and keeps the
63
63
  radio dot; the whole card picks it and the chosen card takes the primary
64
64
  border and a soft fill. The cards share the row (180px at least) and wrap
65
- in a narrow window.
65
+ in a narrow window. Cards usually suit 2–4 options; that is a guide, not a
66
+ limit, and nothing cuts a fifth. Five short options (symptoms, say) read
67
+ better as a vertical `RadioGroup` list, and long options do too even when
68
+ there are three. Pick by how the options read, not by their count.
66
69
  - **Types.** `welcome` offers only Start; `done` drops Back and Cancel, fills
67
- the progress and turns the main action into Finish. The last step without
68
- `next-step-key` turns it into Apply.
70
+ the progress and turns the main action into Finish; `result` ends the flow
71
+ with an outcome the app sets ([Result](#result)); `progress` shows work the
72
+ app runs ([Progress](#progress)). The last step without `next-step-key`
73
+ turns the main action into Apply.
69
74
  - **Main action.** `next-label`, `next-disabled` and `:show-next="false"` (a step
70
75
  that moves on by itself or through its own choices, such as a row of cards)
71
76
  change it for one step. `:show-back="false"` hides Back.
@@ -98,9 +103,12 @@ const open = ref(false)
98
103
  The `#footer` slot replaces the footer's buttons and receives `nextStep`,
99
104
  `previousStep`, `finish`, `cancel`, `canGoPrevious`, `isLastStep`, `busy` and
100
105
  `stepKey`. Events: `next-step`, `previous-step` (`{ from, to }`), `finished`,
101
- `cancel`. A step guard (`pre-enter-next-step`, `pre-enter-previous-step`)
102
- returning `false` keeps the step; the main action shows a spinner while it
103
- runs. The step list does not navigate, so a guard cannot be skipped.
106
+ `cancel` and `navigation-error` ([Guards](#guards)). The step list does not
107
+ navigate, so a guard cannot be skipped.
108
+
109
+ `finished` means the user took Finish (or Apply); it does not mean the work
110
+ succeeded. Read the outcome from your own state, and do not run the work again
111
+ in a `finished` callback.
104
112
 
105
113
  A wizard fills the height its container gives it (`WizardDialog` and
106
114
  `<Dialog flush height="…">` give it one); on a page, set a height on its
@@ -117,6 +125,220 @@ there is no Back and nothing shifts. A welcome step offers Start alone; a done
117
125
  step offers Finish (and its own `#actions`). There is no Close in the footer:
118
126
  a `WizardDialog` closes from its header.
119
127
 
128
+ ## Result
129
+
130
+ A `type="result"` step ends the flow with an outcome: `result-tone` is
131
+ `success`, `warning`, `danger` or `neutral` (the default, which claims neither
132
+ success nor failure). A partial import, a failed connection test or a scan
133
+ that finished with warnings is a result, never a `done` step: `done` always
134
+ shows the success mark and its burst.
135
+
136
+ ```vue
137
+ <WizardStep
138
+ step-key="result"
139
+ type="result"
140
+ :result-tone="tone"
141
+ headline="Some items were not imported"
142
+ description="The imported items are kept; check why the others failed and try again"
143
+ >
144
+ <FindingList :items="findings" />
145
+ <template #actions>
146
+ <Button variant="ghost" kind="tool" @click="startAgain">Check again</Button>
147
+ </template>
148
+ </WizardStep>
149
+ ```
150
+
151
+ - The step shows its tone's mark (a tick, a warning sign, a cross or an info
152
+ mark) on its colour, read as "Succeeded", "Warning", "Failed" or "Done". It
153
+ pops in once, with no ring and no burst for any tone.
154
+ - Finish is the one main action, blue for every tone: a red mark does not
155
+ make the button red. Back and Cancel are gone; the header's close button and
156
+ the step's `#actions` stay. `next-label` renames Finish.
157
+ - The guide marks the step with the outcome: a warning or a failure is not
158
+ drawn or read as completed. The steps before it read as completed: that says
159
+ the user passed them, not that the backend did each part.
160
+ - A result step never moves on: `next-step-key` is ignored (with a warning
161
+ in development).
162
+ - Map the outcome in the app: a rollback that worked can be `neutral`, a
163
+ partial or unknown rollback `warning`, a failed one `danger`.
164
+
165
+ ## Progress
166
+
167
+ A `type="progress"` step shows work the app runs: a progress bar and a status
168
+ line. The wizard only draws them; the app starts, watches and ends the work,
169
+ and moves the wizard on (`v-model:active-step-key`) when the backend says the
170
+ work ended.
171
+
172
+ ```vue
173
+ <WizardStep
174
+ step-key="scanning"
175
+ type="progress"
176
+ headline="Checking"
177
+ :progress="total > 0
178
+ ? { mode: 'determinate', label: 'Items checked', value: checked, max: total, status: statusText }
179
+ : { mode: 'indeterminate', label: 'Getting status', status: statusText }"
180
+ stop-label="Stop watching"
181
+ @stop="stopWatching"
182
+ />
183
+ ```
184
+
185
+ - `progress` is `{ mode: 'indeterminate', label, status? }` while the total is
186
+ unknown, or `{ mode: 'determinate', label, value, max, valueLabel?, status? }`.
187
+ Without it the bar is indeterminate and named by the headline. `status` is
188
+ read politely when it changes.
189
+ - The bar is on its own tinted track (never grey) and has no stripes or
190
+ pattern; reduced motion stills it.
191
+ - Next and Back are hidden unless the step sets `:show-next="true"` or
192
+ `:show-back="true"` (for work that only reads). Back never undoes work that
193
+ changed data.
194
+ - `stop-label` adds a secondary button that emits `stop`; `stop-disabled`
195
+ disables it while the app waits for the backend. "Stop watching" only stops
196
+ the app looking; "Cancel task" is for a backend that can cancel, and the app
197
+ shows a cancelled result only once the backend confirms it.
198
+ - There is no timeout, retry count or auto-advance: time passing is not a
199
+ failure. `lazy` only mounts the step's content; it starts and stops nothing.
200
+
201
+ ## Guards
202
+
203
+ `pre-enter-next-step` and `pre-enter-previous-step` run before a move. A guard
204
+ gets `{ from, direction, signal }` and returns:
205
+
206
+ | Return | Effect |
207
+ | --- | --- |
208
+ | nothing | the move goes on as the step says |
209
+ | `false` | the step stays |
210
+ | `{ goTo: 'key' }` | the move goes to that step instead, this time only |
211
+
212
+ ```ts
213
+ async function checkAgain({ signal }: WizardGuardContext): Promise<WizardGuardResult> {
214
+ const status = await api.status({ signal })
215
+ if (status.needsAccess) return { goTo: 'access' }
216
+ return status.ready ? undefined : false
217
+ }
218
+ ```
219
+
220
+ - The main action shows a spinner while a guard runs; presses meanwhile are
221
+ ignored, so the guard runs once.
222
+ - A `goTo` is checked once the app's update has rendered, so a step the
223
+ guard mounts with `v-if` can be its target. It moves through the usual
224
+ `next-step` or `previous-step` event, `update:active-step-key` and focus.
225
+ The target's own guard does not run.
226
+ - A `goTo` that names no registered step (`unknown-step`) or the step itself
227
+ (`same-step`) keeps the step and emits `navigation-error`. A guard that
228
+ throws or rejects keeps the step and emits `navigation-error` with
229
+ `guard-rejected`, without the error's text: show your own message.
230
+ - `signal` aborts when the move no longer matters: the wizard left the step,
231
+ the app reset `active-step-key`, the `WizardDialog` closed (not while "Keep
232
+ editing" is asked) or the wizard unmounted. The spinner stops at once, and
233
+ a reply that comes later moves nothing and emits nothing. Pass `signal` to
234
+ your requests so they stop too.
235
+ - A step key is not a permission. The target step and the backend still check
236
+ what the user may do.
237
+
238
+ A guard written as `() => false | void` still works as before.
239
+
240
+ ## Recipes
241
+
242
+ These use the API above; none needs anything new.
243
+
244
+ ### Branches the backend decides
245
+
246
+ Steps need not all be known up front. A guard loads the branch, and a
247
+ `next-step-key` function reads it; the wizard reads `next-step-key` after the
248
+ guard. A step only some branches need can be mounted with `v-if`; it takes its
249
+ place in document order.
250
+
251
+ ```vue
252
+ <WizardStep step-key="inspect" headline="Check the target"
253
+ :pre-enter-next-step="loadBranch"
254
+ :next-step-key="() => branch.needsAccess ? 'access' : 'preview'" />
255
+ <WizardStep v-if="branch.needsAccess" step-key="access" headline="Allow access" next-step-key="preview" />
256
+ <WizardStep step-key="preview" headline="Confirm" />
257
+ ```
258
+
259
+ Map each backend kind to a step key in the app, and treat an unknown kind as
260
+ "cannot continue": never use a backend string as a key. The progress counts
261
+ the mounted steps, so mount the path the user takes, not every branch; when
262
+ the total is unknown, `progress-text` can say so.
263
+
264
+ ### Two equal ways on
265
+
266
+ Keep or roll back, replace or keep: put the choices in one `RadioGroup` (cards
267
+ when they need an icon and a line) and let one main action confirm the chosen
268
+ one. Its `next-label` follows the choice; a choice never acts by itself, so
269
+ moving through the options with the arrow keys does nothing else. The footer
270
+ keeps one blue button. A choice that destroys data asks in a confirmation
271
+ dialog first, whose confirm button is the only red one.
272
+
273
+ ```vue
274
+ <WizardStep step-key="decision" headline="Choose what to do"
275
+ :show-back="false" :next-disabled="!decision"
276
+ :next-label="decision === 'rollback' ? 'Roll back' : 'Keep changes'"
277
+ :next-step-key="() => decision === 'rollback' ? 'working' : 'result'"
278
+ :pre-enter-next-step="confirmDecision">
279
+ <RadioGroup v-model="decision" variant="card" orientation="horizontal" :options="allowedDecisions" />
280
+ </WizardStep>
281
+ ```
282
+
283
+ Offer only the choices the backend allows: an interrupted run has no "keep".
284
+
285
+ ### Handing over to another wizard
286
+
287
+ The parent opens one wizard at a time. To hand over (a diagnosis opening a
288
+ fix): check what the source passes, stop the source's pending work, close the
289
+ source, then set the target's props and open it. Do not rely on two
290
+ `v-model:open` flips in one tick; mount the two exclusively (`v-if` on one
291
+ state) so only one dialog holds the focus. A handover is not the source's
292
+ Finish and not a rollback, and secrets do not travel in its props.
293
+
294
+ ```ts
295
+ type WizardRequest = { kind: 'diagnose' } | { kind: 'setup'; intent: 'send' | 'receive' } | undefined
296
+ ```
297
+
298
+ ### Watching work
299
+
300
+ For a [progress](#progress) step the app watches the backend:
301
+
302
+ 1. Watch only while the wizard is open on that step. Leaving, closing,
303
+ unmounting or reopening ends the round: clear its timer and abort its
304
+ request.
305
+ 2. One request at a time: schedule the next when the last ends, not with
306
+ `setInterval`. Follow the backend's retry-after; on errors back off slowly
307
+ (from about a second to 15 or 30 seconds). These are a schedule, not a
308
+ deadline.
309
+ 3. After every `await`, check that the round, the open state and the step are
310
+ still the same before writing anything.
311
+ 4. A network error shows "Status not up to date" with a way to check again and
312
+ keeps the last progress. Only the backend's own failed or interrupted state
313
+ leads to a failure result.
314
+ 5. Reopening reads the run from the backend and resumes; it does not apply
315
+ again.
316
+
317
+ ### Opening another DSM app
318
+
319
+ When a step needs the user to finish something in another app, open it with
320
+ the platform SDK's app launcher (it knows the app's verified ID; a package
321
+ name is not an app ID), and always show the path in words as well, for a host
322
+ that cannot open it. A secondary button opens it; the step's main action is
323
+ "Check again", whose guard reads the state again. Coming back to the wizard
324
+ only triggers a check: it is never a success by itself.
325
+
326
+ ```vue
327
+ <WizardStep step-key="external" headline="Finish in the other app"
328
+ next-label="Check again" :pre-enter-next-step="checkAgain">
329
+ <p>When you are done there, come back and check again</p>
330
+ <Button variant="secondary" kind="tool" @click="openApp">Open the app</Button>
331
+ <p v-if="launchUnavailable">Open it from the DSM main menu</p>
332
+ </WizardStep>
333
+ ```
334
+
335
+ ### Not provided
336
+
337
+ The wizard has no backend step schema or runner, no timeout or retry settings
338
+ for work, no two-primary footer, no card count option, no cross-wizard
339
+ navigation and no launcher of its own. These stay with the app (or the
340
+ platform SDK) on purpose.
341
+
120
342
  ## Modal
121
343
 
122
344
  `WizardDialog` opens like a DSM modal window, in the app (app-local, see
@@ -131,8 +353,16 @@ a `WizardDialog` closes from its header.
131
353
  step title) shows a ring only after a key, never after a click.
132
354
 
133
355
  These are `Dialog` props (`scrim="light"`, `:close-on-outside="false"`,
134
- `:header-divider="false"`), so a dialog of your own around a `Wizard` can
135
- open the same way.
356
+ `:header-divider="false"`, `presentation="modal"`), so a dialog of your own
357
+ around a `Wizard` can open the same way.
358
+
359
+ On a phone `WizardDialog` stays a centred window, as a DSM wizard does: the
360
+ phone's dialog corner, the phone's dim scrim, the same fixed header and
361
+ footer. It is as tall as its step, up to the wizard's height inside the
362
+ phone's safe area; only a longer step scrolls, between the header and the
363
+ footer. `presentation="adaptive"` keeps the bottom sheet instead, for an app
364
+ that wants its earlier phone look; other dialogs are bottom sheets on a phone
365
+ as before. The "Discard changes?" question is always a centred window.
136
366
 
137
367
  ## Leaving with input
138
368
 
@@ -164,6 +394,7 @@ in every built-in locale.
164
394
  - **Motion.** A step fades in from 10px on the side it comes from and its
165
395
  title fades in; the progress segments ease to their new state; the done mark
166
396
  pops with a ring and a short burst. Reduced motion turns all of it off.
167
- - **Size.** In a phone-width window the dialog is a bottom sheet.
397
+ - **Size.** In a phone-width window the dialog stays a centred window with a
398
+ margin around it; `presentation="adaptive"` makes it a bottom sheet.
168
399
  - **Theme.** Colours are the theme's roles, so the wizard follows the accent
169
400
  and the dark theme.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/ui",
3
- "version": "0.25.0",
3
+ "version": "0.25.1",
4
4
  "description": "Shared Vue 3 UI component library with a DSM 7 inspired application theme",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -60,64 +60,6 @@
60
60
  "./themes/dsm7-embedded-reset.css": "./dist/themes/dsm7-embedded-reset.css",
61
61
  "./themes/dsm7-embedded-theme.css": "./dist/themes/dsm7-embedded-theme.css"
62
62
  },
63
- "peerDependencies": {
64
- "vue": "^3.5.0"
65
- },
66
- "dependencies": {
67
- "@floating-ui/dom": "1.8.0",
68
- "@internationalized/date": "3.12.4",
69
- "@json-render/core": "0.21.0",
70
- "@json-render/vue": "0.21.0",
71
- "@lucide/vue": "1.48.0",
72
- "@tiptap/core": "3.32.1",
73
- "@tiptap/extension-bubble-menu": "3.32.1",
74
- "@tiptap/extension-mention": "3.32.1",
75
- "@tiptap/extensions": "3.32.1",
76
- "@tiptap/pm": "3.32.1",
77
- "@tiptap/starter-kit": "3.32.1",
78
- "@tiptap/suggestion": "3.32.1",
79
- "@tiptap/vue-3": "3.32.1",
80
- "zod": "^4.6.5"
81
- },
82
- "devDependencies": {
83
- "@eslint/js": "10.0.1",
84
- "@histoire/plugin-vue": "1.0.0-beta.1",
85
- "@tailwindcss/vite": "4.3.3",
86
- "@tanstack/vue-virtual": "3.13.39",
87
- "@vitejs/plugin-vue": "6.0.9",
88
- "@vue/test-utils": "2.5.1",
89
- "@vueuse/core": "14.4.0",
90
- "eslint": "10.11.0",
91
- "eslint-plugin-vue": "10.11.1",
92
- "flexsearch": "0.8.212",
93
- "globals": "17.12.0",
94
- "histoire": "1.0.0-beta.1",
95
- "jsdom": "30.1.1",
96
- "playwright": "1.58.2",
97
- "reka-ui": "2.11.0",
98
- "tailwindcss": "4.3.3",
99
- "typescript": "5.9.3",
100
- "typescript-eslint": "8.71.0",
101
- "vite": "7.3.6",
102
- "vite-plugin-dts": "5.1.1",
103
- "vitest": "5.0.2",
104
- "vscode-oniguruma": "2.0.1",
105
- "vscode-textmate": "9.3.2",
106
- "vue": "3.5.43",
107
- "vue-eslint-parser": "10.4.1",
108
- "vue-tsc": "3.3.11"
109
- },
110
- "engines": {
111
- "node": ">=20"
112
- },
113
- "config": {
114
- "bundledRuntime": {
115
- "@tanstack/vue-virtual": "3.13.39",
116
- "@vueuse/core": "14.4.0",
117
- "reka-ui": "2.11.0"
118
- }
119
- },
120
- "homepage": "https://www.varvis.me/docs/",
121
63
  "scripts": {
122
64
  "check:docs": "node --test scripts/check-doc-versions.test.mjs && node scripts/check-doc-versions.mjs",
123
65
  "dev": "vite build --watch",
@@ -143,6 +85,7 @@
143
85
  "check:motion": "node scripts/check-motion.mjs",
144
86
  "check:topology": "node scripts/check-topology.mjs",
145
87
  "check:wizard": "node scripts/check-wizard.mjs",
88
+ "check:press": "node scripts/check-press.mjs",
146
89
  "check:edges": "node scripts/check-edges.mjs",
147
90
  "check:data-grid": "node scripts/check-data-grid.mjs",
148
91
  "check:truncation": "node scripts/check-truncation.mjs",
@@ -175,5 +118,70 @@
175
118
  "check:layout": "node scripts/check-layout.mjs",
176
119
  "release:smoke": "node scripts/release-smoke.mjs",
177
120
  "check:browser-install": "playwright install chromium webkit"
178
- }
179
- }
121
+ },
122
+ "peerDependencies": {
123
+ "vue": "^3.5.0"
124
+ },
125
+ "dependencies": {
126
+ "@floating-ui/dom": "1.8.0",
127
+ "@internationalized/date": "3.12.4",
128
+ "@json-render/core": "0.21.0",
129
+ "@json-render/vue": "0.21.0",
130
+ "@lucide/vue": "1.48.0",
131
+ "@tiptap/core": "3.32.1",
132
+ "@tiptap/extension-bubble-menu": "3.32.1",
133
+ "@tiptap/extension-mention": "3.32.1",
134
+ "@tiptap/extensions": "3.32.1",
135
+ "@tiptap/pm": "3.32.1",
136
+ "@tiptap/starter-kit": "3.32.1",
137
+ "@tiptap/suggestion": "3.32.1",
138
+ "@tiptap/vue-3": "3.32.1",
139
+ "zod": "^4.6.5"
140
+ },
141
+ "devDependencies": {
142
+ "@eslint/js": "10.0.1",
143
+ "@histoire/plugin-vue": "1.0.0-beta.1",
144
+ "@tailwindcss/vite": "4.3.3",
145
+ "@tanstack/vue-virtual": "3.13.39",
146
+ "@vitejs/plugin-vue": "6.0.9",
147
+ "@vue/test-utils": "2.5.1",
148
+ "@vueuse/core": "14.4.0",
149
+ "eslint": "10.11.0",
150
+ "eslint-plugin-vue": "10.11.1",
151
+ "flexsearch": "0.8.212",
152
+ "globals": "17.12.0",
153
+ "histoire": "1.0.0-beta.1",
154
+ "jsdom": "30.1.1",
155
+ "playwright": "1.58.2",
156
+ "reka-ui": "2.11.0",
157
+ "tailwindcss": "4.3.3",
158
+ "typescript": "5.9.3",
159
+ "typescript-eslint": "8.71.0",
160
+ "vite": "7.3.6",
161
+ "vite-plugin-dts": "5.1.1",
162
+ "vitest": "5.0.2",
163
+ "vscode-oniguruma": "2.0.1",
164
+ "vscode-textmate": "9.3.2",
165
+ "vue": "3.5.43",
166
+ "vue-eslint-parser": "10.4.1",
167
+ "vue-tsc": "3.3.11"
168
+ },
169
+ "engines": {
170
+ "node": ">=20"
171
+ },
172
+ "packageManager": "pnpm@10.33.2",
173
+ "pnpm": {
174
+ "onlyBuiltDependencies": [
175
+ "esbuild",
176
+ "vue-demi"
177
+ ]
178
+ },
179
+ "config": {
180
+ "bundledRuntime": {
181
+ "@tanstack/vue-virtual": "3.13.39",
182
+ "@vueuse/core": "14.4.0",
183
+ "reka-ui": "2.11.0"
184
+ }
185
+ },
186
+ "homepage": "https://www.varvis.me/docs/"
187
+ }