nuxt-ui-elements 0.1.8 → 0.1.11

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 (27) hide show
  1. package/README.md +36 -30
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +125 -13
  4. package/dist/runtime/components/DialogConfirm.d.vue.ts +49 -0
  5. package/dist/runtime/components/DialogConfirm.vue +170 -0
  6. package/dist/runtime/components/DialogConfirm.vue.d.ts +49 -0
  7. package/dist/runtime/composables/useDialog.d.ts +0 -0
  8. package/dist/runtime/composables/useDialog.js +25 -0
  9. package/dist/runtime/index.css +1 -0
  10. package/dist/runtime/types/tv.d.ts +64 -14
  11. package/package.json +14 -11
  12. package/dist/runtime/components/backgrounds/BackgroundAurora.d.vue.ts +0 -137
  13. package/dist/runtime/components/backgrounds/BackgroundAurora.vue +0 -145
  14. package/dist/runtime/components/backgrounds/BackgroundAurora.vue.d.ts +0 -137
  15. package/dist/runtime/components/backgrounds/BackgroundFlickeringGrid.d.vue.ts +0 -120
  16. package/dist/runtime/components/backgrounds/BackgroundFlickeringGrid.vue +0 -246
  17. package/dist/runtime/components/backgrounds/BackgroundFlickeringGrid.vue.d.ts +0 -120
  18. package/dist/runtime/composables/useColorResolver.d.ts +0 -40
  19. package/dist/runtime/composables/useColorResolver.js +0 -68
  20. package/dist/runtime/composables/useGradient.d.ts +0 -23
  21. package/dist/runtime/composables/useGradient.js +0 -37
  22. package/dist/runtime/composables/useThemeColors.d.ts +0 -69
  23. package/dist/runtime/composables/useThemeColors.js +0 -94
  24. package/dist/runtime/plugin.d.ts +0 -2
  25. package/dist/runtime/plugin.js +0 -4
  26. package/dist/runtime/themes/background-flickering-grid.d.ts +0 -7
  27. package/dist/runtime/themes/background-flickering-grid.js +0 -6
package/README.md CHANGED
@@ -30,22 +30,32 @@ A collection of beautiful, animated UI components for Nuxt applications. Built w
30
30
 
31
31
  ## Quick Setup
32
32
 
33
- Install the module to your Nuxt application with one command:
33
+ 1. Install the module to your Nuxt application:
34
34
 
35
35
  ```bash
36
36
  pnpm add nuxt-ui-elements
37
37
  ```
38
38
 
39
- Add the module to your `nuxt.config.ts`:
39
+ 2. Add the module to your `nuxt.config.ts`:
40
40
 
41
41
  ```ts
42
42
  export default defineNuxtConfig({
43
- modules: ['nuxt-ui-elements']
43
+ modules: ["@nuxt/ui", "nuxt-ui-elements"],
44
44
  })
45
45
  ```
46
46
 
47
+ 3. Import the module's CSS in your main CSS file (e.g., `assets/css/main.css`):
48
+
49
+ ```css
50
+ @import "tailwindcss";
51
+ @import "@nuxt/ui";
52
+ @import "nuxt-ui-elements";
53
+ ```
54
+
47
55
  That's it! You can now use Nuxt UI Elements in your Nuxt app ✨
48
56
 
57
+ > **Note:** This module requires `@nuxt/ui` v4.x as a peer dependency. The CSS import is required for Tailwind v4 to properly scan and generate styles from the component themes.
58
+
49
59
  ## Usage
50
60
 
51
61
  ### FlickeringGrid
@@ -61,8 +71,7 @@ A beautiful animated grid background component perfect for hero sections and lan
61
71
  gradient-direction="left-right"
62
72
  gradient-end-color="white"
63
73
  :flicker-speed="0.2"
64
- class="z-0"
65
- />
74
+ class="z-0" />
66
75
  <div class="relative z-10">
67
76
  <!-- Your content here -->
68
77
  </div>
@@ -113,24 +122,23 @@ An animated button component with an elegant shimmer effect, perfect for call-to
113
122
  shimmer-color="#60a5fa"
114
123
  background="rgba(59, 130, 246, 1)"
115
124
  :speed="2.5"
116
- @click="handleClick"
117
- />
125
+ @click="handleClick" />
118
126
  </template>
