nuxt-ui-elements 0.1.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.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ <!--
2
+ Get your module up and running quickly.
3
+
4
+ Find and replace all on all files (CMD+SHIFT+F):
5
+ - Name: My Module
6
+ - Package name: my-module
7
+ - Description: My new Nuxt module
8
+ -->
9
+
10
+ # Nuxt UI Elements
11
+
12
+ [![npm version][npm-version-src]][npm-version-href]
13
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
14
+ [![License][license-src]][license-href]
15
+ [![Nuxt][nuxt-src]][nuxt-href]
16
+
17
+ A collection of beautiful, animated UI components for Nuxt applications. Built with Vue 3 and designed to work seamlessly with Nuxt UI.
18
+
19
+ - [✨ &nbsp;Release Notes](/CHANGELOG.md)
20
+
21
+ ## Features
22
+
23
+ - ✨ **FlickeringGrid** - Animated canvas-based grid background with gradient effects
24
+ - 🎨 **Dark Mode Support** - Automatic theme switching with customizable colors
25
+ - 🚀 **Performance Optimized** - Uses IntersectionObserver and only animates when visible
26
+ - 📦 **Auto-import** - Components are automatically available in your app
27
+ - 🎯 **TypeScript** - Full type safety out of the box
28
+ - ⚡️ **Lightweight** - Zero external dependencies
29
+
30
+ ## Quick Setup
31
+
32
+ Install the module to your Nuxt application with one command:
33
+
34
+ ```bash
35
+ pnpm add nuxt-ui-elements
36
+ ```
37
+
38
+ Add the module to your `nuxt.config.ts`:
39
+
40
+ ```ts
41
+ export default defineNuxtConfig({
42
+ modules: ['nuxt-ui-elements']
43
+ })
44
+ ```
45
+
46
+ That's it! You can now use Nuxt UI Elements in your Nuxt app ✨
47
+
48
+ ## Usage
49
+
50
+ ### FlickeringGrid
51
+
52
+ A beautiful animated grid background component perfect for hero sections and landing pages.
53
+
54
+ ```vue
55
+ <template>
56
+ <div class="relative w-full h-screen">
57
+ <UiElementsFlickeringGrid
58
+ :square-size="7"
59
+ :grid-gap="10"
60
+ gradient-direction="left-right"
61
+ gradient-end-color="white"
62
+ :flicker-speed="0.2"
63
+ class="z-0"
64
+ />
65
+ <div class="relative z-10">
66
+ <!-- Your content here -->
67
+ </div>
68
+ </div>
69
+ </template>
70
+ ```
71
+
72
+ #### Props
73
+
74
+ | Prop | Type | Default | Description |
75
+ | ------------------------ | -------- | -------------- | -------------------------------------- |
76
+ | `squareSize` | `number` | `4` | Size of each grid square in pixels |
77
+ | `gridGap` | `number` | `6` | Gap between grid squares |
78
+ | `flickerChance` | `number` | `0.3` | Probability of flicker per frame |
79
+ | `flickerSpeed` | `number` | `1` | Animation speed multiplier |
80
+ | `gradientDirection` | `string` | `'left-right'` | Gradient direction (see options below) |
81
+ | `gradientStartColor` | `string` | `'#aaf'` | Light mode gradient start color |
82
+ | `gradientEndColor` | `string` | `'#fff'` | Light mode gradient end color |
83
+ | `flickerColor` | `string` | `'#fff'` | Light mode flicker color |
84
+ | `darkGradientStartColor` | `string` | `'#23272f'` | Dark mode gradient start color |
85
+ | `darkGradientEndColor` | `string` | `'#353b45'` | Dark mode gradient end color |
86
+ | `darkFlickerColor` | `string` | `'#6b7280'` | Dark mode flicker color |
87
+ | `maxOpacity` | `number` | `0.3` | Maximum opacity of grid squares |
88
+ | `width` | `number` | - | Custom width (defaults to container) |
89
+ | `height` | `number` | - | Custom height (defaults to container) |
90
+ | `class` | `string` | - | Additional CSS classes |
91
+
92
+ #### Gradient Directions
93
+
94
+ - `left-right`
95
+ - `right-left`
96
+ - `top-bottom`
97
+ - `bottom-top`
98
+ - `in-out` (radial from center)
99
+ - `out-in` (radial to center)
100
+ - `top-left-bottom-right`
101
+ - `bottom-right-top-left`
102
+
103
+ ## Configuration
104
+
105
+ You can customize the component prefix in your `nuxt.config.ts`:
106
+
107
+ ```ts
108
+ export default defineNuxtConfig({
109
+ modules: ['nuxt-ui-elements'],
110
+ uiElements: {
111
+ prefix: 'Custom' // Components will be named CustomFlickeringGrid
112
+ }
113
+ })
114
+ ```
115
+
116
+ ## Contribution
117
+
118
+ <details>
119
+ <summary>Local development</summary>
120
+
121
+ ```bash
122
+ # Install dependencies
123
+ npm install
124
+
125
+ # Generate type stubs
126
+ npm run dev:prepare
127
+
128
+ # Develop with the playground
129
+ npm run dev
130
+
131
+ # Build the playground
132
+ npm run dev:build
133
+
134
+ # Run ESLint
135
+ npm run lint
136
+
137
+ # Run Vitest
138
+ npm run test
139
+ npm run test:watch
140
+
141
+ # Release new version
142
+ npm run release
143
+ ```
144
+
145
+ </details>
146
+
147
+ <!-- Badges -->
148
+
149
+ [npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=020420&colorB=00DC82
150
+ [npm-version-href]: https://npmjs.com/package/my-module
151
+ [npm-downloads-src]: https://img.shields.io/npm/dm/my-module.svg?style=flat&colorA=020420&colorB=00DC82
152
+ [npm-downloads-href]: https://npm.chart.dev/my-module
153
+ [license-src]: https://img.shields.io/npm/l/my-module.svg?style=flat&colorA=020420&colorB=00DC82
154
+ [license-href]: https://npmjs.com/package/my-module
155
+ [nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
156
+ [nuxt-href]: https://nuxt.com
@@ -0,0 +1,13 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+
3
+ interface ModuleOptions {
4
+ /**
5
+ * Prefix for component names
6
+ * @default 'UE'
7
+ */
8
+ prefix?: string;
9
+ }
10
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
11
+
12
+ export { _default as default };
13
+ export type { ModuleOptions };
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "nuxt-ui-elements",
3
+ "configKey": "uiElements",
4
+ "version": "0.1.1",
5
+ "builder": {
6
+ "@nuxt/module-builder": "1.0.2",
7
+ "unbuild": "3.6.1"
8
+ }
9
+ }
@@ -0,0 +1,29 @@
1
+ import { defineNuxtModule, createResolver, useLogger, hasNuxtModule, addComponentsDir } from '@nuxt/kit';
2
+
3
+ const module$1 = defineNuxtModule({
4
+ meta: {
5
+ name: "nuxt-ui-elements",
6
+ configKey: "uiElements"
7
+ },
8
+ defaults: {
9
+ prefix: "UE"
10
+ },
11
+ moduleDependencies: {
12
+ "motion-v/nuxt": {}
13
+ },
14
+ setup(options, _nuxt) {
15
+ const resolver = createResolver(import.meta.url);
16
+ const logger = useLogger("nuxt-ui-elements");
17
+ if (!hasNuxtModule("@nuxt/ui")) {
18
+ logger.error("[nuxt-ui-elements] @nuxt/ui is required. Please install it");
19
+ }
20
+ addComponentsDir({
21
+ path: resolver.resolve("./runtime/components/background"),
22
+ pathPrefix: false,
23
+ prefix: `${options.prefix}Background`,
24
+ global: true
25
+ });
26
+ }
27
+ });
28
+
29
+ export { module$1 as default };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Aurora - An animated aurora background component with gradient effects
3
+ */
4
+ export type AuroraVariant = "calm" | "energetic" | "cosmic";
5
+ export interface AuroraProps {
6
+ /**
7
+ * Pin the aurora to a specific corner or edge
8
+ * If undefined, aurora flows across the entire screen without mask
9
+ * @default 'top-right'
10
+ */
11
+ pin?: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
12
+ /**
13
+ * Color variant
14
+ * @default 'primary'
15
+ */
16
+ color?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
17
+ /**
18
+ * Speed of the animation (0-100, where 100 is fastest)
19
+ * @default 50
20
+ */
21
+ speed?: number;
22
+ /**
23
+ * Intensity of the aurora effect (0-100)
24
+ * Controls opacity and blur
25
+ * @default 50
26
+ */
27
+ intensity?: number;
28
+ /**
29
+ * Animation style variant
30
+ * Overrides speed and intensity when set
31
+ */
32
+ variant?: AuroraVariant;
33
+ /**
34
+ * Reverse the animation direction
35
+ * @default false
36
+ */
37
+ reverse?: boolean;
38
+ /**
39
+ * Additional CSS classes for the container
40
+ */
41
+ class?: any;
42
+ }
43
+ export interface AuroraSlots {
44
+ /**
45
+ * Default slot content rendered on top of the aurora
46
+ */
47
+ default(): any;
48
+ }
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
51
+ declare const __VLS_export: __VLS_WithSlots<import("@vue/runtime-core").DefineComponent<AuroraProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
52
+ pin: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
53
+ color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
54
+ speed: number;
55
+ intensity: number;
56
+ reverse: boolean;
57
+ }, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
58
+ type __VLS_WithSlots<T, S> = T & {
59
+ new (): {
60
+ $slots: S;
61
+ };
62
+ };
@@ -0,0 +1,120 @@
1
+ <script>
2
+
3
+ </script>
4
+
5
+ <script setup>
6
+ import { computed } from "vue";
7
+ import {
8
+ adjustLightness,
9
+ getThemeColor,
10
+ oklchToRgb
11
+ } from "../../composables/useThemeColors";
12
+ import { createRepeatingGradient } from "../../composables/useGradient";
13
+ const props = defineProps({
14
+ pin: { type: String, required: false, default: "top-right" },
15
+ color: { type: String, required: false, default: "primary" },
16
+ speed: { type: Number, required: false, default: 50 },
17
+ intensity: { type: Number, required: false, default: 50 },
18
+ variant: { type: String, required: false },
19
+ reverse: { type: Boolean, required: false, default: false },
20
+ class: { type: null, required: false }
21
+ });
22
+ defineSlots();
23
+ const variants = {
24
+ calm: { speed: 20, intensity: 30, blur: 15 },
25
+ energetic: { speed: 80, intensity: 70, blur: 8 },
26
+ cosmic: { speed: 50, intensity: 90, blur: 12 }
27
+ };
28
+ const effectiveSpeed = computed(
29
+ () => props.variant ? variants[props.variant].speed : props.speed
30
+ );
31
+ const effectiveIntensity = computed(
32
+ () => props.variant ? variants[props.variant].intensity : props.intensity
33
+ );
34
+ const effectiveBlur = computed(
35
+ () => props.variant ? variants[props.variant].blur : 10
36
+ );
37
+ const baseColor = computed(() => getThemeColor(props.color, 500));
38
+ const auroraColors = computed(() => {
39
+ const base = baseColor.value;
40
+ return [
41
+ oklchToRgb(adjustLightness(base, 60)),
42
+ oklchToRgb(adjustLightness(base, 75)),
43
+ oklchToRgb(adjustLightness(base, 70)),
44
+ oklchToRgb(adjustLightness(base, 80)),
45
+ oklchToRgb(adjustLightness(base, 65))
46
+ ];
47
+ });
48
+ const auroraColorsDark = computed(() => {
49
+ const base = baseColor.value;
50
+ return [
51
+ oklchToRgb(adjustLightness(base, 30)),
52
+ oklchToRgb(adjustLightness(base, 45)),
53
+ oklchToRgb(adjustLightness(base, 40)),
54
+ oklchToRgb(adjustLightness(base, 50)),
55
+ oklchToRgb(adjustLightness(base, 35))
56
+ ];
57
+ });
58
+ const auroraGradient = computed(
59
+ () => createRepeatingGradient(auroraColors.value, 100)
60
+ );
61
+ const auroraGradientDark = computed(
62
+ () => createRepeatingGradient(auroraColorsDark.value, 100)
63
+ );
64
+ const animationDuration = computed(() => {
65
+ const clampedSpeed = Math.max(1, Math.min(100, effectiveSpeed.value));
66
+ const duration = 120 - clampedSpeed * 0.9;
67
+ return `${duration}s`;
68
+ });
69
+ const animationState = computed(
70
+ () => effectiveSpeed.value === 0 ? "paused" : "running"
71
+ );
72
+ const animationDirection = computed(
73
+ () => props.reverse ? "reverse" : "normal"
74
+ );
75
+ const auroraOpacity = computed(() => {
76
+ const clampedIntensity = Math.max(0, Math.min(100, effectiveIntensity.value));
77
+ return clampedIntensity / 100;
78
+ });
79
+ const auroraBlur = computed(() => `${effectiveBlur.value}px`);
80
+ const maskGradient = computed(() => {
81
+ if (!props.pin) return void 0;
82
+ const positions = {
83
+ "top-left": "ellipse at 0% 0%",
84
+ "top-right": "ellipse at 100% 0%",
85
+ "bottom-left": "ellipse at 0% 100%",
86
+ "bottom-right": "ellipse at 100% 100%",
87
+ top: "ellipse at 50% 0%",
88
+ bottom: "ellipse at 50% 100%",
89
+ left: "ellipse at 0% 50%",
90
+ right: "ellipse at 100% 50%"
91
+ };
92
+ return `radial-gradient(${positions[props.pin]}, black 10%, transparent 70%)`;
93
+ });
94
+ </script>
95
+
96
+ <template>
97
+ <div
98
+ class="relative flex h-full w-full items-center justify-center bg-zinc-50 text-slate-950 transition-bg dark:bg-zinc-900"
99
+ >
100
+ <div
101
+ class="absolute inset-0 overflow-hidden"
102
+ :style="maskGradient ? { maskImage: maskGradient } : {}"
103
+ >
104
+ <ClientOnly>
105
+ <div
106
+ class="aurora-effect pointer-events-none absolute -inset-2.5 h-full w-full will-change-transform animate-in fade-in duration-1000"
107
+ :style="{ opacity: auroraOpacity }"
108
+ />
109
+ </ClientOnly>
110
+ </div>
111
+
112
+ <div class="relative z-10">
113
+ <slot />
114
+ </div>
115
+ </div>
116
+ </template>
117
+
118
+ <style scoped>
119
+ .aurora-effect{background-size:200%,100%;filter:blur(v-bind(auroraBlur)) invert(1)}.aurora-effect,.aurora-effect:after{animation:aurora v-bind(animationDuration) linear infinite;animation-direction:v-bind(animationDirection);animation-play-state:v-bind(animationState);background-image:repeating-linear-gradient(100deg,#fff,#fff 7%,transparent 10%,transparent 12%,#fff 16%),v-bind(auroraGradient);background-position:50% 50%,50% 50%}.aurora-effect:after{background-attachment:fixed;background-size:180%,100%;content:"";inset:0;mix-blend-mode:difference;position:absolute}:global(.dark) .aurora-effect{background-image:repeating-linear-gradient(100deg,#000,#000 7%,transparent 10%,transparent 12%,#000 16%),v-bind(auroraGradientDark);filter:blur(10px) invert(0)}:global(.dark) .aurora-effect:after{background-image:repeating-linear-gradient(100deg,rgba(0,0,0,.3),rgba(0,0,0,.3) 7%,transparent 10%,transparent 12%,rgba(0,0,0,.3) 16%),v-bind(auroraGradientDark);opacity:.3}@keyframes aurora{0%{background-position:50% 50%,50% 50%}to{background-position:350% 50%,350% 50%}}
120
+ </style>
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Aurora - An animated aurora background component with gradient effects
3
+ */
4
+ export type AuroraVariant = "calm" | "energetic" | "cosmic";
5
+ export interface AuroraProps {
6
+ /**
7
+ * Pin the aurora to a specific corner or edge
8
+ * If undefined, aurora flows across the entire screen without mask
9
+ * @default 'top-right'
10
+ */
11
+ pin?: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
12
+ /**
13
+ * Color variant
14
+ * @default 'primary'
15
+ */
16
+ color?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
17
+ /**
18
+ * Speed of the animation (0-100, where 100 is fastest)
19
+ * @default 50
20
+ */
21
+ speed?: number;
22
+ /**
23
+ * Intensity of the aurora effect (0-100)
24
+ * Controls opacity and blur
25
+ * @default 50
26
+ */
27
+ intensity?: number;
28
+ /**
29
+ * Animation style variant
30
+ * Overrides speed and intensity when set
31
+ */
32
+ variant?: AuroraVariant;
33
+ /**
34
+ * Reverse the animation direction
35
+ * @default false
36
+ */
37
+ reverse?: boolean;
38
+ /**
39
+ * Additional CSS classes for the container
40
+ */
41
+ class?: any;
42
+ }
43
+ export interface AuroraSlots {
44
+ /**
45
+ * Default slot content rendered on top of the aurora
46
+ */
47
+ default(): any;
48
+ }
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
51
+ declare const __VLS_export: __VLS_WithSlots<import("@vue/runtime-core").DefineComponent<AuroraProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
52
+ pin: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
53
+ color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
54
+ speed: number;
55
+ intensity: number;
56
+ reverse: boolean;
57
+ }, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
58
+ type __VLS_WithSlots<T, S> = T & {
59
+ new (): {
60
+ $slots: S;
61
+ };
62
+ };
@@ -0,0 +1,94 @@
1
+ import type { ComponentConfig } from "../../types/tv.js";
2
+ import backgroundFlickeringGridTheme from "../../themes/background-flickering-grid.js";
3
+ type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridTheme>;
4
+ /**
5
+ * FlickeringGrid - An animated canvas-based grid background component
6
+ */
7
+ export interface FlickeringGridProps {
8
+ /**
9
+ * The square size of the grid (before scaling)
10
+ * @default 12
11
+ */
12
+ squareSize?: number;
13
+ /**
14
+ * The gap between grid squares
15
+ * @default 6
16
+ */
17
+ gridGap?: number;
18
+ /**
19
+ * The flicker animation speed (higher = faster)
20
+ * @default 0.3
21
+ */
22
+ flickerChance?: number;
23
+ /**
24
+ * Speed multiplier for flicker animation
25
+ * @default 1
26
+ */
27
+ flickerSpeed?: number;
28
+ /**
29
+ * Gradient direction for the grid
30
+ * @default 'left-right'
31
+ */
32
+ gradientDirection?: "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in" | "top-left-bottom-right" | "bottom-right-top-left";
33
+ /**
34
+ * Maximum opacity of flickering squares
35
+ * @default 0.3
36
+ */
37
+ maxOpacity?: number;
38
+ /**
39
+ * Apply radial fade to edges
40
+ * @default true
41
+ */
42
+ fade?: boolean;
43
+ /**
44
+ * Canvas width (defaults to container width)
45
+ */
46
+ width?: number;
47
+ /**
48
+ * Canvas height (defaults to container height)
49
+ */
50
+ height?: number;
51
+ /**
52
+ * Color variant
53
+ * @default 'neutral'
54
+ */
55
+ color?: BackgroundFlickeringGrid["variants"]["color"];
56
+ /**
57
+ * Style variant
58
+ * @default 'subtle'
59
+ */
60
+ variant?: BackgroundFlickeringGrid["variants"]["variant"];
61
+ /**
62
+ * Additional CSS classes for the container
63
+ */
64
+ class?: any;
65
+ /**
66
+ * UI slot customization
67
+ */
68
+ ui?: BackgroundFlickeringGrid["slots"];
69
+ }
70
+ export interface FlickeringGridSlots {
71
+ /**
72
+ * Default slot content rendered on top of the grid
73
+ */
74
+ default(): any;
75
+ }
76
+ declare const _default: typeof __VLS_export;
77
+ export default _default;
78
+ declare const __VLS_export: __VLS_WithSlots<import("@vue/runtime-core").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {
79
+ color: BackgroundFlickeringGrid["variants"]["color"];
80
+ variant: BackgroundFlickeringGrid["variants"]["variant"];
81
+ class: any;
82
+ squareSize: number;
83
+ gridGap: number;
84
+ flickerChance: number;
85
+ flickerSpeed: number;
86
+ gradientDirection: "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in" | "top-left-bottom-right" | "bottom-right-top-left";
87
+ maxOpacity: number;
88
+ fade: boolean;
89
+ }, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, FlickeringGridSlots>;
90
+ type __VLS_WithSlots<T, S> = T & {
91
+ new (): {
92
+ $slots: S;
93
+ };
94
+ };
@@ -0,0 +1,226 @@
1
+ <script>
2
+ import backgroundFlickeringGridTheme from "../../themes/background-flickering-grid";
3
+ </script>
4
+
5
+ <script setup>
6
+ import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
7
+ import { tv } from "../../utils/tv";
8
+ import { calculateGradientIntensity } from "../../composables/useGradient";
9
+ import theme from "../../themes/background-flickering-grid";
10
+ import { getThemeColor, adjustLightness, oklchToRgb } from "../../composables/useThemeColors";
11
+ const props = defineProps({
12
+ squareSize: { type: Number, required: false, default: 8 },
13
+ gridGap: { type: Number, required: false, default: 8 },
14
+ flickerChance: { type: Number, required: false, default: 0.3 },
15
+ flickerSpeed: { type: Number, required: false, default: 0.2 },
16
+ gradientDirection: { type: String, required: false, default: "left-right" },
17
+ maxOpacity: { type: Number, required: false, default: 0.3 },
18
+ fade: { type: Boolean, required: false, default: true },
19
+ width: { type: Number, required: false },
20
+ height: { type: Number, required: false },
21
+ color: { type: null, required: false, default: "neutral" },
22
+ variant: { type: null, required: false, default: "subtle" },
23
+ class: { type: null, required: false, default: "" },
24
+ ui: { type: null, required: false }
25
+ });
26
+ defineSlots();
27
+ const ui = computed(
28
+ () => tv(theme)({
29
+ color: props.color,
30
+ variant: props.variant
31
+ })
32
+ );
33
+ const maskStyle = computed(() => {
34
+ if (!props.fade) return {};
35
+ return {
36
+ maskImage: "radial-gradient(circle at center, black 20%, transparent 90%)",
37
+ WebkitMaskImage: "radial-gradient(circle at center, black 20%, transparent 90%)"
38
+ };
39
+ });
40
+ const containerRef = ref();
41
+ const canvasRef = ref();
42
+ const context = ref(null);
43
+ const isInView = ref(false);
44
+ const canvasSize = ref({ width: 0, height: 0 });
45
+ const gridParams = ref(null);
46
+ function parseColor(color) {
47
+ const match = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
48
+ if (match && match[1] && match[2] && match[3]) {
49
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
50
+ }
51
+ return [255, 255, 255];
52
+ }
53
+ const gridColors = computed(() => {
54
+ const baseColor = getThemeColor(props.color, 500);
55
+ const lightnessMap = {
56
+ subtle: { start: 96, end: 98, flicker: 93 },
57
+ soft: { start: 92, end: 96, flicker: 88 },
58
+ solid: { start: 80, end: 92, flicker: 70 }
59
+ };
60
+ const lightness = lightnessMap[props.variant];
61
+ const startRgb = oklchToRgb(adjustLightness(baseColor, lightness.start));
62
+ const endRgb = oklchToRgb(adjustLightness(baseColor, lightness.end));
63
+ const flickerRgb = oklchToRgb(adjustLightness(baseColor, lightness.flicker));
64
+ return {
65
+ start: parseColor(startRgb),
66
+ end: parseColor(endRgb),
67
+ flicker: parseColor(flickerRgb)
68
+ };
69
+ });
70
+ function lerp(a, b, t) {
71
+ return a + (b - a) * t;
72
+ }
73
+ function lerpColor(a, b, t) {
74
+ if (!a || a.length !== 3) a = [255, 255, 255];
75
+ if (!b || b.length !== 3) b = [255, 255, 255];
76
+ return [
77
+ Math.round(lerp(a[0], b[0], t)),
78
+ Math.round(lerp(a[1], b[1], t)),
79
+ Math.round(lerp(a[2], b[2], t))
80
+ ];
81
+ }
82
+ function rgbToString(rgb, alpha = 1) {
83
+ return `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${alpha})`;
84
+ }
85
+ function getGradientT(i, j, cols, rows) {
86
+ const x = cols > 1 ? i / (cols - 1) : 0.5;
87
+ const y = rows > 1 ? j / (rows - 1) : 0.5;
88
+ return calculateGradientIntensity(x, y, props.gradientDirection);
89
+ }
90
+ function setupCanvas(canvas, width, height) {
91
+ const dpr = window.devicePixelRatio || 1;
92
+ canvas.width = width * dpr;
93
+ canvas.height = height * dpr;
94
+ canvas.style.width = `${width}px`;
95
+ canvas.style.height = `${height}px`;
96
+ const cols = Math.floor(width / (props.squareSize + props.gridGap));
97
+ const rows = Math.floor(height / (props.squareSize + props.gridGap));
98
+ const squares = new Float32Array(cols * rows);
99
+ for (let i = 0; i < squares.length; i++) {
100
+ squares[i] = Math.random() * props.maxOpacity;
101
+ }
102
+ return { cols, rows, squares, dpr };
103
+ }
104
+ function updateSquares(squares, deltaTime) {
105
+ for (let i = 0; i < squares.length; i++) {
106
+ if (Math.random() < props.flickerChance * props.flickerSpeed * deltaTime) {
107
+ squares[i] = Math.random() * props.maxOpacity;
108
+ }
109
+ }
110
+ }
111
+ function drawGrid(ctx, width, height, cols, rows, squares, dpr) {
112
+ ctx.clearRect(0, 0, width, height);
113
+ ctx.fillStyle = "transparent";
114
+ ctx.fillRect(0, 0, width, height);
115
+ const colors = gridColors.value;
116
+ for (let i = 0; i < cols; i++) {
117
+ for (let j = 0; j < rows; j++) {
118
+ const idx = i * rows + j;
119
+ const opacity = squares[idx] ?? 0;
120
+ const t = getGradientT(i, j, cols, rows);
121
+ const baseColor = lerpColor(colors.start, colors.end, t);
122
+ let cellColor = baseColor;
123
+ let cellAlpha = opacity;
124
+ if (opacity > 0.5 * props.maxOpacity) {
125
+ const blendT = (opacity - 0.5 * props.maxOpacity) / (0.5 * props.maxOpacity);
126
+ cellColor = lerpColor(baseColor, colors.flicker, blendT);
127
+ cellAlpha = Math.min(1, opacity + 0.2);
128
+ }
129
+ ctx.fillStyle = rgbToString(cellColor, cellAlpha);
130
+ ctx.fillRect(
131
+ i * (props.squareSize + props.gridGap) * dpr,
132
+ j * (props.squareSize + props.gridGap) * dpr,
133
+ props.squareSize * dpr,
134
+ props.squareSize * dpr
135
+ );
136
+ }
137
+ }
138
+ }
139
+ function updateCanvasSize() {
140
+ const newWidth = props.width || containerRef.value?.clientWidth || 0;
141
+ const newHeight = props.height || containerRef.value?.clientHeight || 0;
142
+ canvasSize.value = { width: newWidth, height: newHeight };
143
+ if (canvasRef.value) {
144
+ gridParams.value = setupCanvas(canvasRef.value, newWidth, newHeight);
145
+ }
146
+ }
147
+ let animationFrameId;
148
+ let resizeObserver;
149
+ let intersectionObserver;
150
+ let lastTime = 0;
151
+ function animate(time) {
152
+ if (!isInView.value || !gridParams.value || !context.value) return;
153
+ const deltaTime = (time - lastTime) / 1e3;
154
+ lastTime = time;
155
+ updateSquares(gridParams.value.squares, deltaTime);
156
+ drawGrid(
157
+ context.value,
158
+ canvasRef.value.width,
159
+ canvasRef.value.height,
160
+ gridParams.value.cols,
161
+ gridParams.value.rows,
162
+ gridParams.value.squares,
163
+ gridParams.value.dpr
164
+ );
165
+ animationFrameId = requestAnimationFrame(animate);
166
+ }
167
+ onMounted(() => {
168
+ if (!canvasRef.value || !containerRef.value) return;
169
+ context.value = canvasRef.value.getContext("2d");
170
+ if (!context.value) return;
171
+ updateCanvasSize();
172
+ resizeObserver = new ResizeObserver(() => {
173
+ updateCanvasSize();
174
+ });
175
+ intersectionObserver = new IntersectionObserver(
176
+ (entries) => {
177
+ const entry = entries[0];
178
+ if (!entry) return;
179
+ isInView.value = entry.isIntersecting;
180
+ if (isInView.value) {
181
+ lastTime = performance.now();
182
+ animationFrameId = requestAnimationFrame(animate);
183
+ }
184
+ },
185
+ { threshold: 0 }
186
+ );
187
+ resizeObserver.observe(containerRef.value);
188
+ intersectionObserver.observe(canvasRef.value);
189
+ });
190
+ onBeforeUnmount(() => {
191
+ if (animationFrameId) cancelAnimationFrame(animationFrameId);
192
+ resizeObserver?.disconnect();
193
+ intersectionObserver?.disconnect();
194
+ });
195
+ watch(
196
+ [
197
+ () => props.gradientDirection,
198
+ () => props.squareSize,
199
+ () => props.gridGap,
200
+ () => props.maxOpacity,
201
+ () => props.color,
202
+ () => props.variant
203
+ ],
204
+ () => {
205
+ updateCanvasSize();
206
+ }
207
+ );
208
+ </script>
209
+
210
+ <template>
211
+ <div
212
+ ref="containerRef"
213
+ data-slot="base"
214
+ :class="ui.base({ class: [props.ui?.base, props.class] })"
215
+ >
216
+ <canvas
217
+ ref="canvasRef"
218
+ data-slot="canvas"
219
+ :class="ui.canvas({ class: props.ui?.canvas })"
220
+ :style="maskStyle"
221
+ :width="canvasSize.width"
222
+ :height="canvasSize.height"
223
+ />
224
+ <slot />
225
+ </div>
226
+ </template>
@@ -0,0 +1,94 @@
1
+ import type { ComponentConfig } from "../../types/tv.js";
2
+ import backgroundFlickeringGridTheme from "../../themes/background-flickering-grid.js";
3
+ type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridTheme>;
4
+ /**
5
+ * FlickeringGrid - An animated canvas-based grid background component
6
+ */
7
+ export interface FlickeringGridProps {
8
+ /**
9
+ * The square size of the grid (before scaling)
10
+ * @default 12
11
+ */
12
+ squareSize?: number;
13
+ /**
14
+ * The gap between grid squares
15
+ * @default 6
16
+ */
17
+ gridGap?: number;
18
+ /**
19
+ * The flicker animation speed (higher = faster)
20
+ * @default 0.3
21
+ */
22
+ flickerChance?: number;
23
+ /**
24
+ * Speed multiplier for flicker animation
25
+ * @default 1
26
+ */
27
+ flickerSpeed?: number;
28
+ /**
29
+ * Gradient direction for the grid
30
+ * @default 'left-right'
31
+ */
32
+ gradientDirection?: "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in" | "top-left-bottom-right" | "bottom-right-top-left";
33
+ /**
34
+ * Maximum opacity of flickering squares
35
+ * @default 0.3
36
+ */
37
+ maxOpacity?: number;
38
+ /**
39
+ * Apply radial fade to edges
40
+ * @default true
41
+ */
42
+ fade?: boolean;
43
+ /**
44
+ * Canvas width (defaults to container width)
45
+ */
46
+ width?: number;
47
+ /**
48
+ * Canvas height (defaults to container height)
49
+ */
50
+ height?: number;
51
+ /**
52
+ * Color variant
53
+ * @default 'neutral'
54
+ */
55
+ color?: BackgroundFlickeringGrid["variants"]["color"];
56
+ /**
57
+ * Style variant
58
+ * @default 'subtle'
59
+ */
60
+ variant?: BackgroundFlickeringGrid["variants"]["variant"];
61
+ /**
62
+ * Additional CSS classes for the container
63
+ */
64
+ class?: any;
65
+ /**
66
+ * UI slot customization
67
+ */
68
+ ui?: BackgroundFlickeringGrid["slots"];
69
+ }
70
+ export interface FlickeringGridSlots {
71
+ /**
72
+ * Default slot content rendered on top of the grid
73
+ */
74
+ default(): any;
75
+ }
76
+ declare const _default: typeof __VLS_export;
77
+ export default _default;
78
+ declare const __VLS_export: __VLS_WithSlots<import("@vue/runtime-core").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {
79
+ color: BackgroundFlickeringGrid["variants"]["color"];
80
+ variant: BackgroundFlickeringGrid["variants"]["variant"];
81
+ class: any;
82
+ squareSize: number;
83
+ gridGap: number;
84
+ flickerChance: number;
85
+ flickerSpeed: number;
86
+ gradientDirection: "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in" | "top-left-bottom-right" | "bottom-right-top-left";
87
+ maxOpacity: number;
88
+ fade: boolean;
89
+ }, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, FlickeringGridSlots>;
90
+ type __VLS_WithSlots<T, S> = T & {
91
+ new (): {
92
+ $slots: S;
93
+ };
94
+ };
@@ -0,0 +1,23 @@
1
+ export type GradientDirection = "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in" | "top-left-bottom-right" | "bottom-right-top-left";
2
+ /**
3
+ * Calculate gradient intensity for a position based on direction
4
+ * @param x - X coordinate (0-1)
5
+ * @param y - Y coordinate (0-1)
6
+ * @param direction - Gradient direction
7
+ * @returns Intensity value (0-1)
8
+ */
9
+ export declare function calculateGradientIntensity(x: number, y: number, direction: GradientDirection): number;
10
+ /**
11
+ * Generate CSS repeating linear gradient from colors
12
+ * @param colors - Array of RGB color strings
13
+ * @param angle - Gradient angle in degrees
14
+ * @returns CSS repeating-linear-gradient string
15
+ */
16
+ export declare function createRepeatingGradient(colors: string[], angle?: number): string;
17
+ /**
18
+ * Composable for gradient utilities
19
+ */
20
+ export declare function useGradient(): {
21
+ calculateGradientIntensity: typeof calculateGradientIntensity;
22
+ createRepeatingGradient: typeof createRepeatingGradient;
23
+ };
@@ -0,0 +1,41 @@
1
+ export function calculateGradientIntensity(x, y, direction) {
2
+ switch (direction) {
3
+ case "left-right":
4
+ return x;
5
+ case "right-left":
6
+ return 1 - x;
7
+ case "top-bottom":
8
+ return y;
9
+ case "bottom-top":
10
+ return 1 - y;
11
+ case "in-out": {
12
+ const dx = x - 0.5;
13
+ const dy = y - 0.5;
14
+ return Math.sqrt(dx * dx + dy * dy) * Math.sqrt(2);
15
+ }
16
+ case "out-in": {
17
+ const dx = x - 0.5;
18
+ const dy = y - 0.5;
19
+ return 1 - Math.sqrt(dx * dx + dy * dy) * Math.sqrt(2);
20
+ }
21
+ case "top-left-bottom-right":
22
+ return (x + y) / 2;
23
+ case "bottom-right-top-left":
24
+ return 1 - (x + y) / 2;
25
+ default:
26
+ return 0;
27
+ }
28
+ }
29
+ export function createRepeatingGradient(colors, angle = 100) {
30
+ const stops = colors.map((color, i) => {
31
+ const position = 10 + i * 5;
32
+ return `${color} ${position}%`;
33
+ }).join(",");
34
+ return `repeating-linear-gradient(${angle}deg,${stops})`;
35
+ }
36
+ export function useGradient() {
37
+ return {
38
+ calculateGradientIntensity,
39
+ createRepeatingGradient
40
+ };
41
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Parse OKLCH string to extract L, C, H components
3
+ * @deprecated Use culori.parse instead
4
+ */
5
+ export declare function parseOklch(oklchStr: string): {
6
+ l: number;
7
+ c: number;
8
+ h: number;
9
+ } | null;
10
+ /**
11
+ * Create OKLCH string from L, C, H components
12
+ */
13
+ export declare function createOklch(l: number, c: number, h: number): string;
14
+ /**
15
+ * Adjust the lightness of a color while preserving chroma and hue
16
+ * Accepts any valid CSS color string
17
+ */
18
+ export declare function adjustLightness(colorStr: string, targetLightness: number): string;
19
+ /**
20
+ * Adjust the chroma (saturation) of a color while preserving lightness and hue
21
+ */
22
+ export declare function adjustChroma(colorStr: string, targetChroma: number): string;
23
+ /**
24
+ * Adjust the hue of a color while preserving lightness and chroma
25
+ */
26
+ export declare function adjustHue(colorStr: string, targetHue: number): string;
27
+ /**
28
+ * Adjust all components of a color
29
+ */
30
+ export declare function adjustOklch(colorStr: string, adjustments: {
31
+ l?: number;
32
+ c?: number;
33
+ h?: number;
34
+ }): string;
35
+ /**
36
+ * Convert color to RGB string for canvas rendering
37
+ */
38
+ export declare function oklchToRgb(colorString: string): string;
39
+ /**
40
+ * Get the base color from Nuxt UI theme for a given color name and shade
41
+ * @param colorName - The semantic color name (e.g., 'primary', 'error', 'success')
42
+ * @param shade - The color shade (50-950), defaults to 500
43
+ */
44
+ export declare function getThemeColor(colorName: string, shade?: number): string;
45
+ /**
46
+ * Get multiple shades of a color by adjusting lightness
47
+ * Useful for creating gradients or multi-tone effects
48
+ */
49
+ export declare function getColorShades(colorName: string, lightnessValues: number[]): string[];
50
+ /**
51
+ * Get multiple shades and convert to RGB
52
+ */
53
+ export declare function getColorShadesRgb(colorName: string, lightnessValues: number[]): string[];
54
+ /**
55
+ * Create a color palette with custom adjustments
56
+ * Returns RGB strings ready for canvas use
57
+ */
58
+ export declare function createColorPalette(colorName: string, adjustments: Array<{
59
+ l?: number;
60
+ c?: number;
61
+ h?: number;
62
+ }>): string[];
@@ -0,0 +1,87 @@
1
+ import { converter, parse, formatCss } from "culori";
2
+ const toOklch = converter("oklch");
3
+ const toRgb = converter("rgb");
4
+ export function parseOklch(oklchStr) {
5
+ const parsed = parse(oklchStr);
6
+ if (!parsed) return null;
7
+ const oklch = toOklch(parsed);
8
+ if (!oklch) return null;
9
+ return {
10
+ l: (oklch.l ?? 0) * 100,
11
+ // Convert 0-1 to 0-100%
12
+ c: oklch.c ?? 0,
13
+ h: oklch.h ?? 0
14
+ };
15
+ }
16
+ export function createOklch(l, c, h) {
17
+ return formatCss({ mode: "oklch", l: l / 100, c, h });
18
+ }
19
+ export function adjustLightness(colorStr, targetLightness) {
20
+ const parsed = parse(colorStr);
21
+ if (!parsed) return colorStr;
22
+ const oklch = toOklch(parsed);
23
+ if (!oklch) return colorStr;
24
+ oklch.l = targetLightness / 100;
25
+ return formatCss(oklch);
26
+ }
27
+ export function adjustChroma(colorStr, targetChroma) {
28
+ const parsed = parse(colorStr);
29
+ if (!parsed) return colorStr;
30
+ const oklch = toOklch(parsed);
31
+ if (!oklch) return colorStr;
32
+ oklch.c = targetChroma;
33
+ return formatCss(oklch);
34
+ }
35
+ export function adjustHue(colorStr, targetHue) {
36
+ const parsed = parse(colorStr);
37
+ if (!parsed) return colorStr;
38
+ const oklch = toOklch(parsed);
39
+ if (!oklch) return colorStr;
40
+ oklch.h = targetHue;
41
+ return formatCss(oklch);
42
+ }
43
+ export function adjustOklch(colorStr, adjustments) {
44
+ const parsed = parse(colorStr);
45
+ if (!parsed) return colorStr;
46
+ const oklch = toOklch(parsed);
47
+ if (!oklch) return colorStr;
48
+ if (adjustments.l !== void 0) oklch.l = adjustments.l / 100;
49
+ if (adjustments.c !== void 0) oklch.c = adjustments.c;
50
+ if (adjustments.h !== void 0) oklch.h = adjustments.h;
51
+ return formatCss(oklch);
52
+ }
53
+ export function oklchToRgb(colorString) {
54
+ const parsed = parse(colorString);
55
+ if (!parsed) return "rgb(255, 255, 255)";
56
+ const rgb = toRgb(parsed);
57
+ if (!rgb) return "rgb(255, 255, 255)";
58
+ const r = Math.max(0, Math.min(255, Math.round((rgb.r ?? 0) * 255)));
59
+ const g = Math.max(0, Math.min(255, Math.round((rgb.g ?? 0) * 255)));
60
+ const b = Math.max(0, Math.min(255, Math.round((rgb.b ?? 0) * 255)));
61
+ const a = rgb.alpha ?? 1;
62
+ return a < 1 ? `rgba(${r}, ${g}, ${b}, ${a})` : `rgb(${r}, ${g}, ${b})`;
63
+ }
64
+ export function getThemeColor(colorName, shade = 500) {
65
+ if (typeof document === "undefined") return "oklch(50% 0 0)";
66
+ const styles = getComputedStyle(document.documentElement);
67
+ let colorValue = styles.getPropertyValue(`--ui-color-${colorName}-${shade}`).trim();
68
+ if (!colorValue) {
69
+ colorValue = styles.getPropertyValue(`--color-${colorName}-${shade}`).trim();
70
+ }
71
+ return colorValue || "oklch(50% 0 0)";
72
+ }
73
+ export function getColorShades(colorName, lightnessValues) {
74
+ const baseColor = getThemeColor(colorName, 500);
75
+ return lightnessValues.map((lightness) => adjustLightness(baseColor, lightness));
76
+ }
77
+ export function getColorShadesRgb(colorName, lightnessValues) {
78
+ const shades = getColorShades(colorName, lightnessValues);
79
+ return shades.map(oklchToRgb);
80
+ }
81
+ export function createColorPalette(colorName, adjustments) {
82
+ const baseColor = getThemeColor(colorName, 500);
83
+ return adjustments.map((adj) => {
84
+ const adjusted = adjustOklch(baseColor, adj);
85
+ return oklchToRgb(adjusted);
86
+ });
87
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ export default defineNuxtPlugin((_nuxtApp) => {
3
+ console.log("Plugin injected by my-module!");
4
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json"
3
+ }
@@ -0,0 +1,64 @@
1
+ declare const _default: {
2
+ slots: {
3
+ base: string;
4
+ canvas: string;
5
+ };
6
+ variants: {
7
+ color: {
8
+ primary: string;
9
+ secondary: string;
10
+ success: string;
11
+ info: string;
12
+ warning: string;
13
+ error: string;
14
+ neutral: string;
15
+ };
16
+ variant: {
17
+ subtle: string;
18
+ soft: string;
19
+ solid: string;
20
+ };
21
+ };
22
+ compoundVariants: ({
23
+ color: "primary" | "secondary" | "success" | "info" | "warning" | "error";
24
+ variant: "subtle";
25
+ class: {
26
+ canvas: string;
27
+ };
28
+ } | {
29
+ color: "primary" | "secondary" | "success" | "info" | "warning" | "error";
30
+ variant: "soft";
31
+ class: {
32
+ canvas: string;
33
+ };
34
+ } | {
35
+ color: "primary" | "secondary" | "success" | "info" | "warning" | "error";
36
+ variant: "solid";
37
+ class: {
38
+ canvas: string;
39
+ };
40
+ } | {
41
+ color: "neutral";
42
+ variant: "subtle";
43
+ class: {
44
+ canvas: string;
45
+ };
46
+ } | {
47
+ color: "neutral";
48
+ variant: "soft";
49
+ class: {
50
+ canvas: string;
51
+ };
52
+ } | {
53
+ color: "neutral";
54
+ variant: "solid";
55
+ class: {
56
+ canvas: string;
57
+ };
58
+ })[];
59
+ defaultVariants: {
60
+ color: "neutral";
61
+ variant: "subtle";
62
+ };
63
+ };
64
+ export default _default;
@@ -0,0 +1,75 @@
1
+ const colors = ["primary", "secondary", "success", "info", "warning", "error"];
2
+ export default {
3
+ slots: {
4
+ base: "w-full h-full absolute inset-0 pointer-events-none",
5
+ canvas: "w-full h-full block"
6
+ },
7
+ variants: {
8
+ color: {
9
+ primary: "",
10
+ secondary: "",
11
+ success: "",
12
+ info: "",
13
+ warning: "",
14
+ error: "",
15
+ neutral: ""
16
+ },
17
+ variant: {
18
+ subtle: "",
19
+ soft: "",
20
+ solid: ""
21
+ }
22
+ },
23
+ compoundVariants: [
24
+ // Generate variants for each color + variant combination
25
+ ...colors.flatMap((color) => [
26
+ {
27
+ color,
28
+ variant: "subtle",
29
+ class: {
30
+ canvas: `[.bg-${color}-50_&]:_[--grid-end-color:theme(colors.${color}.50)] [.bg-${color}-100_&]:_[--grid-start-color:theme(colors.${color}.100)] [.bg-${color}-200_&]:_[--grid-flicker-color:theme(colors.${color}.200)]`
31
+ }
32
+ },
33
+ {
34
+ color,
35
+ variant: "soft",
36
+ class: {
37
+ canvas: `[.bg-${color}-100_&]:_[--grid-end-color:theme(colors.${color}.100)] [.bg-${color}-200_&]:_[--grid-start-color:theme(colors.${color}.200)] [.bg-${color}-300_&]:_[--grid-flicker-color:theme(colors.${color}.300)]`
38
+ }
39
+ },
40
+ {
41
+ color,
42
+ variant: "solid",
43
+ class: {
44
+ canvas: `[.bg-${color}-200_&]:_[--grid-end-color:theme(colors.${color}.200)] [.bg-${color}-400_&]:_[--grid-start-color:theme(colors.${color}.400)] [.bg-${color}-500_&]:_[--grid-flicker-color:theme(colors.${color}.500)]`
45
+ }
46
+ }
47
+ ]),
48
+ // Neutral variants (using gray)
49
+ {
50
+ color: "neutral",
51
+ variant: "subtle",
52
+ class: {
53
+ canvas: "[.bg-gray-50_&]:_[--grid-end-color:theme(colors.gray.50)] [.bg-gray-100_&]:_[--grid-start-color:theme(colors.gray.100)] [.bg-gray-200_&]:_[--grid-flicker-color:theme(colors.gray.200)]"
54
+ }
55
+ },
56
+ {
57
+ color: "neutral",
58
+ variant: "soft",
59
+ class: {
60
+ canvas: "[.bg-gray-100_&]:_[--grid-end-color:theme(colors.gray.100)] [.bg-gray-200_&]:_[--grid-start-color:theme(colors.gray.200)] [.bg-gray-300_&]:_[--grid-flicker-color:theme(colors.gray.300)]"
61
+ }
62
+ },
63
+ {
64
+ color: "neutral",
65
+ variant: "solid",
66
+ class: {
67
+ canvas: "[.bg-gray-200_&]:_[--grid-end-color:theme(colors.gray.200)] [.bg-gray-400_&]:_[--grid-start-color:theme(colors.gray.400)] [.bg-gray-500_&]:_[--grid-flicker-color:theme(colors.gray.500)]"
68
+ }
69
+ }
70
+ ],
71
+ defaultVariants: {
72
+ color: "neutral",
73
+ variant: "subtle"
74
+ }
75
+ };
@@ -0,0 +1,14 @@
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 };
File without changes
@@ -0,0 +1 @@
1
+ export declare const tv: import("tailwind-variants").TV;
@@ -0,0 +1,2 @@
1
+ import { createTV } from "tailwind-variants";
2
+ export const tv = /* @__PURE__ */ createTV({});
@@ -0,0 +1,3 @@
1
+ export { default } from './module.mjs'
2
+
3
+ export { type ModuleOptions } from './module.mjs'
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "nuxt-ui-elements",
3
+ "version": "0.1.1",
4
+ "description": "A collection of beautiful, animated UI components for Nuxt applications",
5
+ "license": "MIT",
6
+ "repository": "https://github.com/genu/nuxt-ui-elements.git",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "type": "module",
11
+ "main": "./dist/module.mjs",
12
+ "typesVersions": {
13
+ "*": {
14
+ ".": [
15
+ "./dist/types.d.mts"
16
+ ]
17
+ }
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/types.d.mts",
22
+ "import": "./dist/module.mjs"
23
+ }
24
+ },
25
+ "dependencies": {
26
+ "@nuxt/kit": "^4.2.2",
27
+ "culori": "^4.0.2",
28
+ "motion-v": "^1.7.4",
29
+ "tailwind-variants": "^3.2.2"
30
+ },
31
+ "devDependencies": {
32
+ "@nuxt/devtools": "^3.1.1",
33
+ "@nuxt/module-builder": "^1.0.2",
34
+ "@nuxt/schema": "^4.2.2",
35
+ "@nuxt/test-utils": "^3.21.0",
36
+ "@types/culori": "^4.0.1",
37
+ "@types/node": "latest",
38
+ "changelogen": "^0.6.2",
39
+ "nuxt": "^4.2.2",
40
+ "oxfmt": "^0.20.0",
41
+ "oxlint": "^1.35.0",
42
+ "oxlint-tsgolint": "^0.10.0",
43
+ "typescript": "~5.9.3",
44
+ "vitest": "^4.0.16",
45
+ "vue-tsc": "^3.2.1"
46
+ },
47
+ "peerDependencies": {
48
+ "@nuxt/ui": "^4.0.0"
49
+ },
50
+ "scripts": {
51
+ "dev": "pnpm dev:prepare && nuxi dev playground",
52
+ "dev:build": "nuxi build playground",
53
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
54
+ "lint": "oxlint --type-aware",
55
+ "lint:fix": "oxlint --fix --type-aware",
56
+ "format": "oxfmt --write",
57
+ "format:check": "oxfmt --check",
58
+ "release": "pnpm lint && pnpm test && pnpm prepack && changelogen --release && pnpm publish && git push --follow-tags",
59
+ "test": "vitest run",
60
+ "test:watch": "vitest watch",
61
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
62
+ }
63
+ }