@wyxos/vibe 1.6.6 → 1.6.7
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 +1 -1
- package/lib/apple-touch-icon-114x114.png +0 -0
- package/lib/apple-touch-icon-120x120.png +0 -0
- package/lib/apple-touch-icon-144x144.png +0 -0
- package/lib/apple-touch-icon-152x152.png +0 -0
- package/lib/apple-touch-icon-180x180.png +0 -0
- package/lib/apple-touch-icon-57x57.png +0 -0
- package/lib/apple-touch-icon-60x60.png +0 -0
- package/lib/apple-touch-icon-72x72.png +0 -0
- package/lib/apple-touch-icon-76x76.png +0 -0
- package/lib/favicon-128x128.png +0 -0
- package/lib/favicon-16x16.png +0 -0
- package/lib/favicon-256x256.png +0 -0
- package/lib/favicon-32x32.png +0 -0
- package/lib/favicon-48x48.png +0 -0
- package/lib/favicon-64x64.png +0 -0
- package/lib/favicon.ico +0 -0
- package/lib/index.js +538 -470
- package/lib/logo-dark.svg +36 -0
- package/lib/logo-light.svg +29 -0
- package/lib/logo.svg +32 -0
- package/lib/manifest.json +41 -0
- package/lib/vibe.css +1 -1
- package/package.json +5 -2
- package/src/App.vue +30 -159
- package/src/Masonry.vue +3 -2
- package/src/components/MasonryItem.vue +123 -21
- package/src/main.ts +2 -1
- package/src/pages.json +36401 -32501
- package/src/router/index.ts +20 -0
- package/src/style.css +31 -31
- package/src/views/Examples.vue +20 -0
- package/src/views/Home.vue +169 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRouter, createWebHashHistory } from 'vue-router'
|
|
2
|
+
|
|
3
|
+
const router = createRouter({
|
|
4
|
+
history: createWebHashHistory(), // Hash mode works perfectly with GitHub Pages
|
|
5
|
+
routes: [
|
|
6
|
+
{
|
|
7
|
+
path: '/',
|
|
8
|
+
name: 'home',
|
|
9
|
+
component: () => import('../views/Home.vue')
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
path: '/examples',
|
|
13
|
+
name: 'examples',
|
|
14
|
+
component: () => import('../views/Examples.vue')
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export default router
|
|
20
|
+
|
package/src/style.css
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
:root {
|
|
5
|
-
font-family: 'Inter', sans-serif;
|
|
6
|
-
-webkit-font-smoothing: antialiased;
|
|
7
|
-
-moz-osx-font-smoothing: grayscale;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
body {
|
|
11
|
-
background-color: #f8fafc;
|
|
12
|
-
color: #0f172a;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/* Custom Scrollbar */
|
|
16
|
-
::-webkit-scrollbar {
|
|
17
|
-
width: 8px;
|
|
18
|
-
height: 8px;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
::-webkit-scrollbar-track {
|
|
22
|
-
background: transparent;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
::-webkit-scrollbar-thumb {
|
|
26
|
-
background: #93c5fd;
|
|
27
|
-
border-radius: 4px;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
::-webkit-scrollbar-thumb:hover {
|
|
31
|
-
background: #60a5fa;
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
:root {
|
|
5
|
+
font-family: 'Inter', sans-serif;
|
|
6
|
+
-webkit-font-smoothing: antialiased;
|
|
7
|
+
-moz-osx-font-smoothing: grayscale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
background-color: #f8fafc;
|
|
12
|
+
color: #0f172a;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Custom Scrollbar */
|
|
16
|
+
::-webkit-scrollbar {
|
|
17
|
+
width: 8px;
|
|
18
|
+
height: 8px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
::-webkit-scrollbar-track {
|
|
22
|
+
background: transparent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
::-webkit-scrollbar-thumb {
|
|
26
|
+
background: #93c5fd;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
::-webkit-scrollbar-thumb:hover {
|
|
31
|
+
background: #60a5fa;
|
|
32
32
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="min-h-screen bg-slate-50 p-8 pt-20">
|
|
3
|
+
<div class="max-w-4xl mx-auto">
|
|
4
|
+
<h1 class="text-4xl font-bold text-slate-800 mb-6">Examples</h1>
|
|
5
|
+
<p class="text-slate-600 mb-8">This is a placeholder for examples page.</p>
|
|
6
|
+
|
|
7
|
+
<div class="bg-white rounded-xl shadow-sm p-6">
|
|
8
|
+
<h2 class="text-2xl font-semibold text-slate-800 mb-4">Coming Soon</h2>
|
|
9
|
+
<p class="text-slate-600">
|
|
10
|
+
Examples and code snippets will be added here soon.
|
|
11
|
+
</p>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
// Examples page placeholder
|
|
19
|
+
</script>
|
|
20
|
+
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<main class="flex flex-col h-screen overflow-hidden bg-slate-50 relative pt-[112px]">
|
|
3
|
+
<!-- Fixed Sub-Header -->
|
|
4
|
+
<header class="fixed top-[53px] left-0 right-0 z-20 w-full bg-white/80 backdrop-blur-md border-b border-slate-200 shadow-sm transition-all duration-300">
|
|
5
|
+
<div class="max-w-7xl mx-auto px-4 h-14 flex items-center justify-end">
|
|
6
|
+
<!-- Right: Controls -->
|
|
7
|
+
<div class="flex items-center gap-3">
|
|
8
|
+
<!-- Status Pill -->
|
|
9
|
+
<div v-if="masonry" class="hidden md:flex items-center gap-2 text-xs font-medium text-slate-600 bg-slate-50 px-3 py-1.5 rounded-lg border border-slate-100">
|
|
10
|
+
<span class="flex items-center gap-1.5">
|
|
11
|
+
<span class="w-1.5 h-1.5 rounded-full shadow-sm" :class="masonry.isLoading ? 'bg-amber-400 animate-pulse' : 'bg-emerald-400'"></span>
|
|
12
|
+
{{ masonry.isLoading ? 'Loading...' : 'Ready' }}
|
|
13
|
+
</span>
|
|
14
|
+
<span class="w-px h-3 bg-slate-200"></span>
|
|
15
|
+
<span>{{ items.length }} items</span>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="h-8 w-px bg-slate-100 mx-1 hidden md:block"></div>
|
|
19
|
+
|
|
20
|
+
<!-- Action Buttons -->
|
|
21
|
+
<div class="flex items-center gap-1">
|
|
22
|
+
<button
|
|
23
|
+
@click="showLayoutControls = !showLayoutControls"
|
|
24
|
+
class="w-9 h-9 flex items-center justify-center text-slate-500 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all duration-200"
|
|
25
|
+
:class="{ 'text-blue-600 bg-blue-50 ring-2 ring-blue-100': showLayoutControls }"
|
|
26
|
+
title="Layout Settings"
|
|
27
|
+
>
|
|
28
|
+
<i class="fas fa-sliders text-sm"></i>
|
|
29
|
+
</button>
|
|
30
|
+
|
|
31
|
+
<a
|
|
32
|
+
href="https://github.com/wyxos/vibe"
|
|
33
|
+
target="_blank"
|
|
34
|
+
class="w-9 h-9 flex items-center justify-center text-slate-400 hover:text-slate-900 hover:bg-slate-50 rounded-xl transition-all duration-200"
|
|
35
|
+
title="View on GitHub"
|
|
36
|
+
>
|
|
37
|
+
<i class="fab fa-github text-lg"></i>
|
|
38
|
+
</a>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<!-- Layout Controls Panel -->
|
|
44
|
+
<transition
|
|
45
|
+
enter-active-class="transition duration-200 ease-out"
|
|
46
|
+
enter-from-class="transform -translate-y-2 opacity-0"
|
|
47
|
+
enter-to-class="transform translate-y-0 opacity-100"
|
|
48
|
+
leave-active-class="transition duration-150 ease-in"
|
|
49
|
+
leave-from-class="transform translate-y-0 opacity-100"
|
|
50
|
+
leave-to-class="transform -translate-y-2 opacity-0"
|
|
51
|
+
>
|
|
52
|
+
<div v-if="showLayoutControls" class="absolute top-full right-4 mt-2 w-full max-w-lg bg-white/90 backdrop-blur-md border border-slate-200 shadow-xl rounded-xl p-6 pointer-events-auto z-30">
|
|
53
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
54
|
+
<!-- Column Settings -->
|
|
55
|
+
<div>
|
|
56
|
+
<h3 class="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-3">Column Configuration</h3>
|
|
57
|
+
<div class="grid grid-cols-3 sm:grid-cols-6 gap-3">
|
|
58
|
+
<div v-for="(val, key) in layoutParams.sizes" :key="key" class="flex flex-col gap-1.5">
|
|
59
|
+
<label class="text-[10px] font-bold text-slate-500 uppercase text-center">{{ key }}</label>
|
|
60
|
+
<input
|
|
61
|
+
v-model.number="layoutParams.sizes[key]"
|
|
62
|
+
type="number"
|
|
63
|
+
min="1"
|
|
64
|
+
class="w-full px-2 py-1.5 bg-slate-50 border border-slate-200 rounded-lg text-center text-sm font-medium text-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<!-- Spacing Settings -->
|
|
71
|
+
<div>
|
|
72
|
+
<h3 class="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-3">Spacing</h3>
|
|
73
|
+
<div class="grid grid-cols-2 gap-4">
|
|
74
|
+
<div class="flex flex-col gap-1.5">
|
|
75
|
+
<label class="text-[10px] font-bold text-slate-500 uppercase">Header Offset</label>
|
|
76
|
+
<div class="relative">
|
|
77
|
+
<input
|
|
78
|
+
v-model.number="layoutParams.header"
|
|
79
|
+
type="number"
|
|
80
|
+
min="0"
|
|
81
|
+
class="w-full pl-3 pr-8 py-1.5 bg-slate-50 border border-slate-200 rounded-lg text-sm font-medium text-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all"
|
|
82
|
+
/>
|
|
83
|
+
<span class="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-slate-400">px</span>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="flex flex-col gap-1.5">
|
|
87
|
+
<label class="text-[10px] font-bold text-slate-500 uppercase">Footer Offset</label>
|
|
88
|
+
<div class="relative">
|
|
89
|
+
<input
|
|
90
|
+
v-model.number="layoutParams.footer"
|
|
91
|
+
type="number"
|
|
92
|
+
min="0"
|
|
93
|
+
class="w-full pl-3 pr-8 py-1.5 bg-slate-50 border border-slate-200 rounded-lg text-sm font-medium text-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all"
|
|
94
|
+
/>
|
|
95
|
+
<span class="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-slate-400">px</span>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</transition>
|
|
103
|
+
</header>
|
|
104
|
+
|
|
105
|
+
<!-- Main Content -->
|
|
106
|
+
<div class="flex flex-1 overflow-hidden relative p-5">
|
|
107
|
+
<masonry v-model:items="items" :get-next-page="getPage" :load-at-page="1" :layout="layout" ref="masonry">
|
|
108
|
+
<!-- MasonryItem is used automatically, but you can customize it -->
|
|
109
|
+
</masonry>
|
|
110
|
+
</div>
|
|
111
|
+
</main>
|
|
112
|
+
</template>
|
|
113
|
+
|
|
114
|
+
<script setup lang="ts">
|
|
115
|
+
import Masonry from "../Masonry.vue";
|
|
116
|
+
import { ref, reactive, computed } from "vue";
|
|
117
|
+
import fixture from "../pages.json";
|
|
118
|
+
import type { MasonryItem, GetPageResult } from "../types";
|
|
119
|
+
|
|
120
|
+
const items = ref<MasonryItem[]>([]);
|
|
121
|
+
|
|
122
|
+
const masonry = ref<InstanceType<typeof Masonry> | null>(null);
|
|
123
|
+
|
|
124
|
+
const layoutParams = reactive({
|
|
125
|
+
sizes: {
|
|
126
|
+
base: 1,
|
|
127
|
+
sm: 2,
|
|
128
|
+
md: 3,
|
|
129
|
+
lg: 4,
|
|
130
|
+
xl: 5,
|
|
131
|
+
'2xl': 10
|
|
132
|
+
},
|
|
133
|
+
header: 0,
|
|
134
|
+
footer: 0
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const layout = computed(() => ({
|
|
138
|
+
sizes: { ...layoutParams.sizes },
|
|
139
|
+
header: layoutParams.header,
|
|
140
|
+
footer: layoutParams.footer
|
|
141
|
+
}));
|
|
142
|
+
|
|
143
|
+
const showLayoutControls = ref(false);
|
|
144
|
+
|
|
145
|
+
const getPage = async (page: number): Promise<GetPageResult> => {
|
|
146
|
+
return new Promise((resolve) => {
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
// Check if the page exists in the fixture
|
|
149
|
+
const pageData = (fixture as any[])[page - 1] as { items: MasonryItem[] } | undefined;
|
|
150
|
+
|
|
151
|
+
if (!pageData) {
|
|
152
|
+
// Return empty items if page doesn't exist
|
|
153
|
+
resolve({
|
|
154
|
+
items: [],
|
|
155
|
+
nextPage: null // null indicates no more pages
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const output: GetPageResult = {
|
|
161
|
+
items: pageData.items,
|
|
162
|
+
nextPage: page < (fixture as any[]).length ? page + 1 : null
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
resolve(output);
|
|
166
|
+
}, 1000);
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
</script>
|