119
127
  ```
120
128
 
121
129
  #### Props
122
130
 
123
- | Prop | Type | Default | Description |
124
- | --------------- | -------- | -------------------- | ------------------------------------------------ |
125
- | `label` | `string` | - | Button label text |
126
- | `shimmerColor` | `string` | `'#ffffff'` | Color of the shimmer effect |
127
- | `shimmerSize` | `string` | `'0.05em'` | Size of the shimmer effect |
128
- | `speed` | `number` | `3` | Animation speed in seconds (lower = faster) |
129
- | `background` | `string` | `'rgba(0, 0, 0, 1)'` | Background color of the button |
130
- | `radius` | `string` | `'100px'` | Border radius of the button |
131
- | `size` | `string` | `'md'` | Button size: `xs`, `sm`, `md`, `lg`, `xl` |
132
- | `class` | `string` | - | Additional CSS classes |
133
- | `ui` | `object` | - | UI slot customization for advanced styling |
131
+ | Prop | Type | Default | Description |
132
+ | -------------- | -------- | -------------------- | ------------------------------------------- |
133
+ | `label` | `string` | - | Button label text |
134
+ | `shimmerColor` | `string` | `'#ffffff'` | Color of the shimmer effect |
135
+ | `shimmerSize` | `string` | `'0.05em'` | Size of the shimmer effect |
136
+ | `speed` | `number` | `3` | Animation speed in seconds (lower = faster) |
137
+ | `background` | `string` | `'rgba(0, 0, 0, 1)'` | Background color of the button |
138
+ | `radius` | `string` | `'100px'` | Border radius of the button |
139
+ | `size` | `string` | `'md'` | Button size: `xs`, `sm`, `md`, `lg`, `xl` |
140
+ | `class` | `string` | - | Additional CSS classes |
141
+ | `ui` | `object` | - | UI slot customization for advanced styling |
134
142
 
135
143
  #### Slots
136
144
 
@@ -145,20 +153,19 @@ An animated button component with an elegant shimmer effect, perfect for call-to
145
153
  #### Examples
146
154
 
147
155
  **Basic Usage:**
156
+
148
157
  ```vue
149
158
  <UEButtonShimmer label="Click Me" />
150
159
  ```
151
160
 
152
161
  **With Custom Colors:**
162
+
153
163
  ```vue
154
- <UEButtonShimmer
155
- label="Primary Action"
156
- shimmer-color="#a78bfa"
157
- background="rgba(139, 92, 246, 1)"
158
- />
164
+ <UEButtonShimmer label="Primary Action" shimmer-color="#a78bfa" background="rgba(139, 92, 246, 1)" />
159
165
  ```
160
166
 
161
167
  **Different Sizes:**
168
+
162
169
  ```vue
163
170
  <UEButtonShimmer label="Small" size="sm" />
164
171
  <UEButtonShimmer label="Medium" size="md" />
@@ -167,6 +174,7 @@ An animated button component with an elegant shimmer effect, perfect for call-to
167
174
  ```
168
175
 
169
176
  **With Slots:**
177
+
170
178
  ```vue
171
179
  <UEButtonShimmer>
172
180
  <template #leading>
@@ -180,11 +188,9 @@ An animated button component with an elegant shimmer effect, perfect for call-to
180
188
  ```
181
189
 
182
190
  **Fast Animation:**
191
+
183
192
  ```vue
184
- <UEButtonShimmer
185
- label="Fast Shimmer"
186
- :speed="1.5"
187
- />
193
+ <UEButtonShimmer label="Fast Shimmer" :speed="1.5" />
188
194
  ```
189
195
 
190
196
  ## Configuration
@@ -193,10 +199,10 @@ You can customize the component prefix in your `nuxt.config.ts`:
193
199
 
194
200
  ```ts
195
201
  export default defineNuxtConfig({
196
- modules: ['nuxt-ui-elements'],
202
+ modules: ["nuxt-ui-elements"],
197
203
  uiElements: {
198
- prefix: 'Custom' // Components will be named CustomFlickeringGrid
199
- }
204
+ prefix: "Custom", // Components will be named CustomFlickeringGrid
205
+ },
200
206
  })
