ReviewOS

also looking at this

stacks/ts-qr-codes

chore(deps): update dependency react to 19.2.7

#2137
Closed chris wants to merge buddy-bot/update-major-update-react into main
222 files +16350 -1825

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

docs/.vitepress/components.d.tsdeleted+0-19
Changes to docs/.vitepress/components.d.ts
@@ -1,19 +0,0 @@
1/* eslint-disable */
2// @ts-nocheck
3// Generated by unplugin-vue-components
4// Read more: https://github.com/vuejs/core/pull/3399
5// biome-ignore lint: disable
6export {}
7
8/* prettier-ignore */
9declare module 'vue' {
10 export interface GlobalComponents {
11 BarcodeDemo: typeof import('./theme/components/BarcodeDemo.vue')['default']
12 Home: typeof import('./theme/components/Home.vue')['default']
13 HomeContributors: typeof import('./theme/components/HomeContributors.vue')['default']
14 HomeSponsors: typeof import('./theme/components/HomeSponsors.vue')['default']
15 HomeTeam: typeof import('./theme/components/HomeTeam.vue')['default']
16 QRCodeDemo: typeof import('./theme/components/QRCodeDemo.vue')['default']
17 TeamMember: typeof import('./theme/components/TeamMember.vue')['default']
18 }
19}
docs/.vitepress/config.tsdeleted+0-201
Changes to docs/.vitepress/config.ts
@@ -1,201 +0,0 @@
1import type { HeadConfig } from 'vitepress'
2import { transformerTwoslash } from '@shikijs/vitepress-twoslash'
3import { withPwa } from '@vite-pwa/vitepress'
4import { defineConfig } from 'vitepress'
5import vite from './vite.config'
6
7// https://vitepress.dev/reference/site-config
8
9const analyticsHead: HeadConfig[] = [
10 [
11 'script',
12 {
13 'src': 'https://cdn.usefathom.com/script.js',
14 'data-site': 'PFISGDDM',
15 'defer': '',
16 },
17 ],
18]
19
20const nav = [
21 { text: 'News', link: 'https://stacksjs.org/news' },
22 {
23 text: 'Changelog',
24 link: 'https://github.com/stacksjs/qrx/blob/main/CHANGELOG.md',
25 },
26 // { text: 'Blog', link: 'https://updates.ow3.org' },
27 {
28 text: 'Resources',
29 items: [
30 { text: 'Team', link: '/team' },
31 { text: 'Showcase', link: '/showcase' },
32 { text: 'Sponsors', link: '/sponsors' },
33 { text: 'Partners', link: '/partners' },
34 { text: 'Postcardware', link: '/postcardware' },
35 { text: 'Stargazers', link: '/stargazers' },
36 { text: 'License', link: '/license' },
37 {
38 items: [
39 {
40 text: 'Awesome Stacks',
41 link: 'https://github.com/stacksjs/awesome-stacks',
42 },
43 {
44 text: 'Contributing',
45 link: 'https://github.com/stacksjs/stacks/blob/main/.github/CONTRIBUTING.md',
46 },
47 ],
48 },
49 ],
50 },
51]
52
53const sidebar = [
54 {
55 text: 'Get Started',
56 items: [
57 { text: 'Intro', link: '/intro' },
58 { text: 'Install', link: '/install' },
59 { text: 'Usage', link: '/usage' },
60 { text: 'Config', link: '/config' },
61 { text: 'Demo', link: '/demo' },
62 ],
63 },
64 {
65 text: 'API',
66 items: [
67 {
68 text: 'Barcodes',
69 link: '/api/barcode',
70 collapsed: false,
71 items: [
72 {
73 text: 'CODE128',
74 link: '/api/barcode/CODE128',
75 },
76 { text: 'CODE39', link: '/api/barcode/CODE39' },
77 {
78 text: 'EAN / UPC',
79 link: '/api/barcode/EAN/',
80 items: [
81 { text: 'EAN-13', link: '/api/barcode/EAN/EAN-13' },
82 { text: 'EAN-8', link: '/api/barcode/EAN/EAN-8' },
83 { text: 'EAN-5', link: '/api/barcode/EAN/EAN-5' },
84 { text: 'EAN-2', link: '/api/barcode/EAN/EAN-2' },
85 { text: 'UPC-A', link: '/api/barcode/EAN/UPC-A' },
86 { text: 'UPC-E', link: '/api/barcode/EAN/UPC-E' },
87 ],
88 },
89 { text: 'ITF-14', link: '/api/barcode/ITF-14' },
90 {
91 text: 'MSI',
92 link: '/api/barcode/MSI/',
93 items: [
94 { text: 'MSI10', link: '/api/barcode/MSI/MSI10' },
95 { text: 'MSI11', link: '/api/barcode/MSI/MSI11' },
96 { text: 'MSI1010', link: '/api/barcode/MSI/MSI1010' },
97 { text: 'MSI1110', link: '/api/barcode/MSI/MSI1110' },
98 ],
99 },
100 { text: 'Pharmacode', link: '/api/barcode/Pharmacode' },
101 { text: 'Codabar', link: '/api/barcode/Codabar' },
102 ],
103 },
104 { text: 'QR Codes', link: '/api/qr-code' },
105 ],
106 },
107 { text: 'Showcase', link: '/showcase' },
108]
109const description = 'TypeScript QR & Barcode generating & reading. Lightweight & powerful.'
110const title = 'qrx | QR & Barcode generating & reading. Lightweight & powerful.'
111
112export default withPwa(
113 defineConfig({
114 lang: 'en-US',
115 title: 'qrx',
116 description,
117 metaChunk: true,
118 cleanUrls: true,
119 lastUpdated: true,
120
121 head: [
122 ['link', { rel: 'icon', type: 'image/svg+xml', href: './images/logo-mini.svg' }],
123 ['link', { rel: 'icon', type: 'image/png', href: './images/logo.png' }],
124 ['meta', { name: 'theme-color', content: '#0A0ABC' }],
125 ['meta', { name: 'title', content: title }],
126 ['meta', { name: 'description', content: description }],
127 ['meta', { name: 'author', content: 'Stacks.js, Inc.' }],
128 ['meta', {
129 name: 'tags',
130 content: 'qrx, typescript, qrcode, barcode, qr, bar, code, generate, read, lightweight, powerful, scanner, reader, decoder, encoder, stacksjs, stacks',
131 }],
132
133 ['meta', { property: 'og:type', content: 'website' }],
134 ['meta', { property: 'og:locale', content: 'en' }],
135 ['meta', { property: 'og:title', content: title }],
136 ['meta', { property: 'og:description', content: description }],
137
138 ['meta', { property: 'og:site_name', content: 'qrx' }],
139 ['meta', { property: 'og:image', content: 'https://ts-quick-reaction.netlify.app/images/og-image.png' }],
140 ['meta', { property: 'og:url', content: 'https://ts-quick-reaction.netlify.app/' }],
141 // ['script', { 'src': 'https://cdn.usefathom.com/script.js', 'data-site': '', 'data-spa': 'auto', 'defer': '' }],
142 ...analyticsHead,
143 ],
144
145 themeConfig: {
146 search: {
147 provider: 'local',
148 },
149 logo: {
150 light: './images/logo-transparent.svg',
151 dark: './images/logo-white-transparent.svg',
152 },
153
154 nav,
155 sidebar,
156
157 editLink: {
158 pattern: 'https://github.com/stacksjs/stacks/edit/main/docs/docs/:path',
159 text: 'Edit this page on GitHub',
160 },
161
162 footer: {
163 message: 'Released under the MIT License.',
164 copyright: 'Copyright © 2025-present Stacks.js, Inc.',
165 },
166
167 socialLinks: [
168 { icon: 'twitter', link: 'https://twitter.com/stacksjs' },
169 { icon: 'bluesky', link: 'https://bsky.app/profile/chrisbreuer.dev' },
170 { icon: 'github', link: 'https://github.com/stacksjs/qrx' },
171 { icon: 'discord', link: 'https://discord.gg/stacksjs' },
172 ],
173
174 // algolia: services.algolia,
175
176 // carbonAds: {
177 // code: '',
178 // placement: '',
179 // },
180 },
181
182 pwa: {
183 manifest: {
184 theme_color: '#0A0ABC',
185 },
186 },
187
188 markdown: {
189 theme: {
190 light: 'github-light',
191 dark: 'github-dark',
192 },
193
194 codeTransformers: [
195 transformerTwoslash(),
196 ],
197 },
198
199 vite,
200 }),
201)
docs/.vitepress/sw.tsdeleted+0-123
Changes to docs/.vitepress/sw.ts
@@ -1,123 +0,0 @@
1/// <reference types="vite/client" />
2
3/// <reference lib="webworker" />
4
5import { CacheableResponsePlugin } from 'workbox-cacheable-response'
6import { ExpirationPlugin } from 'workbox-expiration'
7import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching'
8import { NavigationRoute, registerRoute } from 'workbox-routing'
9import { NetworkFirst, NetworkOnly, StaleWhileRevalidate } from 'workbox-strategies'
10
11declare let self: ServiceWorkerGlobalScope
12
13const entries = self.__WB_MANIFEST
14
15// self.__WB_MANIFEST is the default injection point
16precacheAndRoute(entries)
17
18// clean old assets
19cleanupOutdatedCaches()
20
21let allowlist: undefined | RegExp[]
22if (import.meta.env.DEV)
23 allowlist = [/^\/$/]
24
25if (import.meta.env.PROD) {
26 const swPath = self.location.pathname.lastIndexOf('/')
27 const base = swPath === 0 ? '/' : self.location.pathname.slice(0, swPath + 1)
28 function escapeStringRegexp(value: string) {
29 // Escape characters with special meaning either inside or outside character sets.
30 // Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
31 return value
32 .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
33 .replace(/-/g, '\\x2d')
34 }
35 allowlist = entries.filter((page) => {
36 return typeof page === 'string'
37 ? page.endsWith('.html')
38 : page.url.endsWith('.html')
39 }).map((page) => {
40 const url = typeof page === 'string' ? page : page.url
41 const regex = url === 'index.html'
42 ? escapeStringRegexp(base)
43 : escapeStringRegexp(`${base}${url.replace(/\.html$/, '')}`)
44 return new RegExp(`^${regex}(\\.html)?$`)
45 })
46 registerRoute(
47 ({ request, sameOrigin }) => {
48 return sameOrigin && request.mode === 'navigate'
49 },
50 new NetworkOnly({
51 plugins: [{
52 /* this callback will be called when the fetch call fails */
53 handlerDidError: async () => Response.redirect('404', 302),
54 /* this callback will prevent caching the response */
55 cacheWillUpdate: async () => null,
56 }],
57 }),
58 'GET',
59 )
60 // googleapis
61 registerRoute(
62 /^https:\/\/fonts\.googleapis\.com\/.*/i,
63 new NetworkFirst({
64 cacheName: 'google-fonts-cache',
65 plugins: [
66 new CacheableResponsePlugin({ statuses: [0, 200] }),
67 // we only need a few entries
68 new ExpirationPlugin({
69 maxEntries: 10,
70 maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days
71 }),
72 ],
73 }),
74 )
75 // gstatic
76 registerRoute(
77 /^https:\/\/fonts\.gstatic\.com\/.*/i,
78 new StaleWhileRevalidate({
79 cacheName: 'google-fonts-cache',
80 plugins: [
81 new CacheableResponsePlugin({ statuses: [0, 200] }),
82 // we only need a few entries
83 new ExpirationPlugin({
84 maxEntries: 10,
85 maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days
86 }),
87 ],
88 }),
89 )
90 // antfu sponsors
91 registerRoute(
92 /^https:\/\/cdn\.jsdelivr\.net\/.*/i,
93 new NetworkFirst({
94 cacheName: 'jsdelivr-images-cache',
95 plugins: [
96 new CacheableResponsePlugin({ statuses: [0, 200] }),
97 // we only need a few entries
98 new ExpirationPlugin({
99 maxEntries: 10,
100 maxAgeSeconds: 60 * 60 * 24 * 7, // <== 7 days
101 }),
102 ],
103 }),
104 )
105}
106
107// to allow work offline
108registerRoute(new NavigationRoute(
109 createHandlerBoundToURL('index.html'),
110 { allowlist },
111))
112
113// Skip-Waiting Service Worker-based solution
114self.addEventListener('activate', async () => {
115 // after we've taken over, iterate over all the current clients (windows)
116 const clients = await self.clients.matchAll({ type: 'window' })
117 clients.forEach((client) => {
118 // ...and refresh each one of them
119 client.navigate(client.url)
120 })
121})
122
123self.skipWaiting()
docs/.vitepress/theme/components/BarcodeDemo.vuedeleted+0-449
Changes to docs/.vitepress/theme/components/BarcodeDemo.vue
@@ -1,449 +0,0 @@
1<script setup lang="ts">
2import { barcode } from "ts-qr-codes";
3import { nextTick, onMounted, ref, watch } from "vue";
4
5interface BarcodeFormat {
6 value: string;
7 label: string;
8 pattern: RegExp;
9 hint: string;
10 example: string;
11}
12
13// eslint-disable-next-line no-control-regex
14const patternCode128 = /^[\x00-\x7F\xC8-\xD3]+$/;
15
16const formats: BarcodeFormat[] = [
17 {
18 value: "CODE128",
19 label: "Code 128",
20 pattern: patternCode128,
21 hint: "Accepts any ASCII character",
22 example: "123ABC",
23 },
24 {
25 value: "EAN13",
26 label: "EAN-13",
27 pattern: /^\d{12,13}$/,
28 hint: "Must be exactly 12 or 13 digits",
29 example: "5901234123457",
30 },
31 {
32 value: "EAN8",
33 label: "EAN-8",
34 pattern: /^\d{7,8}$/,
35 hint: "Must be exactly 7 or 8 digits",
36 example: "96385074",
37 },
38 {
39 value: "EAN5",
40 label: "EAN-5",
41 pattern: /^\d{5}$/,
42 hint: "Must be exactly 5 digits",
43 example: "54495",
44 },
45 {
46 value: "EAN2",
47 label: "EAN-2",
48 pattern: /^\d{2}$/,
49 hint: "Must be exactly 2 digits",
50 example: "53",
51 },
52 {
53 value: "UPC",
54 label: "UPC",
55 pattern: /^\d{11,12}$/,
56 hint: "Must be exactly 11 or 12 digits",
57 example: "123456789012",
58 },
59 {
60 value: "CODE39",
61 label: "Code 39",
62 pattern: /^[0-9A-Z\-. $/+%]+$/,
63 hint: "Accepts digits, uppercase letters, and special characters: -. $/+%",
64 example: "CODE-39",
65 },
66 {
67 value: "ITF14",
68 label: "ITF-14",
69 pattern: /^\d{13,14}$/,
70 hint: "Must be exactly 13 or 14 digits",
71 example: "15400141288763",
72 },
73 {
74 value: "MSI",
75 label: "MSI",
76 pattern: /^\d+$/,
77 hint: "Accepts only digits",
78 example: "123456",
79 },
80 {
81 value: "MSI10",
82 label: "MSI-10",
83 pattern: /^\d+$/,
84 hint: "Accepts only digits",
85 example: "123456",
86 },
87 {
88 value: "MSI11",
89 label: "MSI-11",
90 pattern: /^\d+$/,
91 hint: "Accepts only digits",
92 example: "123456",
93 },
94 {
95 value: "MSI1010",
96 label: "MSI-1010",
97 pattern: /^\d+$/,
98 hint: "Accepts only digits",
99 example: "123456",
100 },
101 {
102 value: "MSI1110",
103 label: "MSI-1110",
104 pattern: /^\d+$/,
105 hint: "Accepts only digits",
106 example: "123456",
107 },
108 {
109 value: "pharmacode",
110 label: "Pharmacode",
111 pattern: /^\d+$/,
112 hint: "Must be a number between 3 and 131070",
113 example: "1234",
114 },
115 {
116 value: "codabar",
117 label: "Codabar",
118 pattern: /^[A-D][0-9\-$:/.+]+[A-D]$/,
119 hint: "Must start and end with A-D, content can be digits and -$:/.+",
120 example: "A12345B",
121 },
122];
123
124const error = ref("");
125const currentFormat = ref(formats[0]);
126const text = ref(formats[0].example);
127const format = ref("CODE128");
128const width = ref(2);
129const height = ref(100);
130const displayValue = ref(true);
131const fontOptions = ref("");
132const font = ref("monospace");
133const textAlign = ref("center");
134const textPosition = ref("bottom");
135const textMargin = ref(2);
136const fontSize = ref(20);
137const background = ref("#ffffff");
138const lineColor = ref("#ffffff");
139const margin = ref(10);
140
141watch(format, (newFormat) => {
142 currentFormat.value =
143 formats.find((f) => f.value === newFormat) || formats[0];
144 // Don't automatically change the text when format changes
145});
146
147const barcodeContainer = ref<HTMLElement | null>(null);
148
149function validateInput(): boolean {
150 const format = currentFormat.value;
151 if (!format.pattern.test(text.value)) {
152 error.value = `Invalid format for ${format.label}. ${format.hint}`;
153 return false;
154 }
155
156 if (format.value === "pharmacode") {
157 const num = Number(text.value);
158 if (num < 3 || num > 131070) {
159 error.value = "Pharmacode must be a number between 3 and 131070";
160 return false;
161 }
162 }
163
164 return true;
165}
166
167function updateBarcode() {
168 if (!barcodeContainer.value) return;
169
170 error.value = "";
171
172 if (!validateInput()) {
173 return;
174 }
175
176 try {
177 // Create SVG element inside container
178 const svgElement = document.createElementNS(
179 "http://www.w3.org/2000/svg",
180 "svg",
181 );
182 barcodeContainer.value.innerHTML = "";
183 barcodeContainer.value.appendChild(svgElement);
184
185 // Create new barcode
186 barcode(svgElement, text.value, {
187 format: format.value,
188 width: Number(width.value),
189 height: Number(height.value),
190 displayValue: displayValue.value,
191 fontOptions: fontOptions.value,
192 font: font.value,
193 textAlign: textAlign.value,
194 textPosition: textPosition.value,
195 textMargin: Number(textMargin.value),
196 fontSize: Number(fontSize.value),
197 background,
198 lineColor: lineColor.value,
199 margin: Number(margin.value),
200 elementTag: "svg",
201 valid: (valid: boolean) => {
202 if (!valid)
203 error.value = "Invalid barcode input for the selected format";
204 },
205 });
206 } catch (err: any) {
207 error.value = err.message || "Error rendering barcode";
208 console.error("Error rendering barcode:", err);
209 }
210}
211
212onMounted(() => {
213 // Wait for next tick to ensure DOM is ready
214 nextTick(() => {
215 updateBarcode();
216 });
217});
218
219watch(
220 [
221 text,
222 format,
223 width,
224 height,
225 displayValue,
226 fontOptions,
227 font,
228 textAlign,
229 textPosition,
230 textMargin,
231 fontSize,
232 background,
233 lineColor,
234 margin,
235 ],
236 () => {
237 updateBarcode();
238 },
239);
240</script>
241
242<template>
243 <div class="barcode-demo">
244 <div class="controls">
245 <div class="control-grid">
246 <!-- Text Input -->
247 <div class="input-group full-width">
248 <label for="barcode-text">Text to encode:</label>
249 <input
250 id="barcode-text"
251 v-model="text"
252 type="text"
253 placeholder="Enter text to encode"
254 />
255 </div>
256
257 <!-- Format Selection -->
258 <div class="input-group">
259 <label for="format">Format:</label>
260 <select id="format" v-model="format">
261 <option v-for="fmt in formats" :key="fmt.value" :value="fmt.value">
262 {{ fmt.label }}
263 </option>
264 </select>
265 <div class="format-hint">
266 <p>{{ currentFormat.hint }}</p>
267 <p class="example">Example: {{ currentFormat.example }}</p>
268 </div>
269 </div>
270
271 <!-- Display Value Toggle -->
272 <div class="input-group checkbox-group">
273 <label>
274 <input v-model="displayValue" type="checkbox" />
275 Display Value
276 </label>
277 </div>
278
279 <!-- Width Input -->
280 <div class="input-group">
281 <label for="width">Width:</label>
282 <input id="width" v-model="width" type="number" min="1" />
283 </div>
284
285 <!-- Height Input -->
286 <div class="input-group">
287 <label for="height">Height:</label>
288 <input id="height" v-model="height" type="number" min="1" />
289 </div>
290
291 <!-- Text Position -->
292 <div class="input-group">
293 <label for="text-position">Text Position:</label>
294 <select id="text-position" v-model="textPosition">
295 <option value="bottom">Bottom</option>
296 <option value="top">Top</option>
297 </select>
298 </div>
299
300 <!-- Text Alignment -->
301 <div class="input-group">
302 <label for="text-align">Text Alignment:</label>
303 <select id="text-align" v-model="textAlign">
304 <option value="center">Center</option>
305 <option value="left">Left</option>
306 <option value="right">Right</option>
307 </select>
308 </div>
309
310 <!-- Font Size -->
311 <div class="input-group">
312 <label for="font-size">Font Size:</label>
313 <input id="font-size" v-model="fontSize" type="number" min="1" />
314 </div>
315
316 <!-- Margin -->
317 <div class="input-group">
318 <label for="margin">Margin:</label>
319 <input id="margin" v-model="margin" type="number" min="0" />
320 </div>
321
322 <!-- Line Color -->
323 <div class="input-group">
324 <label for="line-color">Line Color:</label>
325 <input id="line-color" v-model="lineColor" type="color" />
326 </div>
327
328 <!-- Background Color -->
329 <div class="input-group">
330 <label for="background">Background:</label>
331 <input id="background" v-model="background" type="color" />
332 </div>
333 </div>
334 </div>
335
336 <div class="barcode-section">
337 <div v-if="error" class="error-message">
338 {{ error }}
339 </div>
340
341 <div ref="barcodeContainer" class="barcode-container" />
342 </div>
343 </div>
344</template>
345
346<style scoped>
347.barcode-demo {
348 padding: 20px;
349 max-width: 600px;
350 margin: 0 auto;
351}
352
353.controls {
354 margin-bottom: 20px;
355}
356
357.control-grid {
358 display: grid;
359 grid-template-columns: repeat(2, 1fr);
360 gap: 15px;
361}
362
363.input-group {
364 margin-bottom: 0;
365}
366
367.input-group.full-width {
368 grid-column: span 2;
369}
370
371.input-group label {
372 display: block;
373 margin-bottom: 5px;
374 font-weight: 500;
375}
376
377.input-group.checkbox-group {
378 display: flex;
379 align-items: center;
380 padding-top: 24px;
381}
382
383.input-group.checkbox-group label {
384 margin-bottom: 0;
385 display: flex;
386 align-items: center;
387 cursor: pointer;
388}
389
390input[type="text"],
391input[type="number"],
392select {
393 width: 100%;
394 padding: 8px;
395 border: 1px solid #ddd;
396 border-radius: 4px;
397 background-color: white;
398}
399
400input[type="color"] {
401 width: 100%;
402 padding: 2px;
403 border: 1px solid #ddd;
404 border-radius: 4px;
405 height: 40px;
406 background-color: white;
407 cursor: pointer;
408}
409
410input[type="checkbox"] {
411 margin-right: 8px;
412 cursor: pointer;
413}
414
415.barcode-section {
416 position: relative;
417}
418
419.format-hint {
420 margin-top: 4px;
421 font-size: 0.875rem;
422 color: #666;
423}
424
425.format-hint .example {
426 color: #0066cc;
427 margin-top: 2px;
428 font-family: monospace;
429}
430
431.error-message {
432 color: #dc2626;
433 margin-bottom: 15px;
434 padding: 8px;
435 border: 1px solid #dc2626;
436 border-radius: 4px;
437 background-color: #fef2f2;
438}
439
440.barcode-container {
441 display: flex;
442 justify-content: center;
443 align-items: center;
444 min-height: 256px;
445 padding: 20px;
446 border: 1px solid #ddd;
447 border-radius: 4px;
448}
449</style>
docs/.vitepress/theme/components/Home.vuedeleted+0-9
Changes to docs/.vitepress/theme/components/Home.vue
@@ -1,9 +0,0 @@
1<template>
2 <div class="flex flex-col items-center mt-4 home">
3 <HomeTeam />
4
5 <HomeSponsors />
6
7 <HomeContributors />
8 </div>
9</template>
docs/.vitepress/theme/components/HomeContributors.vuedeleted+0-20
Changes to docs/.vitepress/theme/components/HomeContributors.vue
@@ -1,20 +0,0 @@
1<script setup lang="ts">
2import { contributors } from './contributors'
3</script>
4
5<template>
6 <div class="vp-doc">
7 <h2 pb-2 pt-5 font-normal op50>
8 Contributors
9 </h2>
10 </div>
11
12 <div max-w-200 p-10 text-center text-lg leading-7>
13 <div flex="~ wrap gap-1" justify-center>
14 <a v-for="{ name, avatar } of contributors" :key="name" :href="`https://github.com/${name}`" m-0 rel="noopener noreferrer" :aria-label="`${name} on GitHub`">
15 <img loading="lazy" :src="avatar" width="40" height="40" h-10 min-h-10 min-w-10 w-10 rounded-full :alt="`${name}'s avatar`">
16 </a>
17 </div>
18 <br>
19 </div>
20</template>
docs/.vitepress/theme/components/HomeSponsors.vuedeleted+0-19
Changes to docs/.vitepress/theme/components/HomeSponsors.vue
@@ -1,19 +0,0 @@
1<template>
2 <div class="vp-doc">
3 <h2 pb-2 pt-5 font-normal op50>
4 Stacks Sponsors
5 </h2>
6 </div>
7
8 <p id="sponsor" class="mt-5 text-center">
9 <a href="https://github.com/sponsors/chrisbbreuer">
10 <img src="https://cdn.jsdelivr.net/gh/stacksjs/sponsors/sponsorkit/sponsors.svg" class="m-auto">
11 </a>
12 </p>
13
14 <p class="mt-5 text-center">
15 <a href="https://github.com/sponsors/chrisbbreuer" class="text-xs italic">
16 Click here to become a sponsor.
17 </a>
18 </p>
19</template>
docs/.vitepress/theme/components/HomeTeam.vuedeleted+0-20
Changes to docs/.vitepress/theme/components/HomeTeam.vue
@@ -1,20 +0,0 @@
1<script setup lang="ts">
2import { coreTeamMembers } from './contributors'
3</script>
4
5<template>
6 <div class="vp-doc">
7 <h2 pb-2 pt-5 font-normal op50>
8 Meet The Team
9 </h2>
10 </div>
11
12 <div grid="~ cols-2 lg:cols-4 gap-x-3 gap-y-20 items-stretch" p-10>
13 <TeamMember
14 v-for="c of coreTeamMembers"
15 :key="c.github"
16 :data="c"
17 class="flex flex-col items-center text-center p-4 h-full"
18 />
19 </div>
20</template>
docs/.vitepress/theme/components/QRCodeDemo.vuedeleted+0-117
Changes to docs/.vitepress/theme/components/QRCodeDemo.vue
@@ -1,117 +0,0 @@
1<script setup>
2import { QRCode, QRErrorCorrectLevel } from "ts-qr-codes";
3import { onMounted, ref, watch } from "vue";
4
5const text = ref("Hello World!");
6const errorLevel = ref(QRErrorCorrectLevel.H);
7const useSVG = ref(true);
8const qrContainer = ref(null);
9let qrCode = null;
10
11function updateQRCode() {
12 if (!qrContainer.value) return;
13
14 if (qrCode) {
15 qrCode.clear();
16 }
17
18 qrCode = new QRCode(qrContainer.value, {
19 text: text.value,
20 width: 256,
21 height: 256,
22 colorDark: "#000000",
23 colorLight: "#ffffff",
24 correctLevel: Number.parseInt(errorLevel.value),
25 useSVG: useSVG.value,
26 });
27}
28
29onMounted(() => {
30 updateQRCode();
31});
32
33watch([text, errorLevel, useSVG], () => {
34 updateQRCode();
35});
36</script>
37
38<template>
39 <div class="qr-demo">
40 <div class="controls">
41 <div class="input-group">
42 <label for="qr-text">Text to encode:</label>
43 <input
44 id="qr-text"
45 v-model="text"
46 type="text"
47 placeholder="Enter text to encode"
48 />
49 </div>
50
51 <div class="input-group">
52 <label for="error-level">Error Correction:</label>
53 <select id="error-level" v-model="errorLevel">
54 <option value="1">Level L (7%)</option>
55 <option value="0">Level M (15%)</option>
56 <option value="3">Level Q (25%)</option>
57 <option value="2">Level H (30%)</option>
58 </select>
59 </div>
60
61 <div class="input-group">
62 <label>
63 <input v-model="useSVG" type="checkbox" />
64 Use SVG Renderer
65 </label>
66 </div>
67 </div>
68
69 <div ref="qrContainer" class="qr-container" />
70 </div>
71</template>
72
73<style scoped>
74.qr-demo {
75 padding: 20px;
76 max-width: 600px;
77 margin: 0 auto;
78}
79
80.controls {
81 margin-bottom: 20px;
82}
83
84.input-group {
85 margin-bottom: 15px;
86}
87
88.input-group label {
89 display: block;
90 margin-bottom: 5px;
91 font-weight: 500;
92}
93
94input[type="text"] {
95 width: 100%;
96 padding: 8px;
97 border: 1px solid #ddd;
98 border-radius: 4px;
99}
100
101select {
102 padding: 8px;
103 border: 1px solid #ddd;
104 border-radius: 4px;
105 background-color: white;
106}
107
108.qr-container {
109 display: flex;
110 justify-content: center;
111 align-items: center;
112 min-height: 256px;
113 padding: 20px;
114 border: 1px solid #ddd;
115 border-radius: 4px;
116}
117</style>
docs/.vitepress/theme/components/TeamMember.vuedeleted+0-42
Changes to docs/.vitepress/theme/components/TeamMember.vue
@@ -1,42 +0,0 @@
1<script setup lang="ts">
2import type { CoreTeam } from './contributors'
3
4defineProps<{
5 data: CoreTeam
6}>()
7</script>
8
9<template>
10 <div text-center>
11 <img
12 loading="lazy"
13 width="100" height="100" m-auto h-25 min-h-25 min-w-25 w-25 rounded-full
14 :src="data.avatar"
15 :alt="`${data.name}'s avatar`"
16 >
17 <div mb-1 mt-2 text-xl>
18 {{ data.name }}
19 </div>
20 <div h-80px op60 v-html="data.description" />
21
22 <div flex="~ inline gap-2" py2 text-2xl>
23 <a
24 class="i-carbon-logo-github mya inline-block text-current op30 transition duration-200 hover:op100"
25 :href="`https://github.com/${data.github}`"
26 target="_blank"
27 rel="noopener noreferrer"
28 :aria-label="`${data.name} on GitHub`"
29 />
30
31 <a
32 v-if="data.sponsors"
33 class="i-carbon-favorite-filled mya inline-block text-current op30 transition duration-200 hover:op100"
34 :href="`https://github.com/sponsors/${data.github}`"
35 target="_blank"
36 rel="noopener noreferrer"
37 :title="`Sponsor ${data.name}`"
38 :aria-label="`Sponsor ${data.name}`"
39 />
40 </div>
41 </div>
42</template>
docs/.vitepress/theme/components/contributors.jsondeleted+0-6
Changes to docs/.vitepress/theme/components/contributors.json
@@ -1,6 +0,0 @@
1{
2 "chrisbbreuer": true,
3 "glennmichael123": false,
4 "cab-mikee": true,
5 "konkonam": false
6}
docs/.vitepress/theme/components/contributors.tsdeleted+0-85
Changes to docs/.vitepress/theme/components/contributors.ts
@@ -1,85 +0,0 @@
1import contributors from './contributors.json'
2
3export interface Contributor {
4 name: string
5 avatar: string
6}
7
8export interface CoreTeam {
9 avatar: string
10 name: string
11 github: string
12 twitter?: string
13 bluesky?: string
14 sponsors?: boolean
15 description: string
16 packages?: string[]
17 functions?: string[]
18}
19
20const contributorsAvatars: Record<string, string> = {}
21
22function getAvatarUrl(name: string) {
23 return `https://avatars.githubusercontent.com/${name}?v=4`
24}
25
26const contributorList = (Object.keys(contributors) as string[]).reduce((acc, name) => {
27 contributorsAvatars[name] = getAvatarUrl(name)
28
29 if (contributors[name]) {
30 acc.push({ name, avatar: contributorsAvatars[name] })
31 }
32
33 return acc
34}, [] as Contributor[])
35
36const coreTeamMembers: CoreTeam[] = [
37 {
38 avatar: contributorsAvatars.chrisbbreuer || 'default-avatar.png',
39 name: 'Chris Breuer',
40 github: 'chrisbbreuer',
41 twitter: 'chrisbbreuer',
42 bluesky: 'chrisbreuer.dev',
43 sponsors: true,
44 description: 'Open sourceror.<br>Core Stacks team.<br>Working at Stacks.js',
45 packages: ['core'],
46 functions: ['cloud', 'backend', 'frontend', 'ci/cd'],
47 },
48 {
49 avatar: contributorsAvatars.glennmichael123 || 'default-avatar.png',
50 name: 'Glenn',
51 github: 'glennmichael123',
52 twitter: 'glennmichael123',
53 sponsors: false,
54 packages: ['core'],
55 functions: ['backend', 'frontend', 'desktop'],
56 description: 'Open sourceror.<br>Core Stacks team.<br>Working at Stacks.js',
57 },
58
59 {
60 avatar: contributorsAvatars['cab-mikee'] || 'default-avatar.png',
61 name: 'Mike',
62 github: 'cab-mikee',
63 twitter: 'cab-mikee',
64 sponsors: false,
65 description: 'Open sourceror.<br>Core Stacks team.<br>Working at Stacks.js',
66 packages: ['core'],
67 functions: ['backend', 'frontend'],
68 },
69
70 {
71 avatar: contributorsAvatars.konkonam || 'default-avatar.png',
72 name: 'Zoltan',
73 github: 'konkonam',
74 sponsors: true,
75 description: 'Open sourceror.<br>Core Stacks team.',
76 packages: ['core'],
77 functions: ['backend', 'frontend', 'desktop'],
78 },
79]
80 .sort((pre, cur) => {
81 const contribute = Object.keys(contributors)
82 return contribute.findIndex(name => name === pre.github) - contribute.findIndex(name => name === cur.github)
83 })
84
85export { contributorList as contributors, coreTeamMembers }
docs/.vitepress/theme/index.tsdeleted+0-24
Changes to docs/.vitepress/theme/index.ts
@@ -1,24 +0,0 @@
1import type { Theme } from 'vitepress'
2import TwoSlashFloatingVue from '@shikijs/vitepress-twoslash/client'
3import DefaultTheme from 'vitepress/theme'
4import { h } from 'vue'
5
6import 'uno.css'
7
8import './styles/main.css'
9import './styles/vars.css'
10import './styles/overrides.css'
11
12export default {
13 ...DefaultTheme,
14
15 enhanceApp(ctx: any) {
16 ctx.app.use(TwoSlashFloatingVue)
17 },
18
19 Layout: () => {
20 return h(DefaultTheme.Layout, null, {
21 // https://vitepress.dev/guide/extending-default-theme#layout-slots
22 })
23 },
24} satisfies Theme
docs/.vitepress/theme/styles/main.cssdeleted+0-31
Changes to docs/.vitepress/theme/styles/main.css
@@ -1,31 +0,0 @@
1html.dark {
2 color-scheme: dark;
3}
4
5.vp-doc h2 {
6 border-top: 0;
7 margin-top: 10px;
8}
9
10.VPMenuLink .link {
11 line-height: 28px !important;
12}
13
14.VPSidebarGroup .link {
15 padding: 3px 0 !important;
16}
17
18.vp-doc a:has(> code) {
19 text-decoration: none;
20 color: var(--vp-c-brand-1);
21}
22
23.vp-doc a:has(> code):hover {
24 text-decoration: underline;
25}
26
27#app a:focus-visible,
28#app button:focus-visible,
29#app input[type='checkbox']:focus-visible {
30 --at-apply: outline-1 outline-primary ring-2 ring-primary;
31}
docs/.vitepress/theme/styles/overrides.cssdeleted+0-8
Changes to docs/.vitepress/theme/styles/overrides.css
@@ -1,8 +0,0 @@
1.custom-block-title {
2 opacity: 0.5;
3 font-size: 12px;
4 margin-top: -5px !important;
5 margin-bottom: -10px !important;
6 filter: saturate(0.6);
7 letter-spacing: 0.5px;
8}
docs/.vitepress/theme/styles/vars.cssdeleted+0-104
Changes to docs/.vitepress/theme/styles/vars.css
@@ -1,104 +0,0 @@
1/**
2 * Colors
3 * -------------------------------------------------------------------------- */
4
5:root {
6 --vp-c-brand-1: #2563eb;
7 --vp-c-brand-2: #1e40af;
8 --vp-c-brand-3: #172554;
9 --vp-c-brand-soft: #2563eb50;
10
11 --vp-c-text-dark-1: #ffffff; /* Adding this to ensure light text */
12
13 --vp-c-text-code: #4a72bf;
14
15 --vp-code-block-bg: rgba(125, 125, 125, 0.04);
16 --vp-code-copy-code-bg: rgba(125, 125, 125, 0.1);
17 --vp-code-copy-code-hover-bg: rgba(125, 125, 125, 0.2);
18
19 --vp-c-disabled-bg: rgba(125, 125, 125, 0.2);
20 --vp-c-text-light-2: rgba(56 56 56 / 70%);
21 --vp-c-text-dark-2: rgba(56 56 56 / 70%);
22
23 --vp-custom-block-info-bg: transparent;
24 --vp-custom-block-tip-bg: transparent;
25
26 --vp-custom-block-warning-bg: #d9a40605;
27 --vp-custom-block-warning-text: #d9a406;
28 --vp-custom-block-warning-border: #d9a40630;
29
30 --vp-custom-block-tip-bg: #2563eb05;
31 --vp-custom-block-tip-text: #2563eb;
32 --vp-custom-block-tip-border: #2563eb30;
33
34 --vp-code-color: #4a72bf;
35}
36
37.dark {
38 --vp-code-block-bg: var(--vp-c-bg-alt);
39 --vp-c-text-code: #93c5fd;
40 --vp-c-text-dark-2: rgba(235, 235, 235, 0.6);
41}
42
43/**
44 * Component: Code
45 * -------------------------------------------------------------------------- */
46
47:root {
48 --vp-code-line-highlight-color: rgba(125, 125, 125, 0.2);
49}
50
51.dark {
52 --vp-code-line-highlight-color: rgba(0, 0, 0, 0.5);
53}
54
55/**
56 * Component: Button
57 * -------------------------------------------------------------------------- */
58
59 :root {
60 --vp-button-brand-border: var(--vp-c-brand-1);
61 --vp-button-brand-text: var(--vp-c-text-dark-1);
62 --vp-button-brand-bg: var(--vp-c-brand-1);
63 --vp-button-brand-hover-border: var(--vp-c-brand-2);
64 --vp-button-brand-hover-text: var(--vp-c-text-dark-1);
65 --vp-button-brand-hover-bg: var(--vp-c-brand-2);
66 --vp-button-brand-active-border: var(--vp-c-brand-2);
67 --vp-button-brand-active-text: var(--vp-c-text-dark-1);
68 --vp-button-brand-active-bg: var(--vp-c-brand-2);
69 }
70
71/**
72 * Component: Home
73 * -------------------------------------------------------------------------- */
74
75:root {
76 --vp-home-hero-name-color: transparent;
77 --vp-home-hero-name-background: -webkit-linear-gradient(
78 120deg,
79 #1e40af,
80 #2563eb
81 );
82 --vp-home-hero-image-background-image: linear-gradient(-45deg, #1e40af 50%, #2563eb 50%);
83 --vp-home-hero-image-filter: blur(30px);
84}
85
86@media (min-width: 640px) {
87 :root {
88 --vp-home-hero-image-filter: blur(56px);
89 }
90}
91
92@media (min-width: 960px) {
93 :root {
94 --vp-home-hero-image-filter: blur(60px);
95 }
96}
97
98/**
99 * Component: Algolia
100 * -------------------------------------------------------------------------- */
101
102/* .DocSearch {
103 --docsearch-primary-color: var(--vp-c-brand) !important;
104} */
docs/.vitepress/unocss.config.tsdeleted+0-40
Changes to docs/.vitepress/unocss.config.ts
@@ -1,40 +0,0 @@
1import {
2 defineConfig,
3 presetAttributify,
4 presetIcons,
5 presetUno,
6 transformerDirectives,
7 transformerVariantGroup,
8} from 'unocss'
9
10export default defineConfig({
11 shortcuts: {
12 'border-main': 'border-$vp-c-divider',
13 'bg-main': 'bg-gray-400',
14 'bg-base': 'bg-white dark:bg-hex-1a1a1a',
15 },
16
17 presets: [
18 presetUno(),
19 presetAttributify(),
20 presetIcons({
21 scale: 1.2,
22 warn: true,
23 }),
24 ],
25
26 theme: {
27 colors: {
28 primary: '#3eaf7c',
29 },
30
31 fontFamily: {
32 mono: 'var(--vp-font-family-mono)',
33 },
34 },
35
36 transformers: [
37 transformerDirectives(),
38 transformerVariantGroup(),
39 ],
40})
docs/.vitepress/vite.config.tsdeleted+0-60
Changes to docs/.vitepress/vite.config.ts
@@ -1,60 +0,0 @@
1import { resolve } from "node:path";
2// import Inspect from 'vite-plugin-inspect'
3import UnoCSS from "unocss/vite";
4import IconsResolver from "unplugin-icons/resolver";
5import Icons from "unplugin-icons/vite";
6import Components from "unplugin-vue-components/vite";
7import { defineConfig } from "vite";
8
9export default defineConfig({
10 build: {
11 assetsDir: "assets",
12 rollupOptions: {
13 output: {
14 assetFileNames: "assets/[name].[hash][extname]",
15 },
16 },
17 },
18
19 resolve: {
20 alias: {
21 "ts-qr-codes": resolve(__dirname, "../../packages/qrx/src/index.ts"),
22 },
23 dedupe: ["vue", "@vue/runtime-core"],
24 },
25
26 plugins: [
27 // custom
28 // MarkdownTransform(),
29 // Contributors(contributions),
30
31 // plugins
32 Components({
33 dirs: resolve(__dirname, "theme/components"),
34 include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
35 resolvers: [
36 IconsResolver({
37 componentPrefix: "",
38 }),
39 ],
40 dts: resolve(__dirname, "components.d.ts"),
41 transformer: "vue3",
42 }),
43
44 Icons({
45 compiler: "vue3",
46 defaultStyle: "display: inline-block",
47 }),
48
49 UnoCSS(resolve(__dirname, "unocss.config.ts")),
50
51 // Inspect(),
52 ],
53
54 optimizeDeps: {
55 exclude: [
56 // 'vue',
57 "body-scroll-lock",
58 ],
59 },
60});