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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-ui-elements",
3
3
  "configKey": "uiElements",
4
- "version": "0.1.1",
4
+ "version": "0.1.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -9,7 +9,8 @@ const module$1 = defineNuxtModule({
9
9
  prefix: "UE"
10
10
  },
11
11
  moduleDependencies: {
12
- "motion-v/nuxt": {}
12
+ "motion-v/nuxt": {},
13
+ "@nuxtjs/color-mode": {}
13
14
  },
14
15
  setup(options, _nuxt) {
15
16
  const resolver = createResolver(import.meta.url);
@@ -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("@vue/runtime-core").DefineComponent<AuroraProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
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("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
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("@vue/runtime-core").DefineComponent<AuroraProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<AuroraProps> & Readonly<{}>, {
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("@vue/runtime-core").ComponentProvideOptions, false, {}, any>, AuroraSlots>;
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 12
11
+ * @default 8
11
12
  */
12
- squareSize?: number;
13
+ size?: number;
13
14
  /**
14
15
  * The gap between grid squares
15
- * @default 6
16
+ * @default 8
16
17
  */
17
- gridGap?: number;
18
+ gap?: number;
18
19
  /**
19
- * The flicker animation speed (higher = faster)
20
- * @default 0.3
20
+ * Animation speed (higher = faster flicker)
21
+ * Scale from 1 (slowest) to 10 (fastest)
22
+ * @default 5
21
23
  */
22
- flickerChance?: number;
24
+ speed?: number;
23
25
  /**
24
- * Speed multiplier for flicker animation
25
- * @default 1
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
- flickerSpeed?: number;
31
+ fade?: "radial" | "left" | "right" | "top" | "bottom";
28
32
  /**
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)
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
- height?: number;
44
+ color?: ColorInput;
51
45
  /**
52
- * Color variant
53
- * @default 'neutral'
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
- color?: BackgroundFlickeringGrid["variants"]["color"];
50
+ lightness?: number;
56
51
  /**
57
- * Style variant
58
- * @default 'subtle'
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
- * Additional CSS classes for the container
57
+ * Override color specifically for dark mode
63
58
  */
64
- class?: any;
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("@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>;
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 { 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: "" },
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: "radial-gradient(circle at center, black 20%, transparent 90%)",
37
- WebkitMaskImage: "radial-gradient(circle at center, black 20%, transparent 90%)"
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(color) {
47
- const match = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
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 = 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));
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
- start: parseColor(startRgb),
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 / (props.squareSize + props.gridGap));
97
- const rows = Math.floor(height / (props.squareSize + props.gridGap));
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() * props.maxOpacity;
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() < props.flickerChance * props.flickerSpeed * deltaTime) {
107
- squares[i] = Math.random() * props.maxOpacity;
136
+ if (Math.random() < internalSpeed.value * deltaTime) {
137
+ squares[i] = Math.random() * effectiveOpacity.value;
108
138
  }
109
139
  }
110
140
  }
111
- function drawGrid(ctx, width, height, cols, rows, squares, dpr) {
112
- ctx.clearRect(0, 0, width, height);
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, width, height);
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
- const t = getGradientT(i, j, cols, rows);
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 * props.maxOpacity) {
125
- const blendT = (opacity - 0.5 * props.maxOpacity) / (0.5 * props.maxOpacity);
126
- cellColor = lerpColor(baseColor, colors.flicker, blendT);
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 * (props.squareSize + props.gridGap) * dpr,
132
- j * (props.squareSize + props.gridGap) * dpr,
133
- props.squareSize * dpr,
134
- props.squareSize * dpr
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 = props.width || containerRef.value?.clientWidth || 0;
141
- const newHeight = props.height || containerRef.value?.clientHeight || 0;
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
- () => props.gradientDirection,
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="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
- />
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 12
11
+ * @default 8
11
12
  */
12
- squareSize?: number;
13
+ size?: number;
13
14
  /**
14
15
  * The gap between grid squares
15
- * @default 6
16
+ * @default 8
16
17
  */
17
- gridGap?: number;
18
+ gap?: number;
18
19
  /**
19
- * The flicker animation speed (higher = faster)
20
- * @default 0.3
20
+ * Animation speed (higher = faster flicker)
21
+ * Scale from 1 (slowest) to 10 (fastest)
22
+ * @default 5
21
23
  */
22
- flickerChance?: number;
24
+ speed?: number;
23
25
  /**
24
- * Speed multiplier for flicker animation
25
- * @default 1
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
- flickerSpeed?: number;
31
+ fade?: "radial" | "left" | "right" | "top" | "bottom";
28
32
  /**
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)
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
- height?: number;
44
+ color?: ColorInput;
51
45
  /**
52
- * Color variant
53
- * @default 'neutral'
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
- color?: BackgroundFlickeringGrid["variants"]["color"];
50
+ lightness?: number;
56
51
  /**
57
- * Style variant
58
- * @default 'subtle'
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
- * Additional CSS classes for the container
57
+ * Override color specifically for dark mode
63
58
  */
64
- class?: any;
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("@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>;
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" | "top-left-bottom-right" | "bottom-right-top-left";
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
- let colorValue = styles.getPropertyValue(`--ui-color-${colorName}-${shade}`).trim();
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) {
@@ -1,2 +1,2 @@
1
- declare const _default: any;
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 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"
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-ui-elements",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "A collection of beautiful, animated UI components for Nuxt applications",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/genu/nuxt-ui-elements.git",