201
207
  ```
202
208
 
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.8",
4
+ "version": "0.1.11",
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,115 @@
1
- import { defineNuxtModule, createResolver, useLogger, hasNuxtModule, addComponentsDir } from '@nuxt/kit';
1
+ import { addTemplate, defineNuxtModule, createResolver, addImportsDir } from '@nuxt/kit';
2
+ import { kebabCase } from 'scule';
3
+
4
+ const dialogConfirm = (options) => ({
5
+ slots: {
6
+ content: "divide-y-0 bg-default ring-0",
7
+ header: "relative flex items-center gap-1.5 p-4 sm:px-6 min-h-16",
8
+ icon: "shrink-0 mt-1 size-6",
9
+ title: "text-lg font-semibold",
10
+ description: "text-sm opacity-90",
11
+ body: "p-2 sm:p-5 sm:pt-0",
12
+ footer: "justify-end gap-3",
13
+ close: ""
14
+ },
15
+ variants: {
16
+ size: {
17
+ sm: {
18
+ content: "sm:max-w-md"
19
+ },
20
+ md: {
21
+ content: "sm:max-w-3xl"
22
+ }
23
+ },
24
+ color: {
25
+ ...Object.fromEntries((options.theme.colors || []).map((color) => [color, ""])),
26
+ neutral: ""
27
+ },
28
+ variant: {
29
+ solid: "",
30
+ outline: ""
31
+ }
32
+ },
33
+ compoundVariants: [
34
+ // Solid variants - dynamically generated for all theme colors
35
+ ...(options.theme.colors || []).map((color) => ({
36
+ color,
37
+ variant: "solid",
38
+ class: {
39
+ content: `bg-${color} text-inverted`,
40
+ close: "!text-white hover:bg-white/10 active:bg-white/20"
41
+ }
42
+ })),
43
+ {
44
+ color: "neutral",
45
+ variant: "solid",
46
+ class: {
47
+ content: "text-inverted bg-inverted",
48
+ close: "!text-white hover:bg-white/10 active:bg-white/20"
49
+ }
50
+ },
51
+ // Outline variants - dynamically generated for all theme colors
52
+ ...(options.theme.colors || []).map((color) => ({
53
+ color,
54
+ variant: "outline",
55
+ class: {
56
+ content: `bg-gradient-to-b from-${color}/5 to-${color}/5 bg-default text-${color} !ring !ring-inset !ring-${color}`
57
+ }
58
+ })),
59
+ {
60
+ color: "neutral",
61
+ variant: "outline",
62
+ class: {
63
+ content: "text-highlighted bg-elevated !ring !ring-inset !ring-accented"
64
+ }
65
+ }
66
+ ],
67
+ defaultVariants: {
68
+ color: "primary",
69
+ variant: "solid",
70
+ size: "sm"
71
+ }
72
+ });
73
+
74
+ const theme = {
75
+ __proto__: null,
76
+ dialogConfirm: dialogConfirm
77
+ };
78
+
79
+ function addTemplates(options, _nuxt) {
80
+ const templates = [];
81
+ function writeThemeTemplate(themeModules) {
82
+ for (const component in themeModules) {
83
+ templates.push({
84
+ filename: `ui-elements/${kebabCase(component)}.ts`,
85
+ write: true,
86
+ getContents: () => {
87
+ const template = themeModules[component];
88
+ const result = typeof template === "function" ? template(options) : template;
89
+ const variants = Object.entries(result.variants || {}).filter(([_, values]) => {
90
+ const keys = Object.keys(values);
91
+ return keys.some((key) => key !== "true" && key !== "false");
92
+ }).map(([key]) => key);
93
+ let json = JSON.stringify(result, null, 2);
94
+ for (const variant of variants) {
95
+ json = json.replace(new RegExp(`("${variant}": "[^"]+")`, "g"), `$1 as typeof ${variant}[number]`);
96
+ json = json.replace(new RegExp(`("${variant}": \\[\\s*)((?:"[^"]+",?\\s*)+)(\\])`, "g"), (_, before, match, after) => {
97
+ const replaced = match.replace(/("[^"]+")/g, `$1 as typeof ${variant}[number]`);
98
+ return `${before}${replaced}${after}`;
99
+ });
100
+ }
101
+ const variantDeclarations = variants.filter((variant) => json.includes(`as typeof ${variant}`)).map((variant) => {
102
+ const keys = Object.keys(result.variants[variant]);
103
+ return `const ${variant} = ${JSON.stringify(keys, null, 2)} as const`;
104
+ });
105
+ return [...variantDeclarations, `export default ${json}`].join("\n\n");
106
+ }
107
+ });
108
+ }
109
+ }
110
+ writeThemeTemplate(theme);
111
+ templates.forEach((template) => addTemplate(template));
112
+ }
2
113
 
