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 +156 -0
- package/dist/module.d.mts +13 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +29 -0
- package/dist/runtime/components/background/Aurora.d.vue.ts +62 -0
- package/dist/runtime/components/background/Aurora.vue +120 -0
- package/dist/runtime/components/background/Aurora.vue.d.ts +62 -0
- package/dist/runtime/components/background/FlickeringGrid.d.vue.ts +94 -0
- package/dist/runtime/components/background/FlickeringGrid.vue +226 -0
- package/dist/runtime/components/background/FlickeringGrid.vue.d.ts +94 -0
- package/dist/runtime/composables/useGradient.d.ts +23 -0
- package/dist/runtime/composables/useGradient.js +41 -0
- package/dist/runtime/composables/useThemeColors.d.ts +62 -0
- package/dist/runtime/composables/useThemeColors.js +87 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.js +4 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/themes/background-flickering-grid.d.ts +64 -0
- package/dist/runtime/themes/background-flickering-grid.js +75 -0
- package/dist/runtime/types/tv.d.ts +14 -0
- package/dist/runtime/types/tv.js +0 -0
- package/dist/runtime/utils/tv.d.ts +1 -0
- package/dist/runtime/utils/tv.js +2 -0
- package/dist/types.d.mts +3 -0
- package/package.json +63 -0
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
|
+
- [✨ 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 };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -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,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;
|
package/dist/types.d.mts
ADDED
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
|
+
}
|