feat: V1 prototype — Vite/React/TS tileset generator

- Scaffold: package.json, tsconfig.json, vite.config.ts, index.html
- src/lib/imageProcessor.ts: full pipeline (normalize, offset, seam repair, export, validation)
- src/components/UploadPanel.tsx: drag-and-drop, file picker, clipboard paste
- src/components/SettingsPanel.tsx: all controls per spec
- src/components/PreviewPanel.tsx: Original / Tileable / Repeated tabs
- src/components/ErrorBanner.tsx: dismissible error/warning banners
- src/App.tsx: root component wiring everything together
- src/index.css: dark premium glassmorphism theme w/ Inter font
This commit is contained in:
Ben
2026-05-15 01:18:26 -07:00
parent 68d1ee21b4
commit 31d0464a60
2439 changed files with 933708 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return async (size = defaultSize) => {
let id = ''
while (true) {
let bytes = crypto.getRandomValues(new Uint8Array(step))
let i = step | 0
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let nanoid = async (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
let byte = bytes[size] & 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte < 63) {
id += '_'
} else {
id += '-'
}
}
return id
}
export { nanoid, customAlphabet, random }