rimelight-components 2.0.45 → 2.0.47
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 +1 -1
- package/dist/runtime/components/blocks/editor/ImageBlockEditor.vue +39 -25
- package/dist/runtime/components/renderers/BlockEditor.vue +1 -1
- package/dist/runtime/utils/index.d.ts +0 -3
- package/dist/runtime/utils/index.js +0 -5
- package/package.json +1 -5
- package/dist/runtime/components/backgrounds/AnimateGrid.d.vue.ts +0 -17
- package/dist/runtime/components/backgrounds/AnimateGrid.vue +0 -84
- package/dist/runtime/components/backgrounds/AnimateGrid.vue.d.ts +0 -17
- package/dist/runtime/components/backgrounds/FlickeringGrid.d.vue.ts +0 -13
- package/dist/runtime/components/backgrounds/FlickeringGrid.vue +0 -136
- package/dist/runtime/components/backgrounds/FlickeringGrid.vue.d.ts +0 -13
- package/dist/runtime/components/backgrounds/InteractiveGrid.d.vue.ts +0 -11
- package/dist/runtime/components/backgrounds/InteractiveGrid.vue +0 -58
- package/dist/runtime/components/backgrounds/InteractiveGrid.vue.d.ts +0 -11
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { readdirSync } from 'node:fs';
|
|
|
4
4
|
import { basename } from 'node:path';
|
|
5
5
|
|
|
6
6
|
const name = "rimelight-components";
|
|
7
|
-
const version = "2.0.
|
|
7
|
+
const version = "2.0.47";
|
|
8
8
|
const homepage = "https://rimelight.com/tools/rimelight-components";
|
|
9
9
|
|
|
10
10
|
const defaultOptions = {
|
|
@@ -31,26 +31,26 @@ watch(fileToUpload, (newFile) => {
|
|
|
31
31
|
</script>
|
|
32
32
|
|
|
33
33
|
<template>
|
|
34
|
-
<figure class="mx-auto space-y-4
|
|
34
|
+
<figure class="mx-auto space-y-4 flex flex-col gap-xs w-full">
|
|
35
35
|
<UFileUpload
|
|
36
36
|
v-slot="{ open }"
|
|
37
37
|
v-model="fileToUpload"
|
|
38
38
|
accept="image/*"
|
|
39
|
-
class="min-h-48"
|
|
39
|
+
class="min-h-48 w-full"
|
|
40
40
|
variant="area"
|
|
41
41
|
color="neutral"
|
|
42
42
|
label="Drop image here"
|
|
43
43
|
description="JPG, PNG, GIF or WEBP. Click to select."
|
|
44
44
|
>
|
|
45
45
|
<div class="flex flex-col items-center justify-center space-y-3 p-4">
|
|
46
|
-
<div class="w-full relative rounded-lg border border-default overflow-hidden
|
|
46
|
+
<div class="w-full relative rounded-lg border border-default overflow-hidden">
|
|
47
47
|
<img
|
|
48
48
|
v-if="previewSrc"
|
|
49
49
|
:src="previewSrc"
|
|
50
50
|
:alt="localAlt || 'Image preview'"
|
|
51
|
-
class="w-full h-
|
|
51
|
+
class="w-full h-auto object-contain transition-opacity duration-300"
|
|
52
52
|
/>
|
|
53
|
-
<div v-else class="w-full h-
|
|
53
|
+
<div v-else class="w-full h-48 flex items-center justify-center bg-elevated/25">
|
|
54
54
|
<UIcon name="i-lucide-image" class="w-10 h-10 text-muted" />
|
|
55
55
|
</div>
|
|
56
56
|
|
|
@@ -75,31 +75,45 @@ watch(fileToUpload, (newFile) => {
|
|
|
75
75
|
</div>
|
|
76
76
|
</div>
|
|
77
77
|
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</UFileUpload>
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
<UInput
|
|
82
|
+
v-model="localAlt"
|
|
83
|
+
type="text"
|
|
84
|
+
placeholder="Alt text (accessibility)"
|
|
85
|
+
class="w-full"
|
|
86
|
+
variant="outline"
|
|
87
|
+
>
|
|
88
|
+
<template #leading>
|
|
89
|
+
<UTooltip>
|
|
90
|
+
<template #default>
|
|
87
91
|
<span class="text-xs text-muted">Alt</span>
|
|
88
92
|
</template>
|
|
89
|
-
|
|
93
|
+
<template #content>
|
|
94
|
+
The text description for the image used by screen readers.
|
|
95
|
+
</template>
|
|
96
|
+
</UTooltip>
|
|
97
|
+
</template>
|
|
98
|
+
</UInput>
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
<UTextarea
|
|
101
|
+
v-model="localCaption"
|
|
102
|
+
autoresize
|
|
103
|
+
placeholder="Caption (optional)"
|
|
104
|
+
class="w-full"
|
|
105
|
+
variant="outline"
|
|
106
|
+
>
|
|
107
|
+
<template #leading>
|
|
108
|
+
<UTooltip>
|
|
109
|
+
<template #default>
|
|
99
110
|
<span class="text-xs text-muted">Caption</span>
|
|
100
111
|
</template>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
<template #content>
|
|
113
|
+
The text description for the image used by screen readers.
|
|
114
|
+
</template>
|
|
115
|
+
</UTooltip>
|
|
116
|
+
</template>
|
|
117
|
+
</UTextarea>
|
|
104
118
|
</figure>
|
|
105
119
|
</template>
|
|
@@ -36,7 +36,7 @@ const getComponent = (block) => {
|
|
|
36
36
|
title="Start adding content blocks."
|
|
37
37
|
description="There is no content yet. Use the '+' button below to add your first block."
|
|
38
38
|
/>
|
|
39
|
-
<div v-else class="flex flex-col gap-md ml-
|
|
39
|
+
<div v-else class="flex flex-col gap-md ml-10">
|
|
40
40
|
<template v-for="block in blocks" :key="block.id">
|
|
41
41
|
<RCBlock v-if="getComponent(block)" :id="block.id">
|
|
42
42
|
<component
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rimelight-components",
|
|
3
3
|
"description": "A component library by Rimelight Entertainment.",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.47",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -99,15 +99,11 @@
|
|
|
99
99
|
"@prettier/plugin-oxc": "^0.0.4",
|
|
100
100
|
"@types/node": "latest",
|
|
101
101
|
"changelogen": "^0.6.2",
|
|
102
|
-
"class-variance-authority": "^0.7.1",
|
|
103
|
-
"clsx": "^2.1.1",
|
|
104
|
-
"motion-v": "^1.7.4",
|
|
105
102
|
"oxlint": "^1.25.0",
|
|
106
103
|
"prettier": "^3.6.2",
|
|
107
104
|
"prettier-plugin-tailwindcss": "^0.7.1",
|
|
108
105
|
"release-it": "^19.0.5",
|
|
109
106
|
"tailwind-merge": "^3.3.1",
|
|
110
|
-
"tw-animate-css": "^1.4.0",
|
|
111
107
|
"typescript": "~5.9.3",
|
|
112
108
|
"vitest": "^4.0.6",
|
|
113
109
|
"vue-tsc": "^3.1.2"
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
interface Cards {
|
|
2
|
-
icon: string;
|
|
3
|
-
href?: string;
|
|
4
|
-
iconClass?: string;
|
|
5
|
-
}
|
|
6
|
-
interface Props {
|
|
7
|
-
class?: string;
|
|
8
|
-
textGlowStartColor?: string;
|
|
9
|
-
perspective?: number;
|
|
10
|
-
textGlowEndColor?: string;
|
|
11
|
-
cards: Cards[];
|
|
12
|
-
rotateX?: number;
|
|
13
|
-
rotateY?: number;
|
|
14
|
-
}
|
|
15
|
-
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
-
declare const _default: typeof __VLS_export;
|
|
17
|
-
export default _default;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { onMounted, ref, watch } from "vue";
|
|
3
|
-
import { cn } from "../../utils";
|
|
4
|
-
import { useMouseInElement, useDebounceFn } from "@vueuse/core";
|
|
5
|
-
const card = ref();
|
|
6
|
-
const props = defineProps({
|
|
7
|
-
class: { type: String, required: false },
|
|
8
|
-
textGlowStartColor: { type: String, required: false, default: "var(--color-primary-300, #38ef7d)" },
|
|
9
|
-
perspective: { type: Number, required: false, default: 750 },
|
|
10
|
-
textGlowEndColor: { type: String, required: false, default: "var(--color-primary-500, #38ef7d)" },
|
|
11
|
-
cards: { type: Array, required: true },
|
|
12
|
-
rotateX: { type: Number, required: false, default: -1 },
|
|
13
|
-
rotateY: { type: Number, required: false, default: -15 }
|
|
14
|
-
});
|
|
15
|
-
function adjacentCardItems(i) {
|
|
16
|
-
return [i - 1, i + 1, i - 4, i + 4].filter((index) => {
|
|
17
|
-
if (index < 0 || index > 15) return false;
|
|
18
|
-
if (i % 4 === 0 && index === i - 1) return false;
|
|
19
|
-
return !(i % 4 === 3 && index === i + 1);
|
|
20
|
-
}).map((index) => card.value?.[index]);
|
|
21
|
-
}
|
|
22
|
-
function removeCardClasses(el, adjacentCards) {
|
|
23
|
-
el.classList.remove("card-raised-big");
|
|
24
|
-
adjacentCards.forEach((adjacentCard) => {
|
|
25
|
-
adjacentCard?.classList.remove("card-raised-small");
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
onMounted(() => {
|
|
29
|
-
card.value?.forEach((el, i) => {
|
|
30
|
-
const { isOutside } = useMouseInElement(el);
|
|
31
|
-
const adjacentCards = adjacentCardItems(i);
|
|
32
|
-
const removeClasses = useDebounceFn(
|
|
33
|
-
() => removeCardClasses(el, adjacentCards),
|
|
34
|
-
200
|
|
35
|
-
);
|
|
36
|
-
watch(isOutside, (isOutside2) => {
|
|
37
|
-
if (!isOutside2) {
|
|
38
|
-
el.classList.add("card-raised-big");
|
|
39
|
-
adjacentCards.forEach((adjacentCard) => {
|
|
40
|
-
adjacentCard?.classList.add("card-raised-small");
|
|
41
|
-
});
|
|
42
|
-
} else {
|
|
43
|
-
removeClasses();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
</script>
|
|
49
|
-
|
|
50
|
-
<template>
|
|
51
|
-
<UContainer :class="cn('relative block', props.class)">
|
|
52
|
-
<div
|
|
53
|
-
:class="
|
|
54
|
-
cn(
|
|
55
|
-
'relative grid w-full max-w-full items-center justify-center gap-2',
|
|
56
|
-
props.cards.length < 4 ? `grid-cols-${props.cards.length}` : 'grid-cols-4'
|
|
57
|
-
)
|
|
58
|
-
"
|
|
59
|
-
:style="{
|
|
60
|
-
transform: `perspective(${props.perspective}px) rotateX(${props.rotateX}deg) rotateY(${props.rotateY}deg)`
|
|
61
|
-
}"
|
|
62
|
-
>
|
|
63
|
-
<div
|
|
64
|
-
v-for="(item, index) in props.cards"
|
|
65
|
-
:key="index"
|
|
66
|
-
ref="card"
|
|
67
|
-
class="card block rounded border border-transparent px-2 py-2 transition-all duration-200"
|
|
68
|
-
:style="{ zIndex: index + 1 }"
|
|
69
|
-
>
|
|
70
|
-
<NuxtLink :to="item.href" target="_blank" :index="index">
|
|
71
|
-
<UIcon
|
|
72
|
-
:name="item.icon"
|
|
73
|
-
class="icon mx-auto h-12 w-auto p-2 lg:h-16 lg:p-3"
|
|
74
|
-
:class="item.iconClass"
|
|
75
|
-
/>
|
|
76
|
-
</NuxtLink>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
</UContainer>
|
|
80
|
-
</template>
|
|
81
|
-
|
|
82
|
-
<style scoped>
|
|
83
|
-
.icon svg{display:block;margin:0 auto;max-height:100%;max-width:100%}.grid-transform:before{background:radial-gradient(circle,#d9fbe8 0,#fff 70%,transparent 100%);content:"";height:120%;left:-10%;opacity:.5;position:absolute;top:-10%;width:150%;z-index:-1}.dark .grid-transform:before{background:radial-gradient(circle,var(--color-neutral-700) 0,var(--color-neutral-800) 70%,transparent 100%)}.card{box-shadow:2px 2px 5px var(--color-primary-300,#38ef7d),3px 3px 10px var(--color-primary-400,#38ef7d),6px 6px 20px var(--color-primary-500,#38ef7d)}.dark .card{box-shadow:2px 2px 5px oklch(from var(--color-primary-900) l c h/.25),3px 3px 10px oklch(from var(--color-primary-900) l c h/.25),6px 6px 20px oklch(from var(--color-primary-900) l c h/.25)}.card svg{opacity:.7;transition:.2s}.dark .card:hover{box-shadow:3px 3px 5px #1f2937,5px 5px 10px #1f2937,10px 10px 20px #1f2937}.card:hover svg{opacity:1}.card svg{shape-rendering:geometricPrecision}.card-raised-small{animation:text-glow-small 1.5s ease-in-out infinite alternate;border:1px solid var(--color-primary-300);transform:scale(1.05) translateX(-5px) translateY(-5px) translateZ(0)}.card-raised-big{animation:text-glow 1.5s ease-in-out infinite alternate;background-color:#fff;transform:scale(1.15) translateX(-20px) translateY(-20px) translateZ(15px)}.card-raised-big,.dark .card-raised-big{border:1px solid v-bind(textGlowStartColor)}.dark .card-raised-big{background-color:oklch(from var(--color-primary-500) l c h/.5)}.dark .card-raised-small{border:1px solid v-bind(textGlowStartColor);transform:scale(1.05) translateX(-5px) translateY(-5px) translateZ(0)}@keyframes text-glow{0%{filter:drop-shadow(0 0 2px v-bind(textGlowStartColor))}to{filter:drop-shadow(0 1px 8px v-bind(textGlowEndColor))}}@keyframes text-glow-small{0%{filter:drop-shadow(0 0 2px v-bind(textGlowEndColor))}to{filter:drop-shadow(0 1px 4px v-bind(textGlowEndColor))}}
|
|
84
|
-
</style>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
interface Cards {
|
|
2
|
-
icon: string;
|
|
3
|
-
href?: string;
|
|
4
|
-
iconClass?: string;
|
|
5
|
-
}
|
|
6
|
-
interface Props {
|
|
7
|
-
class?: string;
|
|
8
|
-
textGlowStartColor?: string;
|
|
9
|
-
perspective?: number;
|
|
10
|
-
textGlowEndColor?: string;
|
|
11
|
-
cards: Cards[];
|
|
12
|
-
rotateX?: number;
|
|
13
|
-
rotateY?: number;
|
|
14
|
-
}
|
|
15
|
-
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
-
declare const _default: typeof __VLS_export;
|
|
17
|
-
export default _default;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
interface FlickeringGridProps {
|
|
2
|
-
squareSize?: number;
|
|
3
|
-
gridGap?: number;
|
|
4
|
-
flickerChance?: number;
|
|
5
|
-
color?: string;
|
|
6
|
-
width?: number;
|
|
7
|
-
height?: number;
|
|
8
|
-
class?: string;
|
|
9
|
-
maxOpacity?: number;
|
|
10
|
-
}
|
|
11
|
-
declare const __VLS_export: import("vue").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
-
declare const _default: typeof __VLS_export;
|
|
13
|
-
export default _default;
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { cn } from "../../utils";
|
|
3
|
-
import { ref, onMounted, onBeforeUnmount, toRefs, computed } from "vue";
|
|
4
|
-
const props = defineProps({
|
|
5
|
-
squareSize: { type: Number, required: false, default: 4 },
|
|
6
|
-
gridGap: { type: Number, required: false, default: 6 },
|
|
7
|
-
flickerChance: { type: Number, required: false, default: 0.3 },
|
|
8
|
-
color: { type: String, required: false, default: "rgb(0, 0, 0)" },
|
|
9
|
-
width: { type: Number, required: false },
|
|
10
|
-
height: { type: Number, required: false },
|
|
11
|
-
class: { type: String, required: false },
|
|
12
|
-
maxOpacity: { type: Number, required: false, default: 0.3 }
|
|
13
|
-
});
|
|
14
|
-
const { squareSize, gridGap, flickerChance, color, maxOpacity, width, height } = toRefs(props);
|
|
15
|
-
const containerRef = ref();
|
|
16
|
-
const canvasRef = ref();
|
|
17
|
-
const context = ref();
|
|
18
|
-
const isInView = ref(false);
|
|
19
|
-
const canvasSize = ref({ width: 0, height: 0 });
|
|
20
|
-
const computedColor = computed(() => {
|
|
21
|
-
if (!context.value) return "rgba(255, 0, 0,";
|
|
22
|
-
const hex = color.value.replace(/^#/, "");
|
|
23
|
-
const bigint = Number.parseInt(hex, 16);
|
|
24
|
-
const r = bigint >> 16 & 255;
|
|
25
|
-
const g = bigint >> 8 & 255;
|
|
26
|
-
const b = bigint & 255;
|
|
27
|
-
return `rgba(${r}, ${g}, ${b},`;
|
|
28
|
-
});
|
|
29
|
-
function setupCanvas(canvas, width2, height2) {
|
|
30
|
-
const dpr = window.devicePixelRatio || 1;
|
|
31
|
-
canvas.width = width2 * dpr;
|
|
32
|
-
canvas.height = height2 * dpr;
|
|
33
|
-
canvas.style.width = `${width2}px`;
|
|
34
|
-
canvas.style.height = `${height2}px`;
|
|
35
|
-
const cols = Math.floor(width2 / (squareSize.value + gridGap.value));
|
|
36
|
-
const rows = Math.floor(height2 / (squareSize.value + gridGap.value));
|
|
37
|
-
const squares = new Float32Array(cols * rows);
|
|
38
|
-
for (let i = 0; i < squares.length; i++) {
|
|
39
|
-
squares[i] = Math.random() * maxOpacity.value;
|
|
40
|
-
}
|
|
41
|
-
return { cols, rows, squares, dpr };
|
|
42
|
-
}
|
|
43
|
-
function updateSquares(squares, deltaTime) {
|
|
44
|
-
for (let i = 0; i < squares.length; i++) {
|
|
45
|
-
if (Math.random() < flickerChance.value * deltaTime) {
|
|
46
|
-
squares[i] = Math.random() * maxOpacity.value;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function drawGrid(ctx, width2, height2, cols, rows, squares, dpr) {
|
|
51
|
-
ctx.clearRect(0, 0, width2, height2);
|
|
52
|
-
ctx.fillStyle = "transparent";
|
|
53
|
-
ctx.fillRect(0, 0, width2, height2);
|
|
54
|
-
for (let i = 0; i < cols; i++) {
|
|
55
|
-
for (let j = 0; j < rows; j++) {
|
|
56
|
-
const opacity = squares[i * rows + j];
|
|
57
|
-
ctx.fillStyle = `${computedColor.value}${opacity})`;
|
|
58
|
-
ctx.fillRect(
|
|
59
|
-
i * (squareSize.value + gridGap.value) * dpr,
|
|
60
|
-
j * (squareSize.value + gridGap.value) * dpr,
|
|
61
|
-
squareSize.value * dpr,
|
|
62
|
-
squareSize.value * dpr
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const gridParams = ref();
|
|
68
|
-
function updateCanvasSize() {
|
|
69
|
-
const newWidth = width.value || containerRef.value.clientWidth;
|
|
70
|
-
const newHeight = height.value || containerRef.value.clientHeight;
|
|
71
|
-
canvasSize.value = { width: newWidth, height: newHeight };
|
|
72
|
-
gridParams.value = setupCanvas(canvasRef.value, newWidth, newHeight);
|
|
73
|
-
}
|
|
74
|
-
let animationFrameId;
|
|
75
|
-
let resizeObserver;
|
|
76
|
-
let intersectionObserver;
|
|
77
|
-
let lastTime = 0;
|
|
78
|
-
function animate(time) {
|
|
79
|
-
if (!isInView.value) return;
|
|
80
|
-
const deltaTime = (time - lastTime) / 1e3;
|
|
81
|
-
lastTime = time;
|
|
82
|
-
updateSquares(gridParams.value.squares, deltaTime);
|
|
83
|
-
drawGrid(
|
|
84
|
-
context.value,
|
|
85
|
-
canvasRef.value.width,
|
|
86
|
-
canvasRef.value.height,
|
|
87
|
-
gridParams.value.cols,
|
|
88
|
-
gridParams.value.rows,
|
|
89
|
-
gridParams.value.squares,
|
|
90
|
-
gridParams.value.dpr
|
|
91
|
-
);
|
|
92
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
93
|
-
}
|
|
94
|
-
onMounted(() => {
|
|
95
|
-
if (!canvasRef.value || !containerRef.value) return;
|
|
96
|
-
context.value = canvasRef.value.getContext("2d");
|
|
97
|
-
if (!context.value) return;
|
|
98
|
-
updateCanvasSize();
|
|
99
|
-
resizeObserver = new ResizeObserver(() => {
|
|
100
|
-
updateCanvasSize();
|
|
101
|
-
});
|
|
102
|
-
intersectionObserver = new IntersectionObserver(
|
|
103
|
-
(entries) => {
|
|
104
|
-
const entry = entries[0];
|
|
105
|
-
if (entry) {
|
|
106
|
-
isInView.value = entry.isIntersecting;
|
|
107
|
-
if (isInView.value && !animationFrameId) {
|
|
108
|
-
lastTime = performance.now();
|
|
109
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
{ threshold: 0 }
|
|
114
|
-
);
|
|
115
|
-
resizeObserver.observe(containerRef.value);
|
|
116
|
-
intersectionObserver.observe(canvasRef.value);
|
|
117
|
-
});
|
|
118
|
-
onBeforeUnmount(() => {
|
|
119
|
-
if (animationFrameId) {
|
|
120
|
-
cancelAnimationFrame(animationFrameId);
|
|
121
|
-
}
|
|
122
|
-
resizeObserver?.disconnect();
|
|
123
|
-
intersectionObserver?.disconnect();
|
|
124
|
-
});
|
|
125
|
-
</script>
|
|
126
|
-
|
|
127
|
-
<template>
|
|
128
|
-
<div ref="containerRef" :class="cn('h-full w-full', props.class)">
|
|
129
|
-
<canvas
|
|
130
|
-
ref="canvasRef"
|
|
131
|
-
class="pointer-events-none"
|
|
132
|
-
:width="canvasSize.width"
|
|
133
|
-
:height="canvasSize.height"
|
|
134
|
-
/>
|
|
135
|
-
</div>
|
|
136
|
-
</template>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
interface FlickeringGridProps {
|
|
2
|
-
squareSize?: number;
|
|
3
|
-
gridGap?: number;
|
|
4
|
-
flickerChance?: number;
|
|
5
|
-
color?: string;
|
|
6
|
-
width?: number;
|
|
7
|
-
height?: number;
|
|
8
|
-
class?: string;
|
|
9
|
-
maxOpacity?: number;
|
|
10
|
-
}
|
|
11
|
-
declare const __VLS_export: import("vue").DefineComponent<FlickeringGridProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FlickeringGridProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
-
declare const _default: typeof __VLS_export;
|
|
13
|
-
export default _default;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type HTMLAttributes } from "vue";
|
|
2
|
-
interface InteractiveGridPatternProps {
|
|
3
|
-
className?: HTMLAttributes["class"];
|
|
4
|
-
squaresClassName?: HTMLAttributes["class"];
|
|
5
|
-
width?: number;
|
|
6
|
-
height?: number;
|
|
7
|
-
squares?: [number, number];
|
|
8
|
-
}
|
|
9
|
-
declare const __VLS_export: import("vue").DefineComponent<InteractiveGridPatternProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<InteractiveGridPatternProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { cn } from "../../utils";
|
|
3
|
-
import { ref, computed } from "vue";
|
|
4
|
-
const props = defineProps({
|
|
5
|
-
className: { type: null, required: false },
|
|
6
|
-
squaresClassName: { type: null, required: false },
|
|
7
|
-
width: { type: Number, required: false, default: 40 },
|
|
8
|
-
height: { type: Number, required: false, default: 40 },
|
|
9
|
-
squares: { type: Array, required: false, default: () => [24, 24] }
|
|
10
|
-
});
|
|
11
|
-
const horizontal = computed(() => props.squares[0]);
|
|
12
|
-
const vertical = computed(() => props.squares[1]);
|
|
13
|
-
const totalSquares = computed(() => horizontal.value * vertical.value);
|
|
14
|
-
const hoveredSquare = ref(null);
|
|
15
|
-
const gridWidth = computed(() => props.width * horizontal.value);
|
|
16
|
-
const gridHeight = computed(() => props.height * vertical.value);
|
|
17
|
-
function getX(index) {
|
|
18
|
-
return index % horizontal.value * props.width;
|
|
19
|
-
}
|
|
20
|
-
function getY(index) {
|
|
21
|
-
return Math.floor(index / horizontal.value) * props.height;
|
|
22
|
-
}
|
|
23
|
-
const svgClass = computed(
|
|
24
|
-
() => cn(
|
|
25
|
-
"absolute inset-0 h-full w-full border border-neutral-400/30",
|
|
26
|
-
props.className
|
|
27
|
-
)
|
|
28
|
-
);
|
|
29
|
-
function getRectClass(index) {
|
|
30
|
-
return cn(
|
|
31
|
-
"stroke-neutral-400/30 transition-all duration-100 ease-in-out [&:not(:hover)]:duration-1000",
|
|
32
|
-
hoveredSquare.value === index ? "fill-neutral-300/30" : "fill-transparent",
|
|
33
|
-
props.squaresClassName
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
function handleMouseEnter(index) {
|
|
37
|
-
hoveredSquare.value = index;
|
|
38
|
-
}
|
|
39
|
-
function handleMouseLeave() {
|
|
40
|
-
hoveredSquare.value = null;
|
|
41
|
-
}
|
|
42
|
-
</script>
|
|
43
|
-
|
|
44
|
-
<template>
|
|
45
|
-
<svg :width="gridWidth" :height="gridHeight" :class="svgClass">
|
|
46
|
-
<rect
|
|
47
|
-
v-for="(_, index) in totalSquares"
|
|
48
|
-
:key="index"
|
|
49
|
-
:x="getX(index)"
|
|
50
|
-
:y="getY(index)"
|
|
51
|
-
:width="width"
|
|
52
|
-
:height="height"
|
|
53
|
-
:class="getRectClass(index)"
|
|
54
|
-
@mouseenter="handleMouseEnter(index)"
|
|
55
|
-
@mouseleave="handleMouseLeave"
|
|
56
|
-
/>
|
|
57
|
-
</svg>
|
|
58
|
-
</template>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type HTMLAttributes } from "vue";
|
|
2
|
-
interface InteractiveGridPatternProps {
|
|
3
|
-
className?: HTMLAttributes["class"];
|
|
4
|
-
squaresClassName?: HTMLAttributes["class"];
|
|
5
|
-
width?: number;
|
|
6
|
-
height?: number;
|
|
7
|
-
squares?: [number, number];
|
|
8
|
-
}
|
|
9
|
-
declare const __VLS_export: import("vue").DefineComponent<InteractiveGridPatternProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<InteractiveGridPatternProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|