@nhealth/nutils 0.0.2
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 +503 -0
- package/dist/module.cjs +43 -0
- package/dist/module.d.cts +13 -0
- package/dist/module.d.mts +13 -0
- package/dist/module.d.ts +13 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +40 -0
- package/dist/runtime/app/assets/styles.css +1 -0
- package/dist/runtime/app/components/ComponentRouter.d.vue.ts +50 -0
- package/dist/runtime/app/components/ComponentRouter.vue +26 -0
- package/dist/runtime/app/components/ComponentRouter.vue.d.ts +50 -0
- package/dist/runtime/app/components/ComponentShell.d.vue.ts +28 -0
- package/dist/runtime/app/components/ComponentShell.vue +95 -0
- package/dist/runtime/app/components/ComponentShell.vue.d.ts +28 -0
- package/dist/runtime/app/components/ConfirmModal.d.vue.ts +3 -0
- package/dist/runtime/app/components/ConfirmModal.vue +163 -0
- package/dist/runtime/app/components/ConfirmModal.vue.d.ts +3 -0
- package/dist/runtime/app/components/LiveIndicator.d.vue.ts +9 -0
- package/dist/runtime/app/components/LiveIndicator.vue +43 -0
- package/dist/runtime/app/components/LiveIndicator.vue.d.ts +9 -0
- package/dist/runtime/app/components/StatCard.d.vue.ts +15 -0
- package/dist/runtime/app/components/StatCard.vue +99 -0
- package/dist/runtime/app/components/StatCard.vue.d.ts +15 -0
- package/dist/runtime/app/components/StatCounter.d.vue.ts +11 -0
- package/dist/runtime/app/components/StatCounter.vue +29 -0
- package/dist/runtime/app/components/StatCounter.vue.d.ts +11 -0
- package/dist/runtime/app/composables/useComponentRouter.d.ts +50 -0
- package/dist/runtime/app/composables/useComponentRouter.js +265 -0
- package/dist/runtime/app/composables/useConfirmModal.d.ts +50 -0
- package/dist/runtime/app/composables/useConfirmModal.js +107 -0
- package/dist/runtime/app/composables/useConfirmModalState.d.ts +12 -0
- package/dist/runtime/app/composables/useConfirmModalState.js +12 -0
- package/dist/runtime/shared/formatters.d.ts +22 -0
- package/dist/runtime/shared/formatters.js +15 -0
- package/dist/types.d.mts +3 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
# nutils
|
|
2
|
+
|
|
3
|
+
A comprehensive Nuxt v4 module providing shared components, composables, utilities, and a component-based router for nhealth.org packages.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- 🎨 **Auto-registered Components** - Use components without explicit imports
|
|
8
|
+
- 🔧 **Auto-imported Composables** - Access composables anywhere in your Nuxt app (useComponentRouter, useConfirmModal)
|
|
9
|
+
- 🛠️ **Utility Functions** - Common utility functions auto-imported
|
|
10
|
+
- 🧭 **Component-based Routing** - Dynamic component rendering with query/hash/memory routing modes
|
|
11
|
+
- 📊 **Pre-built UI Components** - StatCard, StatCounter, LiveIndicator, ConfirmModal, and more
|
|
12
|
+
- ⚡ **Tailwind + Nuxt UI** - Modern styling with Tailwind CSS and Nuxt UI v4
|
|
13
|
+
- 📱 **Fully Responsive** - Mobile-first components
|
|
14
|
+
- 🌙 **Dark Mode Support** - All components support light and dark modes
|
|
15
|
+
- 📦 **TypeScript Support** - Full TypeScript support with type definitions
|
|
16
|
+
- ⚡ **Nuxt 4 Compatible** - Built for Nuxt v4
|
|
17
|
+
|
|
18
|
+
## 🚀 Quick Setup
|
|
19
|
+
|
|
20
|
+
### 1. Install the module
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @nhealth/nutils
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Add to `nuxt.config.ts`
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
export default defineNuxtConfig({
|
|
30
|
+
modules: [
|
|
31
|
+
'@nhealth/nutils'
|
|
32
|
+
]
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. (Optional) Add Nuxt UI and Tailwind for full styling
|
|
37
|
+
|
|
38
|
+
If you want to use the styled components with Nuxt UI and Tailwind CSS:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @nuxt/ui tailwindcss
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then add to `nuxt.config.ts`:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
export default defineNuxtConfig({
|
|
48
|
+
modules: [
|
|
49
|
+
'@nuxt/ui',
|
|
50
|
+
'@nhealth/nutils'
|
|
51
|
+
],
|
|
52
|
+
colorMode: {
|
|
53
|
+
preference: 'light'
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That's it! You can now use all components, composables, and utilities ✨
|
|
59
|
+
|
|
60
|
+
## 📚 Documentation
|
|
61
|
+
|
|
62
|
+
### Components
|
|
63
|
+
|
|
64
|
+
#### StatCard
|
|
65
|
+
A flexible stat display card with multiple variants and optional descriptions.
|
|
66
|
+
|
|
67
|
+
```vue
|
|
68
|
+
<template>
|
|
69
|
+
<NUtilsStatCard
|
|
70
|
+
label="Total Users"
|
|
71
|
+
:value="42500"
|
|
72
|
+
icon="i-heroicons-users-20-solid"
|
|
73
|
+
variant="primary"
|
|
74
|
+
description="Active this month"
|
|
75
|
+
/>
|
|
76
|
+
</template>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Props:**
|
|
80
|
+
- `label` (string, required) - Label text
|
|
81
|
+
- `value` (number | string, required) - The value to display (numbers are formatted: 1M, 1K, etc.)
|
|
82
|
+
- `icon` (string, optional) - Icon name (Heroicons compatible)
|
|
83
|
+
- `description` (string, optional) - Additional description text
|
|
84
|
+
- `variant` (string, default: 'gray') - Color variant: `'gray' | 'primary' | 'success' | 'warning' | 'error' | 'info'`
|
|
85
|
+
- `trend` (string, default: 'neutral') - Trend indicator: `'up' | 'down' | 'neutral'`
|
|
86
|
+
|
|
87
|
+
#### StatCounter
|
|
88
|
+
Compact inline counter for quick status displays.
|
|
89
|
+
|
|
90
|
+
```vue
|
|
91
|
+
<template>
|
|
92
|
+
<NUtilsStatCounter
|
|
93
|
+
label="Pending"
|
|
94
|
+
:count="12"
|
|
95
|
+
color="warning"
|
|
96
|
+
/>
|
|
97
|
+
</template>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Props:**
|
|
101
|
+
- `label` (string, required) - Label text
|
|
102
|
+
- `count` (number, optional) - Counter value
|
|
103
|
+
- `color` (string, default: 'neutral') - Color variant: `'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'info'`
|
|
104
|
+
|
|
105
|
+
#### LiveIndicator
|
|
106
|
+
Status indicator for connection, system, or service status.
|
|
107
|
+
|
|
108
|
+
```vue
|
|
109
|
+
<template>
|
|
110
|
+
<NUtilsLiveIndicator status="connected" />
|
|
111
|
+
<NUtilsLiveIndicator status="reconnecting" />
|
|
112
|
+
<NUtilsLiveIndicator status="offline" />
|
|
113
|
+
</template>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Props:**
|
|
117
|
+
- `status` (string, default: 'offline') - Status: `'connected' | 'reconnecting' | 'offline'`
|
|
118
|
+
|
|
119
|
+
#### ComponentRouter
|
|
120
|
+
A slot-based component for dynamic component rendering with routing capabilities.
|
|
121
|
+
|
|
122
|
+
```vue
|
|
123
|
+
<template>
|
|
124
|
+
<NUtilsComponentRouter
|
|
125
|
+
v-slot="{ component }"
|
|
126
|
+
:routes="routes"
|
|
127
|
+
base="page"
|
|
128
|
+
mode="query"
|
|
129
|
+
>
|
|
130
|
+
<component :is="component" />
|
|
131
|
+
</NUtilsComponentRouter>
|
|
132
|
+
</template>
|
|
133
|
+
|
|
134
|
+
<script setup>
|
|
135
|
+
const routes = {
|
|
136
|
+
'/home': () => import('./pages/Home.vue'),
|
|
137
|
+
'/about': () => import('./pages/About.vue'),
|
|
138
|
+
'/contact': () => import('./pages/Contact.vue'),
|
|
139
|
+
}
|
|
140
|
+
</script>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Props:**
|
|
144
|
+
- `routes` (Record<string, Component | AsyncComponentLoader>, required) - Route definitions
|
|
145
|
+
- `base` (string, default: 'fp') - Query/hash parameter name
|
|
146
|
+
- `mode` (string, default: 'query') - Routing mode: `'query' | 'hash' | 'memory'`
|
|
147
|
+
- `initial` (string, optional) - Initial route path
|
|
148
|
+
- `debug` (boolean, default: false) - Enable debug logging
|
|
149
|
+
|
|
150
|
+
**Slot Props:**
|
|
151
|
+
- `component` - Current component to render
|
|
152
|
+
- `route` - Current route object with path, params, and query
|
|
153
|
+
- `push` - Function to navigate to a route
|
|
154
|
+
|
|
155
|
+
#### ComponentShell
|
|
156
|
+
Layout component with integrated navigation and content area.
|
|
157
|
+
|
|
158
|
+
```vue
|
|
159
|
+
<template>
|
|
160
|
+
<NUtilsComponentShell
|
|
161
|
+
orientation="vertical"
|
|
162
|
+
:items="navigationItems"
|
|
163
|
+
:pageOffset="0"
|
|
164
|
+
>
|
|
165
|
+
<div class="p-4">
|
|
166
|
+
<!-- Content goes here -->
|
|
167
|
+
</div>
|
|
168
|
+
</NUtilsComponentShell>
|
|
169
|
+
</template>
|
|
170
|
+
|
|
171
|
+
<script setup>
|
|
172
|
+
const navigationItems = [
|
|
173
|
+
[
|
|
174
|
+
{ label: 'Home', path: '/', icon: 'i-heroicons-home-20-solid' },
|
|
175
|
+
{ label: 'About', path: '/about', icon: 'i-heroicons-information-circle-20-solid' },
|
|
176
|
+
]
|
|
177
|
+
]
|
|
178
|
+
</script>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Props:**
|
|
182
|
+
- `orientation` (string, default: 'horizontal') - Layout: `'horizontal' | 'vertical'`
|
|
183
|
+
- `items` (NavigationMenuItem[][], optional) - Navigation items
|
|
184
|
+
- `activeMatch` (string, default: 'prefix') - Active match mode: `'exact' | 'prefix'`
|
|
185
|
+
- `pageOffset` (string | number, default: 0) - Height offset for container (e.g., "4rem", 64)
|
|
186
|
+
|
|
187
|
+
**Slots:**
|
|
188
|
+
- `leading` - Additional content above navigation
|
|
189
|
+
- `trailing` - Additional content below navigation
|
|
190
|
+
- Default slot - Main content area
|
|
191
|
+
|
|
192
|
+
#### ConfirmModal
|
|
193
|
+
Modal dialog for requesting user confirmation with optional validation gates.
|
|
194
|
+
|
|
195
|
+
```vue
|
|
196
|
+
<template>
|
|
197
|
+
<NUtilsConfirmModal />
|
|
198
|
+
<UButton @click="handleDelete">Delete Item</UButton>
|
|
199
|
+
</template>
|
|
200
|
+
|
|
201
|
+
<script setup>
|
|
202
|
+
const confirm = useConfirmModal()
|
|
203
|
+
|
|
204
|
+
async function handleDelete() {
|
|
205
|
+
const result = await confirm({
|
|
206
|
+
title: 'Delete Item',
|
|
207
|
+
description: 'This action cannot be undone.',
|
|
208
|
+
dangerous: true,
|
|
209
|
+
icon: 'i-heroicons-trash-20-solid',
|
|
210
|
+
iconColor: 'error',
|
|
211
|
+
confirmLabel: 'Delete',
|
|
212
|
+
cancelLabel: 'Cancel',
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
if (result.confirmed) {
|
|
216
|
+
// Handle deletion
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
</script>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Configuration Options:**
|
|
223
|
+
- `title` (string) - Modal title
|
|
224
|
+
- `description` (string) - Description text
|
|
225
|
+
- `text` (string) - Alternative to description
|
|
226
|
+
- `items` (string[]) - Bullet list items
|
|
227
|
+
- `warning` (string) - Warning message
|
|
228
|
+
- `icon` (string) - Icon name
|
|
229
|
+
- `confirmLabel` (string, default: 'Confirm') - Confirm button label
|
|
230
|
+
- `cancelLabel` (string, default: 'Cancel') - Cancel button label
|
|
231
|
+
- `dangerous` (boolean) - Style for destructive actions
|
|
232
|
+
- `requireInputEquals` (string) - Require typed confirmation
|
|
233
|
+
- `inputPlaceholder` (string) - Placeholder for input field
|
|
234
|
+
- `requireCheckbox` (boolean) - Require checkbox confirmation
|
|
235
|
+
- `checkboxLabel` (string) - Checkbox label
|
|
236
|
+
- `confirmColor` (string) - Button color
|
|
237
|
+
- `iconColor` (string) - Icon color variant
|
|
238
|
+
|
|
239
|
+
### Composables
|
|
240
|
+
|
|
241
|
+
#### useComponentRouter
|
|
242
|
+
Dynamic component routing without Nuxt's file-based routing.
|
|
243
|
+
|
|
244
|
+
```vue
|
|
245
|
+
<script setup>
|
|
246
|
+
const { component, route, push, makePath } = useComponentRouter({
|
|
247
|
+
routes: {
|
|
248
|
+
'/dashboard': () => import('./Dashboard.vue'),
|
|
249
|
+
'/users': () => import('./Users.vue'),
|
|
250
|
+
'/users/:id': () => import('./UserDetail.vue'),
|
|
251
|
+
},
|
|
252
|
+
mode: 'query',
|
|
253
|
+
base: 'view',
|
|
254
|
+
initial: '/dashboard'
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
const goToUser = (id) => {
|
|
258
|
+
push(`/users/${id}`)
|
|
259
|
+
}
|
|
260
|
+
</script>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Options:**
|
|
264
|
+
- `routes` (Record<string, Component | AsyncComponentLoader>) - Route definitions
|
|
265
|
+
- `mode` ('query' | 'hash' | 'memory') - Routing mode
|
|
266
|
+
- `base` (string) - Query/hash parameter name
|
|
267
|
+
- `initial` (string) - Initial route
|
|
268
|
+
- `debug` (boolean) - Enable debug logging
|
|
269
|
+
|
|
270
|
+
**Returns:**
|
|
271
|
+
- `component` - Current component (ShallowRef<Component | null>)
|
|
272
|
+
- `route` - Current route info (ShallowRef)
|
|
273
|
+
- `push(path)` - Navigate to path
|
|
274
|
+
- `replace(path)` - Replace current route
|
|
275
|
+
- `makePath(pattern, params)` - Build path from pattern
|
|
276
|
+
- `makeHref(pattern, params)` - Build href from pattern
|
|
277
|
+
- `pushTo(pattern, params)` - Navigate with pattern
|
|
278
|
+
- `replaceTo(pattern, params)` - Replace with pattern
|
|
279
|
+
- `hooks` - Navigation hooks
|
|
280
|
+
|
|
281
|
+
#### useConfirmModal
|
|
282
|
+
Modal confirmation dialog management.
|
|
283
|
+
|
|
284
|
+
```vue
|
|
285
|
+
<script setup>
|
|
286
|
+
const confirm = useConfirmModal({
|
|
287
|
+
confirmLabel: 'Yes',
|
|
288
|
+
cancelLabel: 'No'
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const result = await confirm({
|
|
292
|
+
title: 'Confirm?',
|
|
293
|
+
description: 'Are you sure?'
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
if (result.confirmed) {
|
|
297
|
+
// Handle confirmation
|
|
298
|
+
}
|
|
299
|
+
</script>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Utilities
|
|
303
|
+
|
|
304
|
+
#### formatDate
|
|
305
|
+
Format dates to readable strings.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
const date = formatDate(new Date())
|
|
309
|
+
// Output: "January 8, 2026"
|
|
310
|
+
|
|
311
|
+
const date = formatDate(new Date(), 'de-DE')
|
|
312
|
+
// Output: "8. Januar 2026"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### formatNumber
|
|
316
|
+
Format numbers with locale-specific separators.
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
const number = formatNumber(1234567.89)
|
|
320
|
+
// Output: "1,234,567.89"
|
|
321
|
+
|
|
322
|
+
const number = formatNumber(1234567.89, 'de-DE')
|
|
323
|
+
// Output: "1.234.567,89"
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
#### truncate
|
|
327
|
+
Truncate strings to maximum length.
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
const text = truncate('This is a long text', 10)
|
|
331
|
+
// Output: "This is..."
|
|
332
|
+
|
|
333
|
+
const text = truncate('This is a long text', 10, '→')
|
|
334
|
+
// Output: "This is→"
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## 🎨 Setup with Nuxt UI + Tailwind
|
|
338
|
+
|
|
339
|
+
For a complete styled experience, follow these steps:
|
|
340
|
+
|
|
341
|
+
### 1. Install dependencies
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
npm install @nuxt/ui @nuxtjs/tailwindcss
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 2. Configure `nuxt.config.ts`
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
export default defineNuxtConfig({
|
|
351
|
+
modules: [
|
|
352
|
+
'@nuxt/ui',
|
|
353
|
+
'@nhealth/nutils'
|
|
354
|
+
],
|
|
355
|
+
|
|
356
|
+
colorMode: {
|
|
357
|
+
preference: 'light'
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
tailwindcss: {
|
|
361
|
+
exposeConfig: true
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 3. Create `tailwind.config.ts`
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import type { Config } from 'tailwindcss'
|
|
370
|
+
import defaultTheme from 'tailwindcss/defaultTheme'
|
|
371
|
+
|
|
372
|
+
export default {
|
|
373
|
+
theme: {
|
|
374
|
+
extend: {
|
|
375
|
+
fontFamily: {
|
|
376
|
+
sans: ['Inter var', ...defaultTheme.fontFamily.sans]
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
} satisfies Config
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### 4. Create `app.vue`
|
|
384
|
+
|
|
385
|
+
```vue
|
|
386
|
+
<template>
|
|
387
|
+
<div class="min-h-screen bg-slate-50 dark:bg-slate-900">
|
|
388
|
+
<NuxtPage />
|
|
389
|
+
</div>
|
|
390
|
+
</template>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### 5. Create CSS entry point `app.css`
|
|
394
|
+
|
|
395
|
+
```css
|
|
396
|
+
@tailwind base;
|
|
397
|
+
@tailwind components;
|
|
398
|
+
@tailwind utilities;
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## 🔧 Development
|
|
402
|
+
|
|
403
|
+
### Setup
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
# Install dependencies
|
|
407
|
+
npm install
|
|
408
|
+
|
|
409
|
+
# Generate type stubs
|
|
410
|
+
npm run dev:prepare
|
|
411
|
+
|
|
412
|
+
# Develop with the playground
|
|
413
|
+
npm run dev
|
|
414
|
+
|
|
415
|
+
# Build the playground
|
|
416
|
+
npm run dev:build
|
|
417
|
+
|
|
418
|
+
# Run linting
|
|
419
|
+
npm run lint
|
|
420
|
+
|
|
421
|
+
# Run tests
|
|
422
|
+
npm run test
|
|
423
|
+
|
|
424
|
+
# Run type checking
|
|
425
|
+
npm run test:types
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Adding New Features
|
|
429
|
+
|
|
430
|
+
#### Components
|
|
431
|
+
|
|
432
|
+
Add `.vue` files to `src/runtime/app/components/` - they'll be auto-registered with the `NUtils` prefix.
|
|
433
|
+
|
|
434
|
+
```vue
|
|
435
|
+
<!-- src/runtime/app/components/MyComponent.vue -->
|
|
436
|
+
<template>
|
|
437
|
+
<div><!-- Your component --></div>
|
|
438
|
+
</template>
|
|
439
|
+
|
|
440
|
+
<script setup lang="ts">
|
|
441
|
+
// Your script
|
|
442
|
+
</script>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Usage:
|
|
446
|
+
```vue
|
|
447
|
+
<NUtilsMyComponent />
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### Composables
|
|
451
|
+
|
|
452
|
+
Add `.ts` files to `src/runtime/app/composables/` - they'll be auto-imported.
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
// src/runtime/app/composables/useMyComposable.ts
|
|
456
|
+
export function useMyComposable() {
|
|
457
|
+
// Your composable logic
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
Usage:
|
|
462
|
+
```typescript
|
|
463
|
+
const myComposable = useMyComposable()
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
#### Utilities
|
|
467
|
+
|
|
468
|
+
Add `.ts` files to `src/runtime/shared/` - they'll be auto-imported.
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
// src/runtime/shared/myUtil.ts
|
|
472
|
+
export function myUtil(input: string): string {
|
|
473
|
+
return input.toUpperCase()
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Usage:
|
|
478
|
+
```typescript
|
|
479
|
+
const result = myUtil('hello')
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## 📦 Module Options
|
|
483
|
+
|
|
484
|
+
Configure the module in your `nuxt.config.ts`:
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
export default defineNuxtConfig({
|
|
488
|
+
modules: [
|
|
489
|
+
'@nhealth/nutils'
|
|
490
|
+
],
|
|
491
|
+
nutils: {
|
|
492
|
+
enabled: true // Enable or disable the module
|
|
493
|
+
}
|
|
494
|
+
})
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## 🎯 Playground
|
|
498
|
+
|
|
499
|
+
The module includes a comprehensive playground at `playground/app.vue` demonstrating all components and composables. Run `npm run dev` to explore.
|
|
500
|
+
|
|
501
|
+
## 📄 License
|
|
502
|
+
|
|
503
|
+
MIT
|
package/dist/module.cjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const kit = require('@nuxt/kit');
|
|
4
|
+
|
|
5
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
6
|
+
const resolver = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href)));
|
|
7
|
+
const module$1 = kit.defineNuxtModule({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "@nhealth/nutils",
|
|
10
|
+
configKey: "nutils",
|
|
11
|
+
compatibility: {
|
|
12
|
+
nuxt: ">=4.0.0"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaults: {
|
|
16
|
+
enabled: true
|
|
17
|
+
},
|
|
18
|
+
async setup(options, nuxt) {
|
|
19
|
+
if (!options.enabled) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
kit.addComponentsDir({
|
|
23
|
+
path: resolver.resolve("./runtime/app/components"),
|
|
24
|
+
pathPrefix: false,
|
|
25
|
+
prefix: "NUtils",
|
|
26
|
+
global: true
|
|
27
|
+
});
|
|
28
|
+
kit.addImportsDir(resolver.resolve("./runtime/app/composables"));
|
|
29
|
+
const formatters = [
|
|
30
|
+
"formatDate",
|
|
31
|
+
"formatNumber",
|
|
32
|
+
"truncate"
|
|
33
|
+
];
|
|
34
|
+
formatters.forEach((name) => {
|
|
35
|
+
kit.addServerImports({ name, as: name, from: resolver.resolve("./runtime/shared/formatters") });
|
|
36
|
+
kit.addImports({ name, as: name, from: resolver.resolve("./runtime/shared/formatters") });
|
|
37
|
+
});
|
|
38
|
+
nuxt.options.build.transpile = nuxt.options.build.transpile || [];
|
|
39
|
+
nuxt.options.build.transpile.push("@nhealthorg/nutils");
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
module.exports = module$1;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface ModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Enable or disable the module
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
11
|
+
|
|
12
|
+
export = _default;
|
|
13
|
+
export type { ModuleOptions };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface ModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Enable or disable the module
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
11
|
+
|
|
12
|
+
export { _default as default };
|
|
13
|
+
export type { ModuleOptions };
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface ModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Enable or disable the module
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
11
|
+
|
|
12
|
+
export = _default;
|
|
13
|
+
export type { ModuleOptions };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createResolver, defineNuxtModule, addComponentsDir, addImportsDir, addServerImports, addImports } from '@nuxt/kit';
|
|
2
|
+
|
|
3
|
+
const resolver = createResolver(import.meta.url);
|
|
4
|
+
const module$1 = defineNuxtModule({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "@nhealth/nutils",
|
|
7
|
+
configKey: "nutils",
|
|
8
|
+
compatibility: {
|
|
9
|
+
nuxt: ">=4.0.0"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
defaults: {
|
|
13
|
+
enabled: true
|
|
14
|
+
},
|
|
15
|
+
async setup(options, nuxt) {
|
|
16
|
+
if (!options.enabled) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
addComponentsDir({
|
|
20
|
+
path: resolver.resolve("./runtime/app/components"),
|
|
21
|
+
pathPrefix: false,
|
|
22
|
+
prefix: "NUtils",
|
|
23
|
+
global: true
|
|
24
|
+
});
|
|
25
|
+
addImportsDir(resolver.resolve("./runtime/app/composables"));
|
|
26
|
+
const formatters = [
|
|
27
|
+
"formatDate",
|
|
28
|
+
"formatNumber",
|
|
29
|
+
"truncate"
|
|
30
|
+
];
|
|
31
|
+
formatters.forEach((name) => {
|
|
32
|
+
addServerImports({ name, as: name, from: resolver.resolve("./runtime/shared/formatters") });
|
|
33
|
+
addImports({ name, as: name, from: resolver.resolve("./runtime/shared/formatters") });
|
|
34
|
+
});
|
|
35
|
+
nuxt.options.build.transpile = nuxt.options.build.transpile || [];
|
|
36
|
+
nuxt.options.build.transpile.push("@nhealthorg/nutils");
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export { module$1 as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@source "../components/**/*.vue";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type Component } from '#imports';
|
|
2
|
+
type AsyncComponentLoader = () => Promise<Component | {
|
|
3
|
+
default: Component;
|
|
4
|
+
}>;
|
|
5
|
+
type ComponentRouteRecord = {
|
|
6
|
+
path: string;
|
|
7
|
+
component: Component | AsyncComponentLoader;
|
|
8
|
+
name?: string;
|
|
9
|
+
};
|
|
10
|
+
type ComponentRouterMode = 'query' | 'hash' | 'memory';
|
|
11
|
+
type __VLS_Props = {
|
|
12
|
+
routes: ComponentRouteRecord[] | Record<string, Component | AsyncComponentLoader>;
|
|
13
|
+
base?: string;
|
|
14
|
+
mode?: ComponentRouterMode;
|
|
15
|
+
initial?: string;
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
};
|
|
18
|
+
declare var __VLS_1: {
|
|
19
|
+
component: Component;
|
|
20
|
+
route: {
|
|
21
|
+
path: string;
|
|
22
|
+
params: Record<string, string>;
|
|
23
|
+
query: Record<string, string | string[]>;
|
|
24
|
+
};
|
|
25
|
+
push: (path: string) => Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
type __VLS_Slots = {} & {
|
|
28
|
+
default?: (props: typeof __VLS_1) => any;
|
|
29
|
+
};
|
|
30
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
31
|
+
push: (path: string) => Promise<void>;
|
|
32
|
+
replace: (path: string) => Promise<void>;
|
|
33
|
+
route: import("vue").ShallowRef<{
|
|
34
|
+
path: string;
|
|
35
|
+
params: Record<string, string>;
|
|
36
|
+
query: Record<string, string | string[]>;
|
|
37
|
+
}>;
|
|
38
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
39
|
+
base: string;
|
|
40
|
+
mode: ComponentRouterMode;
|
|
41
|
+
debug: boolean;
|
|
42
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
43
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
44
|
+
declare const _default: typeof __VLS_export;
|
|
45
|
+
export default _default;
|
|
46
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
47
|
+
new (): {
|
|
48
|
+
$slots: S;
|
|
49
|
+
};
|
|
50
|
+
};
|