nuxt-ui-elements 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -1
- package/dist/runtime/components/background/Aurora.d.vue.ts +2 -2
- package/dist/runtime/components/background/Aurora.vue.d.ts +2 -2
- package/dist/runtime/components/background/FlickeringGrid.d.vue.ts +35 -51
- package/dist/runtime/components/background/FlickeringGrid.vue +96 -90
- package/dist/runtime/components/background/FlickeringGrid.vue.d.ts +35 -51
- package/dist/runtime/composables/useColorResolver.d.ts +40 -0
- package/dist/runtime/composables/useColorResolver.js +68 -0
- package/dist/runtime/composables/useGradient.d.ts +1 -1
- package/dist/runtime/composables/useGradient.js +0 -4
- package/dist/runtime/composables/useThemeColors.js +1 -4
- package/dist/runtime/plugin.d.ts +1 -1
- package/dist/runtime/themes/background-flickering-grid.d.ts +0 -57
- package/dist/runtime/themes/background-flickering-grid.js +2 -71
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -48,13 +48,13 @@ export interface AuroraSlots {
|
|
|
48
48
|
}
|
|
49
49
|
declare const _default: typeof __VLS_export;
|
|
50
50
|
export default _default;
|
|
51
|
-
declare const __VLS_export: __VLS_WithSlots<import("
|
|
51
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<AuroraProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
|
|
52
52
|
pin: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
53
53
|
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
54
54
|
speed: number;
|
|
55
55
|
intensity: number;
|
|
56
56
|
reverse: boolean;
|
|
57
|
-
}, {}, {}, {}, string, import("
|
|
57
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
|
|
58
58
|
type __VLS_WithSlots<T, S> = T & {
|
|
59
59
|
new (): {
|
|
60
60
|
$slots: S;
|
|
@@ -48,13 +48,13 @@ export interface AuroraSlots {
|
|
|
48
48
|
}
|
|
49
49
|
declare const _default: typeof __VLS_export;
|
|
50
50
|
export default _default;
|
|
51
|
-
declare const __VLS_export: __VLS_WithSlots<import("
|
|
51
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<AuroraProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
|
|
52
52
|
pin: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
53
53
|
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
54
54
|
speed: number;
|
|
55
55
|
intensity: number;
|
|
56
56
|
reverse: boolean;
|
|
57
|
-
}, {}, {}, {}, string, import("
|
|
57
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
|
|
58
58
|
type __VLS_WithSlots<T, S> = T & {
|
|
59
59
|
new (): {
|
|
60
60
|
$slots: S;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ColorInput } from "../../composables/useColorResolver.js";
|
|
1
2
|
import type { ComponentConfig } from "../../types/tv.js";
|
|
2
3
|
import backgroundFlickeringGridTheme from "../../themes/background-flickering-grid.js";
|
|
3
4
|
type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridTheme>;
|
|
@@ -7,61 +8,55 @@ type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridT
|
|
|
7
8
|
export interface FlickeringGridProps {
|
|
8
9
|
/**
|
|
9
10
|
* The square size of the grid (before scaling)
|
|
10
|
-
* @default
|
|
11
|
+
* @default 8
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
size?: number;
|
|
13
14
|
/**
|
|
14
15
|
* The gap between grid squares
|
|
15
|
-
* @default
|
|
16
|
+
* @default 8
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
+
gap?: number;
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
20
|
+
* Animation speed (higher = faster flicker)
|
|
21
|
+
* Scale from 1 (slowest) to 10 (fastest)
|
|
22
|
+
* @default 5
|
|
21
23
|
*/
|
|
22
|
-
|
|
24
|
+
speed?: number;
|
|
23
25
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* Apply fade/vignette effect with directional masking
|
|
27
|
+
* - 'radial': Radial fade from center (spotlight effect)
|
|
28
|
+
* - 'left', 'right', 'top', 'bottom': Linear fade from specified edge
|
|
29
|
+
*
|
|
26
30
|
*/
|
|
27
|
-
|
|
31
|
+
fade?: "radial" | "left" | "right" | "top" | "bottom";
|
|
28
32
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
|
|
37
|
-
|
|
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)
|
|
33
|
+
* Color for the grid. Supports:
|
|
34
|
+
* - Nuxt UI semantic: 'primary', 'secondary', 'success', 'info', 'warning', 'error', 'neutral'
|
|
35
|
+
* - Tailwind colors: 'blue-500', 'red-600', 'slate-200', etc.
|
|
36
|
+
* - Direct values: '#3b82f6', 'oklch(0.6 0.15 250)', 'rgb(59, 130, 246)'
|
|
37
|
+
*
|
|
38
|
+
* @example 'primary' - Nuxt UI semantic color
|
|
39
|
+
* @example 'blue-500' - Tailwind color
|
|
40
|
+
* @example '#3b82f6' - Direct hex color value
|
|
41
|
+
*
|
|
42
|
+
* @default 'neutral'
|
|
49
43
|
*/
|
|
50
|
-
|
|
44
|
+
color?: ColorInput;
|
|
51
45
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
46
|
+
* Lightness value for the grid (controls how light/subtle the grid appears)
|
|
47
|
+
* Range: 0-100, where higher values = lighter/more subtle
|
|
48
|
+
* @default 95
|
|
54
49
|
*/
|
|
55
|
-
|
|
50
|
+
lightness?: number;
|
|
56
51
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
52
|
+
* Fine-grained element customization (similar to Nuxt UI's ui prop)
|
|
53
|
+
*
|
|
54
|
+
* @example { colorDark: 'blue-300' } - Override color for dark mode
|
|
59
55
|
*/
|
|
60
|
-
variant?: BackgroundFlickeringGrid["variants"]["variant"];
|
|
61
56
|
/**
|
|
62
|
-
*
|
|
57
|
+
* Override color specifically for dark mode
|
|
63
58
|
*/
|
|
64
|
-
|
|
59
|
+
colorDark?: ColorInput;
|
|
65
60
|
/**
|
|
66
61
|
* UI slot customization
|
|
67
62
|
*/
|
|
@@ -75,18 +70,7 @@ export interface FlickeringGridSlots {
|
|
|
75
70
|
}
|
|
76
71
|
declare const _default: typeof __VLS_export;
|
|
77
72
|
export default _default;
|
|
78
|
-
declare const __VLS_export: __VLS_WithSlots<import("
|
|
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>;
|
|
73
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, FlickeringGridSlots>;
|
|
90
74
|
type __VLS_WithSlots<T, S> = T & {
|
|
91
75
|
new (): {
|
|
92
76
|
$slots: S;
|
|
@@ -4,66 +4,101 @@ import backgroundFlickeringGridTheme from "../../themes/background-flickering-gr
|
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
6
|
import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
|
|
7
|
+
import { useColorMode } from "#imports";
|
|
7
8
|
import { tv } from "../../utils/tv";
|
|
8
|
-
import { calculateGradientIntensity } from "../../composables/useGradient";
|
|
9
9
|
import theme from "../../themes/background-flickering-grid";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
import { adjustLightness, oklchToRgb } from "../../composables/useThemeColors";
|
|
11
|
+
import {
|
|
12
|
+
resolveColor
|
|
13
|
+
} from "../../composables/useColorResolver";
|
|
14
|
+
const {
|
|
15
|
+
size = 8,
|
|
16
|
+
gap = 9,
|
|
17
|
+
speed = 5,
|
|
18
|
+
color = "neutral",
|
|
19
|
+
lightness = 95,
|
|
20
|
+
...props
|
|
21
|
+
} = defineProps({
|
|
22
|
+
size: { type: Number, required: false },
|
|
23
|
+
gap: { type: Number, required: false },
|
|
24
|
+
speed: { type: Number, required: false },
|
|
25
|
+
fade: { type: String, required: false },
|
|
26
|
+
color: { type: null, required: false },
|
|
27
|
+
lightness: { type: Number, required: false },
|
|
28
|
+
colorDark: { type: null, required: false },
|
|
24
29
|
ui: { type: null, required: false }
|
|
25
30
|
});
|
|
31
|
+
const colorMode = useColorMode();
|
|
32
|
+
const isDark = computed(() => colorMode.value === "dark");
|
|
33
|
+
const effectiveColor = computed(() => {
|
|
34
|
+
if (isDark.value && props.colorDark) {
|
|
35
|
+
return props.colorDark;
|
|
36
|
+
}
|
|
37
|
+
return color;
|
|
38
|
+
});
|
|
39
|
+
const internalSpeed = computed(() => {
|
|
40
|
+
return speed * 0.01;
|
|
41
|
+
});
|
|
42
|
+
const effectiveOpacity = computed(() => {
|
|
43
|
+
const minLightness = 70;
|
|
44
|
+
const maxLightness = 100;
|
|
45
|
+
const maxOpacity = 0.8;
|
|
46
|
+
const minOpacity = 0.15;
|
|
47
|
+
const t = Math.max(
|
|
48
|
+
0,
|
|
49
|
+
Math.min(1, (lightness - minLightness) / (maxLightness - minLightness))
|
|
50
|
+
);
|
|
51
|
+
return maxOpacity - t * (maxOpacity - minOpacity);
|
|
52
|
+
});
|
|
26
53
|
defineSlots();
|
|
27
|
-
const ui = computed(
|
|
28
|
-
() => tv(theme)({
|
|
29
|
-
color: props.color,
|
|
30
|
-
variant: props.variant
|
|
31
|
-
})
|
|
32
|
-
);
|
|
54
|
+
const ui = computed(() => tv(theme)());
|
|
33
55
|
const maskStyle = computed(() => {
|
|
34
56
|
if (!props.fade) return {};
|
|
57
|
+
let maskImage;
|
|
58
|
+
switch (props.fade) {
|
|
59
|
+
case "radial":
|
|
60
|
+
maskImage = "radial-gradient(circle at center, black 20%, transparent 90%)";
|
|
61
|
+
break;
|
|
62
|
+
case "left":
|
|
63
|
+
maskImage = "linear-gradient(to right, transparent 0%, black 30%)";
|
|
64
|
+
break;
|
|
65
|
+
case "right":
|
|
66
|
+
maskImage = "linear-gradient(to left, transparent 0%, black 30%)";
|
|
67
|
+
break;
|
|
68
|
+
case "top":
|
|
69
|
+
maskImage = "linear-gradient(to bottom, transparent 0%, black 30%)";
|
|
70
|
+
break;
|
|
71
|
+
case "bottom":
|
|
72
|
+
maskImage = "linear-gradient(to top, transparent 0%, black 30%)";
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
35
77
|
return {
|
|
36
|
-
maskImage
|
|
37
|
-
WebkitMaskImage:
|
|
78
|
+
maskImage,
|
|
79
|
+
WebkitMaskImage: maskImage
|
|
38
80
|
};
|
|
39
81
|
});
|
|
40
82
|
const containerRef = ref();
|
|
41
83
|
const canvasRef = ref();
|
|
42
84
|
const context = ref(null);
|
|
43
85
|
const isInView = ref(false);
|
|
44
|
-
const canvasSize = ref({ width: 0, height: 0 });
|
|
45
86
|
const gridParams = ref(null);
|
|
46
|
-
function parseColor(
|
|
47
|
-
const match =
|
|
87
|
+
function parseColor(color2) {
|
|
88
|
+
const match = color2.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
|
|
48
89
|
if (match && match[1] && match[2] && match[3]) {
|
|
49
90
|
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
50
91
|
}
|
|
51
92
|
return [255, 255, 255];
|
|
52
93
|
}
|
|
53
94
|
const gridColors = computed(() => {
|
|
54
|
-
const baseColor =
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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));
|
|
95
|
+
const baseColor = resolveColor(effectiveColor.value);
|
|
96
|
+
const lightnessBase = lightness;
|
|
97
|
+
const lightnessFlicker = Math.max(0, lightness - 10);
|
|
98
|
+
const baseRgb = oklchToRgb(adjustLightness(baseColor, lightnessBase));
|
|
99
|
+
const flickerRgb = oklchToRgb(adjustLightness(baseColor, lightnessFlicker));
|
|
64
100
|
return {
|
|
65
|
-
|
|
66
|
-
end: parseColor(endRgb),
|
|
101
|
+
base: parseColor(baseRgb),
|
|
67
102
|
flicker: parseColor(flickerRgb)
|
|
68
103
|
};
|
|
69
104
|
});
|
|
@@ -82,64 +117,56 @@ function lerpColor(a, b, t) {
|
|
|
82
117
|
function rgbToString(rgb, alpha = 1) {
|
|
83
118
|
return `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${alpha})`;
|
|
84
119
|
}
|
|
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
120
|
function setupCanvas(canvas, width, height) {
|
|
91
121
|
const dpr = window.devicePixelRatio || 1;
|
|
92
122
|
canvas.width = width * dpr;
|
|
93
123
|
canvas.height = height * dpr;
|
|
94
124
|
canvas.style.width = `${width}px`;
|
|
95
125
|
canvas.style.height = `${height}px`;
|
|
96
|
-
const cols = Math.floor(width / (
|
|
97
|
-
const rows = Math.floor(height / (
|
|
126
|
+
const cols = Math.floor(width / (size + gap));
|
|
127
|
+
const rows = Math.floor(height / (size + gap));
|
|
98
128
|
const squares = new Float32Array(cols * rows);
|
|
99
129
|
for (let i = 0; i < squares.length; i++) {
|
|
100
|
-
squares[i] = Math.random() *
|
|
130
|
+
squares[i] = Math.random() * effectiveOpacity.value;
|
|
101
131
|
}
|
|
102
132
|
return { cols, rows, squares, dpr };
|
|
103
133
|
}
|
|
104
134
|
function updateSquares(squares, deltaTime) {
|
|
105
135
|
for (let i = 0; i < squares.length; i++) {
|
|
106
|
-
if (Math.random() <
|
|
107
|
-
squares[i] = Math.random() *
|
|
136
|
+
if (Math.random() < internalSpeed.value * deltaTime) {
|
|
137
|
+
squares[i] = Math.random() * effectiveOpacity.value;
|
|
108
138
|
}
|
|
109
139
|
}
|
|
110
140
|
}
|
|
111
|
-
function drawGrid(ctx,
|
|
112
|
-
ctx.clearRect(0, 0,
|
|
141
|
+
function drawGrid(ctx, canvasWidth, canvasHeight, cols, rows, squares, dpr) {
|
|
142
|
+
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
|
|
113
143
|
ctx.fillStyle = "transparent";
|
|
114
|
-
ctx.fillRect(0, 0,
|
|
144
|
+
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
|
115
145
|
const colors = gridColors.value;
|
|
116
146
|
for (let i = 0; i < cols; i++) {
|
|
117
147
|
for (let j = 0; j < rows; j++) {
|
|
118
148
|
const idx = i * rows + j;
|
|
119
149
|
const opacity = squares[idx] ?? 0;
|
|
120
|
-
|
|
121
|
-
const baseColor = lerpColor(colors.start, colors.end, t);
|
|
122
|
-
let cellColor = baseColor;
|
|
150
|
+
let cellColor = colors.base;
|
|
123
151
|
let cellAlpha = opacity;
|
|
124
|
-
if (opacity > 0.5 *
|
|
125
|
-
const blendT = (opacity - 0.5 *
|
|
126
|
-
cellColor = lerpColor(
|
|
152
|
+
if (opacity > 0.5 * effectiveOpacity.value) {
|
|
153
|
+
const blendT = (opacity - 0.5 * effectiveOpacity.value) / (0.5 * effectiveOpacity.value);
|
|
154
|
+
cellColor = lerpColor(colors.base, colors.flicker, blendT);
|
|
127
155
|
cellAlpha = Math.min(1, opacity + 0.2);
|
|
128
156
|
}
|
|
129
157
|
ctx.fillStyle = rgbToString(cellColor, cellAlpha);
|
|
130
158
|
ctx.fillRect(
|
|
131
|
-
i * (
|
|
132
|
-
j * (
|
|
133
|
-
|
|
134
|
-
|
|
159
|
+
i * (size + gap) * dpr,
|
|
160
|
+
j * (size + gap) * dpr,
|
|
161
|
+
size * dpr,
|
|
162
|
+
size * dpr
|
|
135
163
|
);
|
|
136
164
|
}
|
|
137
165
|
}
|
|
138
166
|
}
|
|
139
167
|
function updateCanvasSize() {
|
|
140
|
-
const newWidth =
|
|
141
|
-
const newHeight =
|
|
142
|
-
canvasSize.value = { width: newWidth, height: newHeight };
|
|
168
|
+
const newWidth = containerRef.value?.clientWidth || 0;
|
|
169
|
+
const newHeight = containerRef.value?.clientHeight || 0;
|
|
143
170
|
if (canvasRef.value) {
|
|
144
171
|
gridParams.value = setupCanvas(canvasRef.value, newWidth, newHeight);
|
|
145
172
|
}
|
|
@@ -192,35 +219,14 @@ onBeforeUnmount(() => {
|
|
|
192
219
|
resizeObserver?.disconnect();
|
|
193
220
|
intersectionObserver?.disconnect();
|
|
194
221
|
});
|
|
195
|
-
watch(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
() => props.squareSize,
|
|
199
|
-
() => props.gridGap,
|
|
200
|
-
() => props.maxOpacity,
|
|
201
|
-
() => props.color,
|
|
202
|
-
() => props.variant
|
|
203
|
-
],
|
|
204
|
-
() => {
|
|
205
|
-
updateCanvasSize();
|
|
206
|
-
}
|
|
207
|
-
);
|
|
222
|
+
watch([() => size, () => gap, () => color, () => lightness], () => {
|
|
223
|
+
updateCanvasSize();
|
|
224
|
+
});
|
|
208
225
|
</script>
|
|
209
226
|
|
|
210
227
|
<template>
|
|
211
|
-
<div
|
|
212
|
-
ref="
|
|
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
|
-
/>
|
|
228
|
+
<div ref="containerRef" :class="ui.base({ class: [props.ui?.base] })">
|
|
229
|
+
<canvas ref="canvasRef" :class="ui.canvas({ class: props.ui?.canvas })" :style="maskStyle" />
|
|
224
230
|
<slot />
|
|
225
231
|
</div>
|
|
226
232
|
</template>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ColorInput } from "../../composables/useColorResolver.js";
|
|
1
2
|
import type { ComponentConfig } from "../../types/tv.js";
|
|
2
3
|
import backgroundFlickeringGridTheme from "../../themes/background-flickering-grid.js";
|
|
3
4
|
type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridTheme>;
|
|
@@ -7,61 +8,55 @@ type BackgroundFlickeringGrid = ComponentConfig<typeof backgroundFlickeringGridT
|
|
|
7
8
|
export interface FlickeringGridProps {
|
|
8
9
|
/**
|
|
9
10
|
* The square size of the grid (before scaling)
|
|
10
|
-
* @default
|
|
11
|
+
* @default 8
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
size?: number;
|
|
13
14
|
/**
|
|
14
15
|
* The gap between grid squares
|
|
15
|
-
* @default
|
|
16
|
+
* @default 8
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
+
gap?: number;
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
20
|
+
* Animation speed (higher = faster flicker)
|
|
21
|
+
* Scale from 1 (slowest) to 10 (fastest)
|
|
22
|
+
* @default 5
|
|
21
23
|
*/
|
|
22
|
-
|
|
24
|
+
speed?: number;
|
|
23
25
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* Apply fade/vignette effect with directional masking
|
|
27
|
+
* - 'radial': Radial fade from center (spotlight effect)
|
|
28
|
+
* - 'left', 'right', 'top', 'bottom': Linear fade from specified edge
|
|
29
|
+
*
|
|
26
30
|
*/
|
|
27
|
-
|
|
31
|
+
fade?: "radial" | "left" | "right" | "top" | "bottom";
|
|
28
32
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
|
|
37
|
-
|
|
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)
|
|
33
|
+
* Color for the grid. Supports:
|
|
34
|
+
* - Nuxt UI semantic: 'primary', 'secondary', 'success', 'info', 'warning', 'error', 'neutral'
|
|
35
|
+
* - Tailwind colors: 'blue-500', 'red-600', 'slate-200', etc.
|
|
36
|
+
* - Direct values: '#3b82f6', 'oklch(0.6 0.15 250)', 'rgb(59, 130, 246)'
|
|
37
|
+
*
|
|
38
|
+
* @example 'primary' - Nuxt UI semantic color
|
|
39
|
+
* @example 'blue-500' - Tailwind color
|
|
40
|
+
* @example '#3b82f6' - Direct hex color value
|
|
41
|
+
*
|
|
42
|
+
* @default 'neutral'
|
|
49
43
|
*/
|
|
50
|
-
|
|
44
|
+
color?: ColorInput;
|
|
51
45
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
46
|
+
* Lightness value for the grid (controls how light/subtle the grid appears)
|
|
47
|
+
* Range: 0-100, where higher values = lighter/more subtle
|
|
48
|
+
* @default 95
|
|
54
49
|
*/
|
|
55
|
-
|
|
50
|
+
lightness?: number;
|
|
56
51
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
52
|
+
* Fine-grained element customization (similar to Nuxt UI's ui prop)
|
|
53
|
+
*
|
|
54
|
+
* @example { colorDark: 'blue-300' } - Override color for dark mode
|
|
59
55
|
*/
|
|
60
|
-
variant?: BackgroundFlickeringGrid["variants"]["variant"];
|
|
61
56
|
/**
|
|
62
|
-
*
|
|
57
|
+
* Override color specifically for dark mode
|
|
63
58
|
*/
|
|
64
|
-
|
|
59
|
+
colorDark?: ColorInput;
|
|
65
60
|
/**
|
|
66
61
|
* UI slot customization
|
|
67
62
|
*/
|
|
@@ -75,18 +70,7 @@ export interface FlickeringGridSlots {
|
|
|
75
70
|
}
|
|
76
71
|
declare const _default: typeof __VLS_export;
|
|
77
72
|
export default _default;
|
|
78
|
-
declare const __VLS_export: __VLS_WithSlots<import("
|
|
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>;
|
|
73
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, FlickeringGridSlots>;
|
|
90
74
|
type __VLS_WithSlots<T, S> = T & {
|
|
91
75
|
new (): {
|
|
92
76
|
$slots: S;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import colors from "tailwindcss/colors";
|
|
2
|
+
/**
|
|
3
|
+
* Nuxt UI semantic colors
|
|
4
|
+
*/
|
|
5
|
+
declare const SEMANTIC_COLORS: readonly ["primary", "secondary", "success", "info", "warning", "error", "neutral"];
|
|
6
|
+
export type SemanticColor = (typeof SEMANTIC_COLORS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* Tailwind color names
|
|
9
|
+
*/
|
|
10
|
+
type TailwindColorName = keyof typeof colors;
|
|
11
|
+
/**
|
|
12
|
+
* Tailwind color shades
|
|
13
|
+
*/
|
|
14
|
+
type TailwindShade = "50" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900" | "950";
|
|
15
|
+
/**
|
|
16
|
+
* Tailwind color format: colorName-shade (e.g., 'blue-500', 'red-600')
|
|
17
|
+
*/
|
|
18
|
+
export type TailwindColor = `${TailwindColorName}-${TailwindShade}`;
|
|
19
|
+
/**
|
|
20
|
+
* Supported color input formats
|
|
21
|
+
*/
|
|
22
|
+
export type ColorInput = SemanticColor | TailwindColor | (string & {});
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a color input to an actual color value
|
|
25
|
+
* Supports:
|
|
26
|
+
* - Nuxt UI semantic colors: 'primary', 'secondary', etc.
|
|
27
|
+
* - Tailwind colors: 'blue-500', 'red-600', etc.
|
|
28
|
+
* - Direct color values: '#3b82f6', 'oklch(0.6 0.15 250)', etc.
|
|
29
|
+
*
|
|
30
|
+
* @param colorInput - The color string to resolve
|
|
31
|
+
* @param fallback - Fallback color if resolution fails (default: 'neutral')
|
|
32
|
+
* @returns The resolved color value
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveColor(colorInput: string | undefined, fallback?: SemanticColor): string;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a color and ensure it returns an OKLCH string
|
|
37
|
+
* Useful when you need consistent color space for manipulation
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveColorAsOklch(colorInput: string | undefined, fallback?: SemanticColor): string;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { parse } from "culori";
|
|
2
|
+
import { getThemeColor } from "./useThemeColors.js";
|
|
3
|
+
import colors from "tailwindcss/colors";
|
|
4
|
+
const SEMANTIC_COLORS = [
|
|
5
|
+
"primary",
|
|
6
|
+
"secondary",
|
|
7
|
+
"success",
|
|
8
|
+
"info",
|
|
9
|
+
"warning",
|
|
10
|
+
"error",
|
|
11
|
+
"neutral"
|
|
12
|
+
];
|
|
13
|
+
function getTailwindDefaultColor(colorName, shade) {
|
|
14
|
+
const colorObj = colors[colorName];
|
|
15
|
+
if (colorObj && typeof colorObj === "object" && !Array.isArray(colorObj)) {
|
|
16
|
+
return colorObj[shade.toString()] || null;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
function isSemanticColor(color) {
|
|
21
|
+
return SEMANTIC_COLORS.includes(color);
|
|
22
|
+
}
|
|
23
|
+
function isDirectColor(color) {
|
|
24
|
+
return color.startsWith("#") || color.startsWith("rgb") || color.startsWith("hsl") || color.startsWith("oklch") || color.startsWith("lab") || color.startsWith("lch");
|
|
25
|
+
}
|
|
26
|
+
export function resolveColor(colorInput, fallback = "neutral") {
|
|
27
|
+
if (!colorInput || colorInput.trim() === "") {
|
|
28
|
+
return getThemeColor(fallback, 500);
|
|
29
|
+
}
|
|
30
|
+
const color = colorInput.trim();
|
|
31
|
+
if (isDirectColor(color)) {
|
|
32
|
+
const parsed = parse(color);
|
|
33
|
+
if (parsed) {
|
|
34
|
+
return color;
|
|
35
|
+
}
|
|
36
|
+
console.warn(`[resolveColor] Invalid color format: "${color}"`);
|
|
37
|
+
}
|
|
38
|
+
if (isSemanticColor(color)) {
|
|
39
|
+
return getThemeColor(color, 500);
|
|
40
|
+
}
|
|
41
|
+
const tailwindColorMatch = color.match(/^([a-z]+)-(\d{2,3})$/);
|
|
42
|
+
if (tailwindColorMatch) {
|
|
43
|
+
const [, colorName, shade] = tailwindColorMatch;
|
|
44
|
+
if (colorName && shade) {
|
|
45
|
+
if (typeof document !== "undefined") {
|
|
46
|
+
const resolvedColor = getThemeColor(colorName, parseInt(shade));
|
|
47
|
+
if (resolvedColor !== "oklch(50% 0 0)") {
|
|
48
|
+
return resolvedColor;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const defaultColor = getTailwindDefaultColor(colorName, parseInt(shade));
|
|
52
|
+
if (defaultColor) {
|
|
53
|
+
return defaultColor;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
console.warn(
|
|
58
|
+
`[resolveColor] Could not resolve color: "${colorInput}". Supported formats: Nuxt UI semantic colors ('primary', 'secondary', etc.), Tailwind colors ('blue-500', 'red-600', etc.), or direct color values ('#3b82f6', 'oklch(...)', 'rgb(...)'). Falling back to "${fallback}".`
|
|
59
|
+
);
|
|
60
|
+
return getThemeColor(fallback, 500);
|
|
61
|
+
}
|
|
62
|
+
export function resolveColorAsOklch(colorInput, fallback = "neutral") {
|
|
63
|
+
const resolved = resolveColor(colorInput, fallback);
|
|
64
|
+
if (isSemanticColor(colorInput || "")) {
|
|
65
|
+
return resolved;
|
|
66
|
+
}
|
|
67
|
+
return resolved;
|
|
68
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type GradientDirection = "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in"
|
|
1
|
+
export type GradientDirection = "left-right" | "right-left" | "top-bottom" | "bottom-top" | "in-out" | "out-in";
|
|
2
2
|
/**
|
|
3
3
|
* Calculate gradient intensity for a position based on direction
|
|
4
4
|
* @param x - X coordinate (0-1)
|
|
@@ -18,10 +18,6 @@ export function calculateGradientIntensity(x, y, direction) {
|
|
|
18
18
|
const dy = y - 0.5;
|
|
19
19
|
return 1 - Math.sqrt(dx * dx + dy * dy) * Math.sqrt(2);
|
|
20
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
21
|
default:
|
|
26
22
|
return 0;
|
|
27
23
|
}
|
|
@@ -64,10 +64,7 @@ export function oklchToRgb(colorString) {
|
|
|
64
64
|
export function getThemeColor(colorName, shade = 500) {
|
|
65
65
|
if (typeof document === "undefined") return "oklch(50% 0 0)";
|
|
66
66
|
const styles = getComputedStyle(document.documentElement);
|
|
67
|
-
|
|
68
|
-
if (!colorValue) {
|
|
69
|
-
colorValue = styles.getPropertyValue(`--color-${colorName}-${shade}`).trim();
|
|
70
|
-
}
|
|
67
|
+
const colorValue = styles.getPropertyValue(`--ui-color-${colorName}-${shade}`).trim();
|
|
71
68
|
return colorValue || "oklch(50% 0 0)";
|
|
72
69
|
}
|
|
73
70
|
export function getColorShades(colorName, lightnessValues) {
|
package/dist/runtime/plugin.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default:
|
|
1
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
2
2
|
export default _default;
|
|
@@ -3,62 +3,5 @@ declare const _default: {
|
|
|
3
3
|
base: string;
|
|
4
4
|
canvas: string;
|
|
5
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
6
|
};
|
|
64
7
|
export default _default;
|
|
@@ -1,75 +1,6 @@
|
|
|
1
|
-
const colors = ["primary", "secondary", "success", "info", "warning", "error"];
|
|
2
1
|
export default {
|
|
3
2
|
slots: {
|
|
4
|
-
base: "w-full h-full absolute inset-0
|
|
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"
|
|
3
|
+
base: "w-full h-full absolute inset-0",
|
|
4
|
+
canvas: "w-full h-full block pointer-events-none"
|
|
74
5
|
}
|
|
75
6
|
};
|
package/package.json
CHANGED