nuxt-ui-elements 0.1.41 → 0.2.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.
package/README.md CHANGED
@@ -7,11 +7,9 @@
7
7
 
8
8
  **A growing collection of components and utilities that extend [@nuxt/ui](https://ui.nuxt.com) with enhanced functionality.**
9
9
 
10
- This module extends Nuxt UI with additional components and utilities designed to integrate with Nuxt UI's design system.
11
-
12
10
  > **Early Development Notice**: This project is in early development. APIs, component interfaces, and utilities are subject to change in future releases. Please use with caution in production environments.
13
11
 
14
- - [✨  Release Notes](/CHANGELOG.md)
12
+ - [Release Notes](/CHANGELOG.md)
15
13
 
16
14
  ## Features
17
15
 
@@ -21,26 +19,20 @@ This module extends Nuxt UI with additional components and utilities designed to
21
19
  - 🔄 **Auto-import** - Components and composables are automatically available
22
20
  - 🎯 **TypeScript** - Full type safety out of the box
23
21
  - 🌙 **Dark Mode** - Automatic theme switching compatible with Nuxt UI
24
- - 🔀 **Vue Flow Integration** - Themed wrapper components for interactive flowcharts and diagrams
25
22
 
26
23
  ## Requirements
27
24
 
28
25
  This module requires [@nuxt/ui](https://ui.nuxt.com) v4.0.0 or higher.
29
26
 
30
- ## Installation
27
+ ## Quick Setup
28
+
29
+ Install the module:
31
30
 
32
31
  ```bash
33
- # pnpm
34
32
  pnpm add nuxt-ui-elements
35
-
36
- # npm
37
- npm install nuxt-ui-elements
38
-
39
- # yarn
40
- yarn add nuxt-ui-elements
41
33
  ```
42
34
 
43
- Add the module to your `nuxt.config.ts`:
35
+ Add it to your `nuxt.config.ts`:
44
36
 
45
37
  ```typescript
46
38
  export default defineNuxtConfig({
@@ -56,407 +48,10 @@ Import the module's CSS in your main CSS file (e.g., `assets/css/main.css`):
56
48
  @import "nuxt-ui-elements";
57
49
  ```
58
50
 
59
- That's it! You can now use Nuxt UI Elements in your Nuxt app
51
+ That's it! Components and composables are automatically available in your Nuxt app.
60
52
 
61
53
  > **Note:** The CSS import is required for Tailwind v4 to properly scan and generate styles from the component themes.
62
54
 
63
- ## Usage
64
-
65
- Components and composables are automatically imported. Standard utilities (`#std`) are available via explicit imports.
66
-
67
- ### Dialog Components
68
-
69
- The module provides two dialog components via the `useDialog` composable: Alert and Confirm dialogs.
70
-
71
- #### Alert Dialog
72
-
73
- Display informational messages to users:
74
-
75
- ```vue
76
- <script setup>
77
- const { alert } = useDialog()
78
-
79
- function showAlert() {
80
- alert({
81
- title: 'Success!',
82
- description: 'Your changes have been saved.',
83
- icon: 'i-lucide-check-circle',
84
- label: 'Got it',
85
- color: 'success'
86
- })
87
- }
88
- </script>
89
-
90
- <template>
91
- <UButton @click="showAlert">Show Alert</UButton>
92
- </template>
93
- ```
94
-
95
- **Alert Dialog API:**
96
-
97
- | Property | Type | Default | Description |
98
- |----------|------|---------|-------------|
99
- | `title` | `string` | `''` | Dialog title |
100
- | `description` | `string` | `''` | Dialog description/message |
101
- | `icon` | `string` | `undefined` | Icon name (e.g., 'i-lucide-info') |
102
- | `label` | `string` | `'Ok'` | Dismiss button label |
103
- | `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'neutral'` | `'neutral'` | Color theme |
104
- | `variant` | `'solid' \| 'outline'` | `'solid'` | Dialog variant |
105
- | `onDismiss` | `() => void \| Promise<void>` | `() => {}` | Callback when dismissed |
106
- | `ui` | `object` | `{}` | Custom UI classes override |
107
-
108
- #### Confirm Dialog
109
-
110
- Request user confirmation with async support:
111
-
112
- ```vue
113
- <script setup>
114
- const { confirm } = useDialog()
115
-
116
- async function handleDelete() {
117
- confirm({
118
- title: 'Delete Item',
119
- description: 'Are you sure? This action cannot be undone.',
120
- confirmLabel: 'Delete',
121
- dismissLabel: 'Cancel',
122
- color: 'error',
123
- onConfirm: async () => {
124
- // Async operations are supported
125
- await deleteItem()
126
- // Dialog shows loading state and success feedback automatically
127
- },
128
- onDismiss: () => {
129
- console.log('User cancelled')
130
- }
131
- })
132
- }
133
- </script>
134
-
135
- <template>
136
- <UButton @click="handleDelete">Delete</UButton>
137
- </template>
138
- ```
139
-
140
- **Confirm Dialog API:**
141
-
142
- | Property | Type | Default | Description |
143
- |----------|------|---------|-------------|
144
- | `title` | `string` | `''` | Dialog title |
145
- | `description` | `string` | `''` | Dialog description/message |
146
- | `icon` | `boolean` | `true` | Show icon (auto-selected based on color) |
147
- | `confirmLabel` | `string` | `'Yes'` | Confirm button label |
148
- | `dismissLabel` | `string` | `'No'` | Dismiss button label |
149
- | `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'neutral'` | `'neutral'` | Color theme |
150
- | `variant` | `'solid' \| 'outline'` | `'solid'` | Dialog variant |
151
- | `close` | `boolean` | `false` | Show close button in header |
152
- | `onConfirm` | `() => void \| Promise<void>` | `() => {}` | Callback when confirmed (supports async) |
153
- | `onDismiss` | `() => void \| Promise<void>` | `() => {}` | Callback when dismissed |
154
- | `ui` | `object` | `{}` | Custom UI classes override |
155
-
156
- **Async Support**: When `onConfirm` returns a Promise, the dialog automatically shows loading state and displays success/error feedback before closing.
157
-
158
- ### Flow Components
159
-
160
- Themed wrapper components for [Vue Flow](https://vueflow.dev/), providing interactive flowcharts and node-based diagrams with Nuxt UI theming integration.
161
-
162
- #### Prerequisites
163
-
164
- Flow components require the `@vue-flow` packages. Install them alongside `nuxt-ui-elements`:
165
-
166
- ```bash
167
- pnpm add @vue-flow/core @vue-flow/background @vue-flow/controls @vue-flow/minimap
168
- ```
169
-
170
- #### Flow
171
-
172
- The main container component that wraps Vue Flow with Nuxt UI theming and SSR safety via `<ClientOnly>`.
173
-
174
- ```vue
175
- <script setup>
176
- const nodes = ref([
177
- { id: '1', type: 'custom', position: { x: 0, y: 0 }, data: { label: 'Start' } },
178
- { id: '2', type: 'custom', position: { x: 250, y: 100 }, data: { label: 'Process' } },
179
- ])
180
-
181
- const edges = ref([
182
- { id: 'e1-2', source: '1', target: '2', animated: true },
183
- ])
184
- </script>
185
-
186
- <template>
187
- <UEFlow :nodes="nodes" :edges="edges" @connect="onConnect">
188
- <template #node-custom="{ data }">
189
- <UEFlowNode :label="data.label" color="primary" variant="outline">
190
- <UEFlowHandle type="target" position="left" />
191
- <UEFlowHandle type="source" position="right" />
192
- </UEFlowNode>
193
- </template>
194
-
195
- <UEFlowBackground />
196
- <UEFlowControls />
197
- <UEFlowMiniMap />
198
- </UEFlow>
199
- </template>
200
- ```
201
-
202
- **Flow API:**
203
-
204
- | Property | Type | Default | Description |
205
- |----------|------|---------|-------------|
206
- | `nodes` | `Node[]` | `[]` | Array of node objects |
207
- | `edges` | `Edge[]` | `[]` | Array of edge objects |
208
- | `nodeTypes` | `Record<string, any>` | `undefined` | Map of custom node type components |
209
- | `edgeTypes` | `Record<string, any>` | `undefined` | Map of custom edge type components |
210
- | `fitViewOnInit` | `boolean` | `true` | Fit view on initialization |
211
- | `minZoom` | `number` | `0.2` | Minimum zoom level |
212
- | `maxZoom` | `number` | `4` | Maximum zoom level |
213
- | `nodesDraggable` | `boolean` | `true` | Whether nodes are draggable |
214
- | `nodesConnectable` | `boolean` | `true` | Whether nodes are connectable |
215
- | `elementsSelectable` | `boolean` | `true` | Whether elements are selectable |
216
- | `connectionMode` | `ConnectionMode` | `undefined` | Connection mode |
217
- | `defaultEdgeOptions` | `Record<string, any>` | `undefined` | Default options for edges |
218
- | `ui` | `object` | `{}` | Custom UI classes override |
219
-
220
- **Events:**
221
-
222
- | Event | Payload | Description |
223
- |-------|---------|-------------|
224
- | `update:nodes` | `Node[]` | Emitted when nodes change |
225
- | `update:edges` | `Edge[]` | Emitted when edges change |
226
- | `nodeClick` | `event` | Emitted on node click |
227
- | `edgeClick` | `event` | Emitted on edge click |
228
- | `paneClick` | `event` | Emitted on pane click |
229
- | `connect` | `params` | Emitted when a connection is made |
230
-
231
- **Slots:** All Vue Flow slots are forwarded, including custom node/edge type slots (e.g., `#node-custom`).
232
-
233
- #### FlowNode
234
-
235
- A styled node component with color and variant theming. Use inside custom node type slots.
236
-
237
- ```vue
238
- <template #node-custom="{ data, selected }">
239
- <UEFlowNode :label="data.label" color="success" variant="soft" :selected="selected">
240
- <UEFlowHandle type="target" position="top" />
241
- <template #default>
242
- <p>Custom content here</p>
243
- </template>
244
- <UEFlowHandle type="source" position="bottom" />
245
- </UEFlowNode>
246
- </template>
247
- ```
248
-
249
- **FlowNode API:**
250
-
251
- | Property | Type | Default | Description |
252
- |----------|------|---------|-------------|
253
- | `label` | `string` | `undefined` | Node label text |
254
- | `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'neutral'` | `'primary'` | Theme color |
255
- | `variant` | `'solid' \| 'outline' \| 'soft' \| 'subtle'` | `'outline'` | Visual variant |
256
- | `selected` | `boolean` | `false` | Whether the node is selected (adds ring indicator) |
257
- | `ui` | `object` | `{}` | Custom UI classes override |
258
-
259
- **Slots:**
260
-
261
- | Slot | Description |
262
- |------|-------------|
263
- | `default` | Custom content rendered below the label |
264
-
265
- #### FlowHandle
266
-
267
- A themed connection handle for nodes. Place inside `FlowNode` to define source/target connection points.
268
-
269
- ```vue
270
- <UEFlowNode label="My Node" color="primary">
271
- <UEFlowHandle type="target" position="top" color="primary" />
272
- <UEFlowHandle type="source" position="bottom" color="primary" :connected="true" />
273
- </UEFlowNode>
274
- ```
275
-
276
- **FlowHandle API:**
277
-
278
- | Property | Type | Default | Description |
279
- |----------|------|---------|-------------|
280
- | `type` | `'source' \| 'target'` | **(required)** | Handle type |
281
- | `position` | `Position \| 'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Handle position on the node |
282
- | `id` | `string` | `undefined` | Handle ID (required when a node has multiple handles of the same type) |
283
- | `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'neutral'` | `'primary'` | Theme color |
284
- | `connected` | `boolean` | `false` | Whether a connection is active (fills the handle with color) |
285
- | `ui` | `object` | `{}` | Custom UI classes override |
286
-
287
- #### FlowBackground
288
-
289
- A themed background pattern for the flow canvas.
290
-
291
- ```vue
292
- <UEFlow :nodes="nodes" :edges="edges">
293
- <!-- Dot pattern (default) -->
294
- <UEFlowBackground />
295
-
296
- <!-- Line pattern with custom settings -->
297
- <UEFlowBackground pattern="lines" :gap="30" :size="2" color="#ccc" />
298
- </UEFlow>
299
- ```
300
-
301
- **FlowBackground API:**
302
-
303
- | Property | Type | Default | Description |
304
- |----------|------|---------|-------------|
305
- | `pattern` | `'dots' \| 'lines'` | `'dots'` | Background pattern |
306
- | `gap` | `number \| number[]` | `20` | Pattern gap spacing |
307
- | `size` | `number` | `1` | Pattern element size |
308
- | `color` | `string` | `undefined` | Pattern color |
309
- | `lineWidth` | `number` | `undefined` | Line width (only for `lines` pattern) |
310
- | `ui` | `object` | `{}` | Custom UI classes override |
311
-
312
- #### FlowControls
313
-
314
- A themed control panel for zoom, fit view, and interactivity toggles.
315
-
316
- ```vue
317
- <UEFlow :nodes="nodes" :edges="edges">
318
- <!-- Default controls (all visible) -->
319
- <UEFlowControls />
320
-
321
- <!-- Only zoom and fit view -->
322
- <UEFlowControls :show-interactive="false" position="top-left" />
323
- </UEFlow>
324
- ```
325
-
326
- **FlowControls API:**
327
-
328
- | Property | Type | Default | Description |
329
- |----------|------|---------|-------------|
330
- | `showZoom` | `boolean` | `true` | Show zoom in/out buttons |
331
- | `showFitView` | `boolean` | `true` | Show fit-view button |
332
- | `showInteractive` | `boolean` | `true` | Show interactive toggle |
333
- | `fitViewParams` | `FitViewParams` | `undefined` | Parameters for fit view action |
334
- | `position` | `PanelPositionType` | `'bottom-left'` | Panel position on the canvas |
335
- | `ui` | `object` | `{}` | Custom UI classes override |
336
-
337
- **Slots:**
338
-
339
- | Slot | Description |
340
- |------|-------------|
341
- | `default` | Additional custom controls |
342
-
343
- #### FlowMiniMap
344
-
345
- A themed minimap for navigating large flow diagrams.
346
-
347
- ```vue
348
- <UEFlow :nodes="nodes" :edges="edges">
349
- <!-- Default minimap -->
350
- <UEFlowMiniMap />
351
-
352
- <!-- Customized minimap -->
353
- <UEFlowMiniMap
354
- :pannable="true"
355
- :zoomable="true"
356
- position="top-right"
357
- :node-border-radius="8"
358
- />
359
- </UEFlow>
360
- ```
361
-
362
- **FlowMiniMap API:**
363
-
364
- | Property | Type | Default | Description |
365
- |----------|------|---------|-------------|
366
- | `pannable` | `boolean` | `true` | Enable drag to pan the viewport |
367
- | `zoomable` | `boolean` | `true` | Enable scroll to zoom the viewport |
368
- | `position` | `PanelPositionType` | `'bottom-right'` | Panel position on the canvas |
369
- | `nodeColor` | `string` | `undefined` | Node fill color in the minimap |
370
- | `nodeStrokeColor` | `string` | `undefined` | Node stroke color in the minimap |
371
- | `nodeBorderRadius` | `number` | `4` | Node border radius in the minimap |
372
- | `maskColor` | `string` | `undefined` | Viewport mask overlay color |
373
- | `width` | `number` | `undefined` | Minimap width |
374
- | `height` | `number` | `undefined` | Minimap height |
375
- | `ui` | `object` | `{}` | Custom UI classes override |
376
-
377
- ## Standard Utilities (`#std`)
378
-
379
- The module provides tree-shakeable utility functions via the `#std` alias. These are **not** auto-imported and must be explicitly imported.
380
-
381
- ### Date Utilities
382
-
383
- Comprehensive date manipulation built on `@internationalized/date`. Import the entire module or individual functions:
384
-
385
- ```typescript
386
- import std from '#std'
387
-
388
- const nextMonth = std.date.add(std.date.today(), 1, 'month')
389
- const formatted = std.date.format(new Date(), 'YYYY-MM-DD')
390
-
391
- // Or import individual functions
392
- import { add, format, today, relative } from '#std/date'
393
-
394
- // Add/subtract time
395
- const nextMonth = add(today(), 1, 'month')
396
- const lastWeek = subtract(new Date(), 7, 'day')
397
-
398
- // Format dates (Day.js-compatible tokens)
399
- format(new Date(), 'YYYY-MM-DD') // "2024-01-15"
400
- format(new Date(), 'MMMM D, YYYY') // "January 15, 2024"
401
- format(new Date(), 'MMM DD, YYYY h:mm A') // "Jan 15, 2024 3:30 PM"
402
-
403
- // Relative time
404
- relative(someDate) // "2 days ago" or "in 3 months"
405
-
406
- // Date comparisons
407
- isBefore(date1, date2)
408
- isAfter(date1, date2)
409
- isSame(date1, date2)
410
- isBetween(date, startDate, endDate)
411
-
412
- // Date manipulation
413
- set(someDate, { day: 15, month: 3 })
414
- startOf(someDate, 'month')
415
- endOf(someDate, 'week')
416
-
417
- // Calculate differences
418
- diff(date1, date2, 'days') // number of days between dates
419
-
420
- // Conversions
421
- toDate(dateValue) // Convert to JavaScript Date
422
- asCalendarDate(date) // Date without time
423
- asCalendarDateTime(date) // Date with time, no timezone
424
- asZonedDateTime(date, 'UTC') // Date with timezone
425
-
426
- // Utilities
427
- today() // Current date
428
- now() // Current date and time
429
- parse('2024-01-15') // Parse date string
430
- ```
431
-
432
- **Available Functions:**
433
-
434
- | Function | Description |
435
- |----------|-------------|
436
- | `add(date, amount, unit)` | Add time to a date |
437
- | `subtract(date, amount, unit)` | Subtract time from a date |
438
- | `set(date, values)` | Set specific date/time values |
439
- | `format(date, formatString, locale?)` | Format date with Day.js tokens |
440
- | `relative(date, locale?)` | Get relative time string |
441
- | `toDate(input, timeZone?)` | Convert to JavaScript Date |
442
- | `asCalendarDate(input)` | Convert to date without time |
443
- | `asCalendarDateTime(input)` | Convert to date with time |
444
- | `asZonedDateTime(input, timeZone?)` | Convert to date with timezone |
445
- | `isBefore(date1, date2)` | Check if date1 is before date2 |
446
- | `isAfter(date1, date2)` | Check if date1 is after date2 |
447
- | `isSame(date1, date2)` | Check if dates are equal |
448
- | `isBetween(date, start, end, inclusive?)` | Check if date is in range |
449
- | `diff(date1, date2, unit?)` | Calculate difference between dates |
450
- | `startOf(date, unit, locale?)` | Get start of time period |
451
- | `endOf(date, unit, locale?)` | Get end of time period |
452
- | `today(timeZone?)` | Get today's date |
453
- | `now(timeZone?)` | Get current date and time |
454
- | `parse(dateString)` | Parse YYYY-MM-DD string |
455
-
456
- Plus re-exported utilities: `isSameDay`, `isSameMonth`, `isSameYear`, `isToday`, `isWeekend`, `getDayOfWeek`, `getWeeksInMonth`, `getLocalTimeZone`
457
-
458
- **Tree-shakeable**: All utilities under `#std` are tree-shakeable. Only imported functions will be included in your bundle, whether you import the entire module or individual functions.
459
-
460
55
  ## Contribution
461
56
 
462
57
  <details>
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-ui-elements",
3
3
  "configKey": "uiElements",
4
- "version": "0.1.41",
4
+ "version": "0.2.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { addTemplate, defineNuxtModule, createResolver, addImportsDir, addComponentsDir } from '@nuxt/kit';
1
+ import { addTemplate, defineNuxtModule, createResolver, addImportsDir, addComponentsDir, tryResolveModule } from '@nuxt/kit';
2
2
  import { kebabCase } from 'scule';
3
3
 
4
4
  const dialogConfirm = (options) => ({
@@ -481,7 +481,7 @@ const module$1 = defineNuxtModule({
481
481
  moduleDependencies: {
482
482
  "@nuxt/ui": {}
483
483
  },
484
- setup(options, nuxt) {
484
+ async setup(options, nuxt) {
485
485
  const resolver = createResolver(import.meta.url);
486
486
  const uiOptions = nuxt.options.ui;
487
487
  const themeColors = uiOptions?.theme?.colors || ["primary", "secondary", "success", "info", "warning", "error"];
@@ -498,39 +498,25 @@ const module$1 = defineNuxtModule({
498
498
  nuxt.options.alias["#ui-elements"] = resolver.resolve("./runtime");
499
499
  addComponentsDir({
500
500
  path: resolver.resolve("./runtime/components"),
501
- prefix: options.prefix
501
+ prefix: options.prefix,
502
+ ignore: ["**/flow/**"]
502
503
  });
503
- try {
504
- const vueFlowCorePath = resolver.resolve("@vue-flow/core");
505
- if (vueFlowCorePath) {
506
- nuxt.options.css.push("@vue-flow/core/dist/style.css");
507
- nuxt.options.css.push("@vue-flow/core/dist/theme-default.css");
508
- nuxt.options.build.transpile.push("@vue-flow/core");
509
- }
510
- } catch {
504
+ const moduleDirs = nuxt.options.modulesDir;
505
+ if (await tryResolveModule("@vue-flow/core", moduleDirs)) {
506
+ nuxt.options.css.push("@vue-flow/core/dist/style.css");
507
+ nuxt.options.css.push("@vue-flow/core/dist/theme-default.css");
508
+ nuxt.options.build.transpile.push("@vue-flow/core");
511
509
  }
512
- try {
513
- const bgPath = resolver.resolve("@vue-flow/background");
514
- if (bgPath) {
515
- nuxt.options.build.transpile.push("@vue-flow/background");
516
- }
517
- } catch {
510
+ if (await tryResolveModule("@vue-flow/background", moduleDirs)) {
511
+ nuxt.options.build.transpile.push("@vue-flow/background");
518
512
  }
519
- try {
520
- const controlsPath = resolver.resolve("@vue-flow/controls");
521
- if (controlsPath) {
522
- nuxt.options.css.push("@vue-flow/controls/dist/style.css");
523
- nuxt.options.build.transpile.push("@vue-flow/controls");
524
- }
525
- } catch {
513
+ if (await tryResolveModule("@vue-flow/controls", moduleDirs)) {
514
+ nuxt.options.css.push("@vue-flow/controls/dist/style.css");
515
+ nuxt.options.build.transpile.push("@vue-flow/controls");
526
516
  }
527
- try {
528
- const minimapPath = resolver.resolve("@vue-flow/minimap");
529
- if (minimapPath) {
530
- nuxt.options.css.push("@vue-flow/minimap/dist/style.css");
531
- nuxt.options.build.transpile.push("@vue-flow/minimap");
532
- }
533
- } catch {
517
+ if (await tryResolveModule("@vue-flow/minimap", moduleDirs)) {
518
+ nuxt.options.css.push("@vue-flow/minimap/dist/style.css");
519
+ nuxt.options.build.transpile.push("@vue-flow/minimap");
534
520
  }
535
521
  }
536
522
  });
@@ -24,7 +24,7 @@ const {
24
24
  color: { type: null, required: false },
25
25
  variant: { type: null, required: false },
26
26
  onDismiss: { type: Function, required: false },
27
- ui: { type: Object, required: false }
27
+ ui: { type: null, required: false }
28
28
  });
29
29
  const emits = defineEmits(["update:open", "close"]);
30
30
  const ui = computed(
@@ -31,7 +31,7 @@ const {
31
31
  close: { type: Boolean, required: false },
32
32
  onConfirm: { type: Function, required: false },
33
33
  onDismiss: { type: Function, required: false },
34
- ui: { type: Object, required: false }
34
+ ui: { type: null, required: false }
35
35
  });
36
36
  const emits = defineEmits(["update:open", "close"]);
37
37
  const isLoading = ref(false);
@@ -2,6 +2,9 @@ import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow";
3
3
  import type { ComponentConfig } from "../types/index.js";
4
4
  import type { Node, Edge, ConnectionMode } from "@vue-flow/core";
5
+ import type { FlowBackgroundProps } from "./flow/FlowBackground.vue.js";
6
+ import type { FlowControlsProps } from "./flow/FlowControls.vue.js";
7
+ import type { FlowMiniMapProps } from "./flow/FlowMiniMap.vue.js";
5
8
  type Flow = ComponentConfig<typeof theme, AppConfig, "flow">;
6
9
  export interface FlowProps {
7
10
  /** Array of node objects */
@@ -28,6 +31,12 @@ export interface FlowProps {
28
31
  connectionMode?: ConnectionMode;
29
32
  /** Default edge options */
30
33
  defaultEdgeOptions?: Record<string, any>;
34
+ /** Show background (true for defaults, or pass config object) */
35
+ background?: boolean | Omit<FlowBackgroundProps, "ui">;
36
+ /** Show controls (true for defaults, or pass config object) */
37
+ controls?: boolean | Omit<FlowControlsProps, "ui">;
38
+ /** Show minimap (true for defaults, or pass config object) */
39
+ minimap?: boolean | Omit<FlowMiniMapProps, "ui">;
31
40
  /** Theme slot overrides */
32
41
  ui?: Flow["slots"];
33
42
  }
@@ -39,6 +48,9 @@ export interface FlowEmits {
39
48
  paneClick: [event: any];
40
49
  connect: [params: any];
41
50
  }
51
+ export type { FlowBackgroundProps, FlowControlsProps, FlowMiniMapProps };
52
+ export type { FlowNodeProps } from "./FlowNode.vue.js";
53
+ export type { FlowHandleProps } from "./FlowHandle.vue.js";
42
54
  declare const _default: typeof __VLS_export;
43
55
  export default _default;
44
56
  declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FlowProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
@@ -6,6 +6,9 @@ import theme from "#build/ui-elements/flow";
6
6
  import { computed } from "vue";
7
7
  import { VueFlow } from "@vue-flow/core";
8
8
  import { tv } from "../utils/tv";
9
+ import FlowBackground from "./flow/FlowBackground.vue";
10
+ import FlowControls from "./flow/FlowControls.vue";
11
+ import FlowMiniMap from "./flow/FlowMiniMap.vue";
9
12
  const {
10
13
  nodes = [],
11
14
  edges = [],
@@ -15,6 +18,9 @@ const {
15
18
  nodesDraggable = true,
16
19
  nodesConnectable = true,
17
20
  elementsSelectable = true,
21
+ background = true,
22
+ controls = true,
23
+ minimap = false,
18
24
  ui: uiProps = {}
19
25
  } = defineProps({
20
26
  nodes: { type: Array, required: false },
@@ -29,10 +35,28 @@ const {
29
35
  elementsSelectable: { type: Boolean, required: false },
30
36
  connectionMode: { type: String, required: false },
31
37
  defaultEdgeOptions: { type: Object, required: false },
32
- ui: { type: Object, required: false }
38
+ background: { type: [Boolean, Object], required: false },
39
+ controls: { type: [Boolean, Object], required: false },
40
+ minimap: { type: [Boolean, Object], required: false },
41
+ ui: { type: null, required: false }
33
42
  });
34
43
  const emit = defineEmits(["update:nodes", "update:edges", "nodeClick", "edgeClick", "paneClick", "connect"]);
35
44
  const ui = computed(() => tv({ extend: tv(theme) })({}));
45
+ const backgroundProps = computed(() => {
46
+ if (background === false) return null;
47
+ if (background === true) return {};
48
+ return background;
49
+ });
50
+ const controlsProps = computed(() => {
51
+ if (controls === false) return null;
52
+ if (controls === true) return {};
53
+ return controls;
54
+ });
55
+ const minimapProps = computed(() => {
56
+ if (minimap === false) return null;
57
+ if (minimap === true) return {};
58
+ return minimap;
59
+ });
36
60
  </script>
37
61
 
38
62
  <template>
@@ -61,6 +85,10 @@ const ui = computed(() => tv({ extend: tv(theme) })({}));
61
85
  <template v-for="(_, name) in $slots" #[name]="slotData">
62
86
  <slot :name="name" v-bind="slotData ?? {}" />
63
87
  </template>
88
+
89
+ <FlowBackground v-if="backgroundProps" v-bind="backgroundProps" />
90
+ <FlowControls v-if="controlsProps" v-bind="controlsProps" />
91
+ <FlowMiniMap v-if="minimapProps" v-bind="minimapProps" />
64
92
  </VueFlow>
65
93
  </div>
66
94
 
@@ -2,6 +2,9 @@ import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow";
3
3
  import type { ComponentConfig } from "../types/index.js";
4
4
  import type { Node, Edge, ConnectionMode } from "@vue-flow/core";
5
+ import type { FlowBackgroundProps } from "./flow/FlowBackground.vue.js";
6
+ import type { FlowControlsProps } from "./flow/FlowControls.vue.js";
7
+ import type { FlowMiniMapProps } from "./flow/FlowMiniMap.vue.js";
5
8
  type Flow = ComponentConfig<typeof theme, AppConfig, "flow">;
6
9
  export interface FlowProps {
7
10
  /** Array of node objects */
@@ -28,6 +31,12 @@ export interface FlowProps {
28
31
  connectionMode?: ConnectionMode;
29
32
  /** Default edge options */
30
33
  defaultEdgeOptions?: Record<string, any>;
34
+ /** Show background (true for defaults, or pass config object) */
35
+ background?: boolean | Omit<FlowBackgroundProps, "ui">;
36
+ /** Show controls (true for defaults, or pass config object) */
37
+ controls?: boolean | Omit<FlowControlsProps, "ui">;
38
+ /** Show minimap (true for defaults, or pass config object) */
39
+ minimap?: boolean | Omit<FlowMiniMapProps, "ui">;
31
40
  /** Theme slot overrides */
32
41
  ui?: Flow["slots"];
33
42
  }
@@ -39,6 +48,9 @@ export interface FlowEmits {
39
48
  paneClick: [event: any];
40
49
  connect: [params: any];
41
50
  }
51
+ export type { FlowBackgroundProps, FlowControlsProps, FlowMiniMapProps };
52
+ export type { FlowNodeProps } from "./FlowNode.vue.js";
53
+ export type { FlowHandleProps } from "./FlowHandle.vue.js";
42
54
  declare const _default: typeof __VLS_export;
43
55
  export default _default;
44
56
  declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FlowProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
@@ -18,7 +18,7 @@ const {
18
18
  id: { type: String, required: false },
19
19
  color: { type: null, required: false },
20
20
  connected: { type: Boolean, required: false },
21
- ui: { type: Object, required: false }
21
+ ui: { type: null, required: false }
22
22
  });
23
23
  const ui = computed(
24
24
  () => tv({ extend: tv(theme) })({
@@ -16,7 +16,7 @@ const {
16
16
  color: { type: null, required: false },
17
17
  variant: { type: null, required: false },
18
18
  selected: { type: Boolean, required: false },
19
- ui: { type: Object, required: false }
19
+ ui: { type: null, required: false }
20
20
  });
21
21
  const ui = computed(
22
22
  () => tv({ extend: tv(theme) })({
@@ -23,7 +23,7 @@ const {
23
23
  defaultValue: { type: null, required: false },
24
24
  multiple: { type: null, required: false },
25
25
  orientation: { type: String, required: false },
26
- ui: { type: Object, required: false },
26
+ ui: { type: null, required: false },
27
27
  loop: { type: Boolean, required: false },
28
28
  disabled: { type: Boolean, required: false },
29
29
  name: { type: String, required: false },
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-background";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  type FlowBackground = ComponentConfig<typeof theme, AppConfig, "flowBackground">;
5
5
  export interface FlowBackgroundProps {
6
6
  /** Background pattern variant */
@@ -5,7 +5,7 @@ import theme from "#build/ui-elements/flow-background";
5
5
  <script setup>
6
6
  import { computed } from "vue";
7
7
  import { Background } from "@vue-flow/background";
8
- import { tv } from "../utils/tv";
8
+ import { tv } from "../../utils/tv";
9
9
  const {
10
10
  pattern = "dots",
11
11
  gap = 20,
@@ -19,7 +19,7 @@ const {
19
19
  size: { type: Number, required: false },
20
20
  color: { type: String, required: false },
21
21
  lineWidth: { type: Number, required: false },
22
- ui: { type: Object, required: false }
22
+ ui: { type: null, required: false }
23
23
  });
24
24
  const ui = computed(
25
25
  () => tv({ extend: tv(theme) })({
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-background";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  type FlowBackground = ComponentConfig<typeof theme, AppConfig, "flowBackground">;
5
5
  export interface FlowBackgroundProps {
6
6
  /** Background pattern variant */
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-controls";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  import type { PanelPositionType, FitViewParams } from "@vue-flow/core";
5
5
  type FlowControls = ComponentConfig<typeof theme, AppConfig, "flowControls">;
6
6
  export interface FlowControlsProps {
@@ -5,7 +5,7 @@ import theme from "#build/ui-elements/flow-controls";
5
5
  <script setup>
6
6
  import { computed } from "vue";
7
7
  import { Controls } from "@vue-flow/controls";
8
- import { tv } from "../utils/tv";
8
+ import { tv } from "../../utils/tv";
9
9
  const {
10
10
  showZoom = true,
11
11
  showFitView = true,
@@ -19,7 +19,7 @@ const {
19
19
  showInteractive: { type: Boolean, required: false },
20
20
  fitViewParams: { type: Object, required: false },
21
21
  position: { type: String, required: false },
22
- ui: { type: Object, required: false }
22
+ ui: { type: null, required: false }
23
23
  });
24
24
  const ui = computed(() => tv({ extend: tv(theme) })({}));
25
25
  </script>
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-controls";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  import type { PanelPositionType, FitViewParams } from "@vue-flow/core";
5
5
  type FlowControls = ComponentConfig<typeof theme, AppConfig, "flowControls">;
6
6
  export interface FlowControlsProps {
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-mini-map";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  import type { PanelPositionType } from "@vue-flow/core";
5
5
  type FlowMiniMap = ComponentConfig<typeof theme, AppConfig, "flowMiniMap">;
6
6
  export interface FlowMiniMapProps {
@@ -5,7 +5,7 @@ import theme from "#build/ui-elements/flow-mini-map";
5
5
  <script setup>
6
6
  import { computed } from "vue";
7
7
  import { MiniMap } from "@vue-flow/minimap";
8
- import { tv } from "../utils/tv";
8
+ import { tv } from "../../utils/tv";
9
9
  const {
10
10
  pannable = true,
11
11
  zoomable = true,
@@ -27,7 +27,7 @@ const {
27
27
  maskColor: { type: String, required: false },
28
28
  width: { type: Number, required: false },
29
29
  height: { type: Number, required: false },
30
- ui: { type: Object, required: false }
30
+ ui: { type: null, required: false }
31
31
  });
32
32
  const ui = computed(() => tv({ extend: tv(theme) })({}));
33
33
  </script>
@@ -1,6 +1,6 @@
1
1
  import type { AppConfig } from "@nuxt/schema";
2
2
  import theme from "#build/ui-elements/flow-mini-map";
3
- import type { ComponentConfig } from "../types/index.js";
3
+ import type { ComponentConfig } from "../../types/index.js";
4
4
  import type { PanelPositionType } from "@vue-flow/core";
5
5
  type FlowMiniMap = ComponentConfig<typeof theme, AppConfig, "flowMiniMap">;
6
6
  export interface FlowMiniMapProps {
@@ -1 +1 @@
1
- @import "#build/ui-elements.css";@source "./components";
1
+ @import "#build/ui-elements.css";@source "./components";.vue-flow__controls{border:1px solid var(--ui-border);border-radius:var(--ui-radius);box-shadow:0 0 2px 1px rgba(0,0,0,.08);overflow:hidden}.vue-flow__controls-button{align-items:center;background:var(--ui-bg);border:none;border-bottom:1px solid var(--ui-border);cursor:pointer;display:flex;height:16px;justify-content:center;padding:6px;width:16px}.vue-flow__controls-button:last-child{border-bottom:none}.vue-flow__controls-button:hover{background:var(--ui-bg-elevated)}.vue-flow__controls-button svg{fill:var(--ui-text);max-height:12px;max-width:12px;width:100%}.vue-flow__minimap{border:1px solid var(--ui-border);border-radius:var(--ui-radius);overflow:hidden}
@@ -11,6 +11,7 @@
11
11
  import plur from "plur";
12
12
  import slugify from "@sindresorhus/slugify";
13
13
  import * as date from "./std/date.js";
14
+ export { plur, slugify, date };
14
15
  declare const _default: {
15
16
  readonly plur: typeof plur;
16
17
  readonly slugify: typeof slugify;
@@ -1,6 +1,7 @@
1
1
  import plur from "plur";
2
2
  import slugify from "@sindresorhus/slugify";
3
3
  import * as date from "./std/date.js";
4
+ export { plur, slugify, date };
4
5
  export default {
5
6
  plur,
6
7
  slugify,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-ui-elements",
3
- "version": "0.1.41",
3
+ "version": "0.2.0",
4
4
  "description": "A collection of beautiful, animated UI components for Nuxt applications",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/genu/nuxt-ui-elements.git",
@@ -43,7 +43,7 @@
43
43
  "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
44
44
  },
45
45
  "dependencies": {
46
- "@internationalized/date": "3.11.0",
46
+ "@internationalized/date": "3.12.0",
47
47
  "@nuxt/kit": "4.3.1",
48
48
  "@sindresorhus/slugify": "3.0.0",
49
49
  "plur": "6.0.0",
@@ -51,7 +51,7 @@
51
51
  "tailwind-variants": "3.2.2"
52
52
  },
53
53
  "devDependencies": {
54
- "@nuxt/devtools": "3.2.2",
54
+ "@nuxt/devtools": "3.2.3",
55
55
  "@nuxt/eslint-config": "1.15.2",
56
56
  "@nuxt/module-builder": "1.0.2",
57
57
  "@nuxt/schema": "4.3.1",
@@ -60,7 +60,7 @@
60
60
  "@types/node": "latest",
61
61
  "@vitest/coverage-v8": "4.0.18",
62
62
  "better-sqlite3": "12.6.2",
63
- "eslint": "10.0.2",
63
+ "eslint": "10.0.3",
64
64
  "eslint-config-prettier": "10.1.8",
65
65
  "eslint-plugin-prettier": "5.5.5",
66
66
  "nuxt": "4.3.1",
@@ -90,7 +90,7 @@
90
90
  "optional": true
91
91
  }
92
92
  },
93
- "packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017",
93
+ "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
94
94
  "pnpm": {
95
95
  "onlyBuiltDependencies": [
96
96
  "better-sqlite3"