3
114
  const module$1 = defineNuxtModule({
4
115
  meta: {
@@ -9,20 +120,21 @@ const module$1 = defineNuxtModule({
9
120
  prefix: "UE"
10
121
  },
11
122
  moduleDependencies: {
12
- "motion-v/nuxt": {},
13
- "@nuxtjs/color-mode": {}
123
+ "@nuxt/ui": {}
14
124
  },
15
- setup(options, _nuxt) {
125
+ setup(options, nuxt) {
16
126
  const resolver = createResolver(import.meta.url);
17
- const logger = useLogger("nuxt-ui-elements");
18
- if (!hasNuxtModule("@nuxt/ui")) {
19
- logger.error("[nuxt-ui-elements] @nuxt/ui is required. Please install it");
20
- }
21
- addComponentsDir({
22
- path: resolver.resolve("./runtime/components"),
23
- pathPrefix: false,
24
- prefix: options.prefix
25
- });
127
+ const uiOptions = nuxt.options.ui;
128
+ const themeColors = uiOptions?.theme?.colors || ["primary", "secondary", "success", "info", "warning", "error"];
129
+ const optionsWithTheme = {
130
+ ...options,
131
+ theme: {
132
+ colors: themeColors
133
+ }
134
+ };
135
+ addTemplates(optionsWithTheme);
136
+ nuxt.options.css.push(resolver.resolve("./runtime/index.css"));
137
+ addImportsDir(resolver.resolve("./runtime/composables"));
26
138
  }
27
139
  });
28
140
 
@@ -0,0 +1,49 @@
1
+ import type { AppConfig } from "@nuxt/schema";
2
+ import theme from "#build/ui-elements/dialog-confirm";
3
+ import type { ComponentConfig } from "../types/tv.js";
4
+ type DialogConfirm = ComponentConfig<typeof theme, AppConfig, "dialogConfirm">;
5
+ export interface DialogConfirmEmits {
6
+ "update:open": [value: boolean];
7
+ close: [value?: any];
8
+ "after:leave": [];
9
+ }
10
+ export interface DialogConfirmSlots {
11
+ title(props?: {}): any;
12
+ description(props?: {}): any;
13
+ actions(props?: {}): any;
14
+ }
15
+ export interface DialogConfirmProps {
16
+ title: string;
17
+ description?: string;
18
+ icon?: boolean;
19
+ confirmLabel?: string;
20
+ dismissLabel?: string;
21
+ close?: boolean;
22
+ color?: DialogConfirm["variants"]["color"];
23
+ variant?: DialogConfirm["variants"]["variant"];
24
+ onConfirm?: (() => void) | (() => Promise<void>);
25
+ onDismiss?: () => void;
26
+ ui?: Partial<DialogConfirm["slots"]>;
27
+ }
28
+ declare const _default: typeof __VLS_export;
29
+ export default _default;
30
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<DialogConfirmProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
+ close: (value?: any) => any;
32
+ "update:open": (value: boolean) => any;
33
+ "after:leave": () => any;
34
+ }, string, import("vue").PublicProps, Readonly<DialogConfirmProps> & Readonly<{
35
+ onClose?: ((value?: any) => any) | undefined;
36
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
37
+ "onAfter:leave"?: (() => any) | undefined;
38
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
39
+ title?: (props: {}) => any;
40
+ } & {
41
+ description?: (props: {}) => any;
42
+ } & {
43
+ actions?: (props: {}) => any;
44
+ }>;
45
+ type __VLS_WithSlots<T, S> = T & {
46
+ new (): {
47
+ $slots: S;
48
+ };
49
+ };
@@ -0,0 +1,170 @@
1
+ <script>
2
+ import theme from "#build/ui-elements/dialog-confirm";
3
+ import { computed, ref } from "vue";
4
+ import { DialogTitle, DialogDescription } from "reka-ui";
5
+ import { tv } from "../utils/tv";
6
+ </script>
7
+
8
+ <script setup>
9
+ const {
10
+ title,
11
+ description = "",
12
+ icon = true,
13
+ confirmLabel = "Yes",
14
+ dismissLabel = "No",
15
+ close = false,
16
+ color = "neutral",
17
+ variant = "solid",
18
+ onConfirm,
19
+ onDismiss,
20
+ ui: uiProps
21
+ } = defineProps({
22
+ title: { type: String, required: true },
23
+ description: { type: String, required: false },
24
+ icon: { type: Boolean, required: false },
25
+ confirmLabel: { type: String, required: false },
26
+ dismissLabel: { type: String, required: false },
27
+ close: { type: Boolean, required: false },
28
+ color: { type: null, required: false },
29
+ variant: { type: null, required: false },
30
+ onConfirm: { type: Function, required: false },
31
+ onDismiss: { type: Function, required: false },
32
+ ui: { type: Object, required: false }
33
+ });
34
+ const emits = defineEmits(["update:open", "close", "after:leave"]);
35
+ const isLoading = ref(false);
36
+ const isComplete = ref(false);
37
+ const isError = ref(false);
38
+ const ui = computed(
39
+ () => tv({
40
+ extend: tv(theme)
41
+ })({
42
+ size: "sm",
43
+ color,
44
+ variant
45
+ })
46
+ );
47
+ const colorIconMap = {
48
+ primary: "i-lucide-info",
49
+ secondary: "i-lucide-info",
50
+ success: "i-lucide-circle-check",
51
+ info: "i-lucide-info",
52
+ warning: "i-lucide-triangle-alert",
53
+ error: "i-lucide-circle-x",
54
+ neutral: "i-lucide-info"
55
+ };
56
+ const dialogIcon = computed(() => {
57
+ if (icon === false) return void 0;
58
+ return colorIconMap[color];
59
+ });
60
+ const closeButtonProps = computed(() => ({
61
+ icon: "i-lucide-x",
62
+ size: "md",
63
+ color: "neutral",
64
+ variant: "ghost"
65
+ }));
66
+ const confirmHandler = async () => {
67
+ if (!onConfirm) {
68
+ emits("close");
69
+ return;
70
+ }
71
+ try {
72
+ const result = onConfirm();
73
+ const isAsync = result instanceof Promise;
74
+ if (isAsync) {
75
+ isLoading.value = true;
76
+ await result;
77
+ isLoading.value = false;
78
+ isComplete.value = true;
79
+ setTimeout(() => {
80
+ emits("close");
81
+ }, 800);
82
+ } else {
83
+ emits("close");
84
+ }
85
+ } catch (error) {
86
+ isLoading.value = false;
87
+ isError.value = true;
88
+ console.error("Dialog confirm error:", error);
89
+ setTimeout(() => {
90
+ isError.value = false;
91
+ }, 2e3);
92
+ }
93
+ };
94
+ const dismiss = () => {
95
+ if (onDismiss) {
96
+ onDismiss();
97
+ }
98
+ emits("close");
99
+ };
100
+ const handleClose = () => {
101
+ dismiss();
102
+ };
103
+ </script>
104
+
105
+ <template>
106
+ <UModal
107
+ :dismissible="false"
108
+ :close="false"
109
+ :title="title"
110
+ :description="description"
111
+ :ui="{
112
+ content: ui.content({ class: uiProps?.content }),
113
+ header: ui.header({ class: uiProps?.header }),
114
+ body: ui.body({ class: uiProps?.body }),
115
+ footer: ui.footer({ class: uiProps?.footer })
116
+ }"
117
+ @close="emits('close', $event)"
118
+ @after:leave="emits('after:leave')">
119
+ <template #header>
120
+ <div class="relative w-full flex items-start gap-3">
121
+ <UIcon v-if="dialogIcon" :name="dialogIcon" data-slot="icon" :class="ui.icon({ class: uiProps?.icon })" />
122
+ <div class="flex-1 min-w-0">
123
+ <DialogTitle v-if="title" data-slot="title" :class="ui.title({ class: uiProps?.title })">
124
+ <slot name="title">
125
+ {{ title }}
126
+ </slot>
127
+ </DialogTitle>
128
+
129
+ <DialogDescription v-if="description" :class="ui.description({ class: uiProps?.description })">
130
+ <slot name="description">
131
+ {{ description }}
132
+ </slot>
133
+ </DialogDescription>
134
+ </div>
135
+
136
+ <UButton
137
+ v-if="close"
138
+ v-bind="closeButtonProps"
139
+ data-slot="close"
140
+ :class="ui.close({ class: uiProps?.close })"
141
+ @click="handleClose" />
142
+ </div>
143
+ </template>
144
+
145
+ <template #footer>
146
+ <slot name="actions">
147
+ <!-- Dismiss button (No) - hidden when loading, complete, or error -->
148
+ <UButton
149
+ v-if="dismissLabel && !isLoading && !isComplete && !isError"
150
+ :label="dismissLabel"
151
+ size="lg"
152
+ :color="color"
153
+ variant="solid"
154
+ @click="dismiss" />
155
+
156
+ <!-- Confirm button (Yes) - shows loading/complete/error states -->
157
+ <UButton
158
+ :label="isError ? 'Error' : isComplete ? 'Complete' : confirmLabel"
159
+ size="lg"
160
+ color="neutral"
161
+ variant="outline"
162
+ :loading="isLoading"
163
+ :disabled="isComplete"
164
+ :leading-icon="isError ? 'i-lucide-circle-x' : isComplete ? 'i-lucide-check' : void 0"
165
+ :class="{ 'animate-shake': isError }"
166
+ @click="confirmHandler" />
167
+ </slot>
168
+ </template>
169
+ </UModal>
170
+ </template>
@@ -0,0 +1,49 @@
1
+ import type { AppConfig } from "@nuxt/schema";
2
+ import theme from "#build/ui-elements/dialog-confirm";
3
+ import type { ComponentConfig } from "../types/tv.js";
4
+ type DialogConfirm = ComponentConfig<typeof theme, AppConfig, "dialogConfirm">;
5
+ export interface DialogConfirmEmits {
6
+ "update:open": [value: boolean];
7
+ close: [value?: any];
8
+ "after:leave": [];
9
+ }
10
+ export interface DialogConfirmSlots {
11
+ title(props?: {}): any;
12
+ description(props?: {}): any;
13
+ actions(props?: {}): any;
14
+ }
15
+ export interface DialogConfirmProps {
16
+ title: string;
17
+ description?: string;
18
+ icon?: boolean;
19
+ confirmLabel?: string;
20
+ dismissLabel?: string;
21
+ close?: boolean;
22
+ color?: DialogConfirm["variants"]["color"];
23
+ variant?: DialogConfirm["variants"]["variant"];
24
+ onConfirm?: (() => void) | (() => Promise<void>);
25
+ onDismiss?: () => void;
26
+ ui?: Partial<DialogConfirm["slots"]>;
27
+ }
28
+ declare const _default: typeof __VLS_export;
29
+ export default _default;
30
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<DialogConfirmProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
+ close: (value?: any) => any;
32
+ "update:open": (value: boolean) => any;
33
+ "after:leave": () => any;
34
+ }, string, import("vue").PublicProps, Readonly<DialogConfirmProps> & Readonly<{
35
+ onClose?: ((value?: any) => any) | undefined;
36
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
37
+ "onAfter:leave"?: (() => any) | undefined;
38
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
39
+ title?: (props: {}) => any;
40
+ } & {
41
+ description?: (props: {}) => any;
42
+ } & {
43
+ actions?: (props: {}) => any;
44
+ }>;
45
+ type __VLS_WithSlots<T, S> = T & {
46
+ new (): {
47
+ $slots: S;
48
+ };
49
+ };
File without changes
@@ -0,0 +1,25 @@
1
+ import DialogConfirm from "../components/DialogConfirm.vue";
2
+ import { useOverlay } from "#imports";
3
+ import { navigateTo } from "#app";
4
+ export const useDialog = () => {
5
+ const overlay = useOverlay();
6
+ const confirm = (options) => {
7
+ const modal = overlay.create(DialogConfirm, {
8
+ destroyOnClose: true,
9
+ props: options
10
+ });
11
+ modal.open();
12
+ return modal;
13
+ };
14
+ const confirmNavigate = (path, options) => {
15
+ confirm({
16
+ title: "Leave this page?",
17
+ description: "Are you sure you want to navigate away? Unsaved changes will be lost.",
18
+ ...options,
19
+ onConfirm: () => {
20
+ navigateTo(path);
21
+ }
22
+ });
23
+ };
24
+ return { confirm, confirmNavigate };
25
+ };
@@ -0,0 +1 @@
1
+ @source "../theme";@source "./components";@keyframes shake{0%,to{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-4px)}20%,40%,60%,80%{transform:translateX(4px)}}.animate-shake{animation:shake .5s ease-in-out}
@@ -1,14 +1,64 @@
1
- import type { TV } from "tailwind-variants";
2
- export type ComponentConfig<T extends Record<string, any>> = {
3
- variants: T extends {
4
- variants: infer V;
5
- } ? {
6
- [K in keyof V]: V[K] extends Record<string, any> ? keyof V[K] : never;
7
- } : never;
8
- slots: T extends {
9
- slots: infer S;
10
- } ? {
11
- [K in keyof S]: any;
12
- } : never;
13
- };
14
- export type { TV };
1
+ import type { ClassValue, TVVariants, TVCompoundVariants, TVDefaultVariants } from "tailwind-variants";
2
+ /**
3
+ * Defines the AppConfig object based on the tailwind-variants configuration.
4
+ */
5
+ export type TVConfig<T extends Record<string, any>> = {
6
+ [P in keyof T]?: {
7
+ [K in keyof T[P] as K extends "base" | "slots" | "variants" | "defaultVariants" ? K : never]?: K extends "base" ? ClassValue : K extends "slots" ? {
8
+ [S in keyof T[P]["slots"]]?: ClassValue;
9
+ } : K extends "variants" ? TVVariants<T[P]["slots"], ClassValue, WidenVariantsValues<T[P]["variants"]>> : K extends "defaultVariants" ? TVDefaultVariants<WidenVariantsValues<T[P]["variants"]>, T[P]["slots"], object, undefined> : never;
10
+ };
11
+ } & {
12
+ [P in keyof T]?: {
13
+ compoundVariants?: TVCompoundVariants<WidenVariantsValues<T[P]["variants"]>, T[P]["slots"], ClassValue, object, undefined>;
14
+ };
15
+ };
16
+ type WidenVariantsValues<V extends Record<string, any> | undefined> = V extends Record<string, any> ? V & {
17
+ [K in keyof V]: V[K] extends Record<string, any> ? V[K] & Record<string & {}, any> : V[K];
18
+ } : V;
19
+ /**
20
+ * Utility type to flatten intersection types for better IDE hover information.
21
+ * @template T The type to flatten.
22
+ */
23
+ type Id<T> = {} & {
24
+ [P in keyof T]: T[P];
25
+ };
26
+ type ComponentVariants<T extends {
27
+ variants?: Record<string, Record<string, any>>;
28
+ }> = {
29
+ [K in keyof T["variants"]]: keyof T["variants"][K];
30
+ };
31
+ type ComponentSlots<T extends {
32
+ slots?: Record<string, any>;
33
+ }> = Id<{
34
+ [K in keyof T["slots"]]?: ClassValue;
35
+ }>;
36
+ type ComponentUI<T extends {
37
+ slots?: Record<string, any>;
38
+ }> = Id<{
39
+ [K in keyof Required<T["slots"]>]: (props?: Record<string, any>) => string;
40
+ }>;
41
+ type GetComponentAppConfig<A, U extends string, K extends string> = A extends Record<U, Record<K, any>> ? A[U][K] : {};
42
+ type ComponentAppConfig<T, A extends Record<string, any>, K extends string, U extends string = "ui" | "uiElements"> = A & (U extends "uiElements" ? {
43
+ uiElements?: {
44
+ [k in K]?: Partial<T>;
45
+ };
46
+ } : {
47
+ [key in Exclude<U, "uiElements">]?: {
48
+ [k in K]?: Partial<T>;
49
+ };
50
+ });
51
+ /**
52
+ * Defines the configuration shape expected for a component.
53
+ * @template T The component's theme imported from `#build/ui-elements/*`.
54
+ * @template A The base AppConfig type from `@nuxt/schema`.
55
+ * @template K The key identifying the component (e.g., 'dialogConfirm').
56
+ * @template U The top-level key in AppConfig ('ui' or 'uiElements').
57
+ */
58
+ export type ComponentConfig<T extends Record<string, any>, A extends Record<string, any>, K extends string, U extends "ui" | "uiElements" = "uiElements"> = {
59
+ AppConfig: ComponentAppConfig<T, A, K, U>;
60
+ variants: ComponentVariants<T & GetComponentAppConfig<A, U, K>>;
61
+ slots: ComponentSlots<T>;
62
+ ui: ComponentUI<T>;
63
+ };
64
+ export {};