1 Commits
Author SHA1 Message Date
libretechandClaude Opus 4.7 c147843cb5 Add Svelte + Vite port of the logo generator
Svelte 5 (runes) single-component port over the shared src/logo.js
core. $state holds the model, $derived produces the generated CSS and
the logo's style string, $effect syncs the body background. bind:value
drives the controls (range/number inputs coerce to numbers). Keeps the
accessibility markup (labels, aria, <details>/<summary>, focus rings);
reset restores defaults via the form's onreset handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:25:17 +02:00
7 changed files with 443 additions and 328 deletions
+290 -192
View File
@@ -1,67 +1,19 @@
{ {
"name": "demo-ecmascript-vue", "name": "demo-ecmascript-svelte",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "demo-ecmascript-vue", "name": "demo-ecmascript-svelte",
"version": "1.0.0", "version": "1.0.0",
"license": "WTFPL", "license": "WTFPL",
"dependencies": {
"vue": "^3.5.13"
},
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.2.1", "@sveltejs/vite-plugin-svelte": "^5.0.3",
"svelte": "^5.16.0",
"vite": "^6.0.0" "vite": "^6.0.0"
} }
}, },
"node_modules/@babel/helper-string-parser": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
"integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
"integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.7"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/types": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
"integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.29.7",
"@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.12", "version": "0.25.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
@@ -504,12 +456,56 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/remapping": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.60.4", "version": "4.60.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz",
@@ -899,144 +895,147 @@
"win32" "win32"
] ]
}, },
"node_modules/@sveltejs/acorn-typescript": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz",
"integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
}
},
"node_modules/@sveltejs/vite-plugin-svelte": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.1.tgz",
"integrity": "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
"debug": "^4.4.1",
"deepmerge": "^4.3.1",
"kleur": "^4.1.5",
"magic-string": "^0.30.17",
"vitefu": "^1.0.6"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22"
},
"peerDependencies": {
"svelte": "^5.0.0",
"vite": "^6.0.0"
}
},
"node_modules/@sveltejs/vite-plugin-svelte-inspector": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz",
"integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.7"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22"
},
"peerDependencies": {
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"svelte": "^5.0.0",
"vite": "^6.0.0"
}
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.8", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vitejs/plugin-vue": { "node_modules/@types/trusted-types": {
"version": "5.2.4", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"dev": true,
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/aria-query": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.0.0 || >=20.0.0" "node": ">=6"
},
"peerDependencies": {
"vite": "^5.0.0 || ^6.0.0",
"vue": "^3.2.25"
} }
}, },
"node_modules/@vue/compiler-core": { "node_modules/debug": {
"version": "3.5.35", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.35.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.29.3", "ms": "^2.1.3"
"@vue/shared": "3.5.35",
"entities": "^7.0.1",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
}, },
"node_modules/@vue/compiler-dom": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.35.tgz",
"integrity": "sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.35.tgz",
"integrity": "sha512-G5VPMcXTSywXBgtFOZOnHKBxKSrwXUcvY1iaF5/hRcy7t0J6CH/d8ha9F4nzi00Fax1eLV0QHM7v4mQu68jydw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.3",
"@vue/compiler-core": "3.5.35",
"@vue/compiler-dom": "3.5.35",
"@vue/compiler-ssr": "3.5.35",
"@vue/shared": "3.5.35",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.21",
"postcss": "^8.5.15",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.35.tgz",
"integrity": "sha512-rGhAeXgdM7/ffTJGXT69rCCdTmjDewnFuUZfBQQHTdcEBeWdT5HCGY60y2ytLJr9/Dsu7IntUi5z/w0h6Rjnzw==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.35.tgz",
"integrity": "sha512-tVc+SsHConvh/Lz64qq1pP3rYArBmK42xonovEcxY74SQtvctZodG/zhq54P5dr38cVuw25d27cPNRdlMidpGQ==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.35.tgz",
"integrity": "sha512-A/xFNX9loIcWDygeQuNCfKuh0CoYBzxhqEMNah5TSFg9Z53DrFYEN2qi5CU9necjM1OWYegYREUTHmXTmhfXtg==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.35.tgz",
"integrity": "sha512-odrJ1C391dbGnyDRh8U+rnP7J2amIEzfmRk5vXy7xi3aZhEXofTvpi0T4HJb6jlNqQZTNPR5MPHSB3RHNkIORA==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.35",
"@vue/runtime-core": "3.5.35",
"@vue/shared": "3.5.35",
"csstype": "^3.2.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.35.tgz",
"integrity": "sha512-NkebSOYdB97wi8OQcO3HqzZSlymJi/aWsN/7h74OSVhRTm6qGs3Jp3e0rCXynmWwSlKeRrnlIug+ilYoHBmQDA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.35",
"@vue/shared": "3.5.35"
},
"peerDependencies": {
"vue": "3.5.35"
}
},
"node_modules/@vue/shared": {
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.35.tgz",
"integrity": "sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT"
},
"node_modules/entities": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=0.12" "node": ">=6.0"
}, },
"funding": { "peerDependenciesMeta": {
"url": "https://github.com/fb55/entities?sponsor=1" "supports-color": {
"optional": true
} }
}
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/devalue": {
"version": "5.8.1",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz",
"integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==",
"dev": true,
"license": "MIT"
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.25.12", "version": "0.25.12",
@@ -1080,12 +1079,31 @@
"@esbuild/win32-x64": "0.25.12" "@esbuild/win32-x64": "0.25.12"
} }
}, },
"node_modules/estree-walker": { "node_modules/esm-env": {
"version": "2.0.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/esrap": {
"version": "2.2.9",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.9.tgz",
"integrity": "sha512-4KijP+NxCWthMCUC3qHbE6n4vCjqgJS1uAYKhuT/GWfFTf1Qyive2TgOjep+gzbSzRfnNyaN/UU9YmdOt8Eg0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"peerDependencies": {
"@typescript-eslint/types": "^8.2.0"
},
"peerDependenciesMeta": {
"@typescript-eslint/types": {
"optional": true
}
}
},
"node_modules/fdir": { "node_modules/fdir": {
"version": "6.5.0", "version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -1119,19 +1137,55 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0" "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
} }
}, },
"node_modules/is-reference": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
}
},
"node_modules/kleur": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true,
"license": "MIT"
},
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.21", "version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5" "@jridgewell/sourcemap-codec": "^1.5.5"
} }
}, },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.12", "version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -1150,6 +1204,7 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
@@ -1169,6 +1224,7 @@
"version": "8.5.15", "version": "8.5.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -1238,15 +1294,51 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/rollup/node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true,
"license": "MIT"
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/svelte": {
"version": "5.55.10",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.10.tgz",
"integrity": "sha512-v9mFVBY1USosyIWdXE7Cg4AN0ywyKCMcAhONvli8doMowEhFhMdNLKD1j7O/UnsrdVTHaUOk/jv8hD/HClVy+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.10",
"@types/estree": "^1.0.5",
"@types/trusted-types": "^2.0.7",
"acorn": "^8.12.1",
"aria-query": "5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
"devalue": "^5.8.1",
"esm-env": "^1.2.1",
"esrap": "^2.2.9",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",
"zimmerframe": "^1.1.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.16", "version": "0.2.16",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
@@ -1339,26 +1431,32 @@
} }
} }
}, },
"node_modules/vue": { "node_modules/vitefu": {
"version": "3.5.35", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.35.tgz", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",
"integrity": "sha512-cx89fnr+0kVGHiNFG6y6s0bdjypJRFNZn6x3WPstNdQR1bi1mbB7h4v5IBGTsPJU3nK1+0Iqj3Zf+hZWMieR4Q==", "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "workspaces": [
"@vue/compiler-dom": "3.5.35", "tests/deps/*",
"@vue/compiler-sfc": "3.5.35", "tests/projects/*",
"@vue/runtime-dom": "3.5.35", "tests/projects/workspace/packages/*"
"@vue/server-renderer": "3.5.35", ],
"@vue/shared": "3.5.35"
},
"peerDependencies": { "peerDependencies": {
"typescript": "*" "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"typescript": { "vite": {
"optional": true "optional": true
} }
} }
},
"node_modules/zimmerframe": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
"dev": true,
"license": "MIT"
} }
} }
} }
+4 -6
View File
@@ -1,7 +1,7 @@
{ {
"name": "demo-ecmascript-vue", "name": "demo-ecmascript-svelte",
"version": "1.0.0", "version": "1.0.0",
"description": "LIBRETECH logo generator — Vue + Vite", "description": "LIBRETECH logo generator — Svelte + Vite",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "ssh://tengo@git.librete.ch:41240/public/demo-ecmascript.git" "url": "ssh://tengo@git.librete.ch:41240/public/demo-ecmascript.git"
@@ -13,11 +13,9 @@
"build": "vite build", "build": "vite build",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": {
"vue": "^3.5.13"
},
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.2.1", "@sveltejs/vite-plugin-svelte": "^5.0.3",
"svelte": "^5.16.0",
"vite": "^6.0.0" "vite": "^6.0.0"
} }
} }
+133
View File
@@ -0,0 +1,133 @@
<script>
import { defaults, fonts, logoStyle, cssOutput } from './logo.js';
const FONT_LABELS = { Impact: 'Impact (System)' };
let s = $state({ ...defaults });
let copied = $state(false);
const css = $derived(cssOutput(s));
const logoCss = $derived(styleString(logoStyle(s)));
$effect(() => {
document.body.style.background = s.bg;
});
// logoStyle() returns a camelCase object; the style attribute needs a string.
function styleString(obj) {
return Object.entries(obj)
.map(([k, v]) => `${k.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase())}:${v}`)
.join(';');
}
async function copy() {
try {
await navigator.clipboard.writeText(css);
copied = true;
setTimeout(() => (copied = false), 1500);
} catch {
alert('Kopieren fehlgeschlagen — bitte manuell aus dem Code-Feld kopieren.');
}
}
function onSubmit(e) {
e.preventDefault();
}
// bind:value owns the values, so restore defaults explicitly on reset.
function onReset(e) {
e.preventDefault();
s = { ...defaults };
}
</script>
<div class="logo" style={logoCss}>{s.text || ' '}</div>
<details class="disclosure" id="panel" open>
<summary class="toggle-panel">Panel ein/aus</summary>
<div class="panel">
<h1>Logo-Generator</h1>
<form id="logoForm" onsubmit={onSubmit} onreset={onReset}>
<h2>Inhalt</h2>
<p class="hint" id="hint-text">Mehrere Zeilen mit Enter trennen.</p>
<textarea id="text" rows="2" aria-label="Logo-Text" aria-describedby="hint-text" bind:value={s.text}></textarea>
<h2>Schrift</h2>
<select id="font" aria-label="Schriftart" bind:value={s.font}>
{#each fonts as f}
<option value={f}>{FONT_LABELS[f] || f}</option>
{/each}
</select>
<div class="row-2col">
<div>
<label for="fs">Größe: <span class="val">{s.fs}</span>vw</label>
<input type="range" id="fs" min="6" max="30" step="0.5" bind:value={s.fs} />
</div>
<div>
<label for="lh">Zeilenabstand: <span class="val">{s.lh.toFixed(2)}</span></label>
<input type="range" id="lh" min="0.5" max="2" step="0.05" bind:value={s.lh} />
</div>
</div>
<label for="ls">Buchstabenabstand: <span class="val">{s.ls.toFixed(3)}</span>em</label>
<input type="range" id="ls" min="-0.15" max="0.3" step="0.005" bind:value={s.ls} />
<h2>Farben</h2>
<div class="color-row">
<input type="color" id="c-bg" bind:value={s.bg} aria-labelledby="lbl-bg" />
<span class="swatch-label" id="lbl-bg">Hintergrund</span>
<span class="hex">{s.bg}</span>
</div>
<div class="color-row">
<input type="color" id="c-face" bind:value={s.face} aria-labelledby="lbl-face" />
<span class="swatch-label" id="lbl-face">Face</span>
<span class="hex">{s.face}</span>
</div>
<div class="color-row">
<input type="color" id="c-depth" bind:value={s.depth} aria-labelledby="lbl-depth" />
<span class="swatch-label" id="lbl-depth">Tiefe</span>
<span class="hex">{s.depth}</span>
</div>
<div class="color-row">
<input type="color" id="c-shadow" bind:value={s.shadow} aria-labelledby="lbl-shadow" />
<span class="swatch-label" id="lbl-shadow">Schatten &amp; Kontur</span>
<span class="hex">{s.shadow}</span>
</div>
<h2>Lichtrichtung</h2>
<p class="hint">Steuert alle Versätze gleichzeitig — Schatten geht in Lichtrichtung, Tiefe entgegen.</p>
<label for="angle">Winkel: <span class="val">{s.angle}</span>° (0=oben, 90=rechts, 180=unten)</label>
<input type="range" id="angle" min="0" max="359" bind:value={s.angle} />
<h2>Schichten</h2>
<p class="hint">Hinten nach vorn: Schatten · Tiefe · Kontur · Face</p>
<label for="shadow-len">Schatten-Länge: <span class="val">{s.shadowLen}</span>px</label>
<input type="range" id="shadow-len" min="0" max="80" bind:value={s.shadowLen} />
<label for="depth-len">Tiefe (in Gegenrichtung): <span class="val">{s.depthLen}</span>px</label>
<input type="range" id="depth-len" min="0" max="30" bind:value={s.depthLen} />
<label for="contour-len">Kontur (vor der Tiefe): <span class="val">{s.contourLen}</span>px</label>
<input type="range" id="contour-len" min="0" max="20" bind:value={s.contourLen} />
<h2>Komposition</h2>
<div class="row-2col">
<div>
<label for="rot">Drehung: <span class="val">{s.rot}</span>°</label>
<input type="range" id="rot" min="-25" max="25" bind:value={s.rot} />
</div>
<div>
<label for="skew">Schräge: <span class="val">{s.skew}</span>°</label>
<input type="range" id="skew" min="-20" max="20" bind:value={s.skew} />
</div>
</div>
<h2>Generiertes CSS</h2>
<code id="cssout">{css}</code>
<button type="button" class="copy-btn" class:copied onclick={copy}>
{copied ? 'Kopiert!' : 'CSS kopieren'}
</button>
<button type="reset" class="reset-btn">Zurücksetzen</button>
</form>
</div>
</details>
-121
View File
@@ -1,121 +0,0 @@
<script setup>
import { reactive, computed, ref, watchEffect } from 'vue';
import { defaults, fonts, logoStyle, cssOutput } from './logo.js';
const FONT_LABELS = { Impact: 'Impact (System)' };
const s = reactive({ ...defaults });
const css = computed(() => cssOutput(s));
const logoCss = computed(() => logoStyle(s));
const copied = ref(false);
watchEffect(() => {
document.body.style.background = s.bg;
});
async function copy() {
try {
await navigator.clipboard.writeText(css.value);
copied.value = true;
setTimeout(() => (copied.value = false), 1500);
} catch {
alert('Kopieren fehlgeschlagen — bitte manuell aus dem Code-Feld kopieren.');
}
}
// v-model bindings own the values, so restore defaults explicitly on reset.
function reset() {
Object.assign(s, defaults);
}
</script>
<template>
<div class="logo" :style="logoCss">{{ s.text || ' ' }}</div>
<details class="disclosure" id="panel" open>
<summary class="toggle-panel">Panel ein/aus</summary>
<div class="panel">
<h1>Logo-Generator</h1>
<form id="logoForm" @submit.prevent @reset.prevent="reset">
<h2>Inhalt</h2>
<p class="hint" id="hint-text">Mehrere Zeilen mit Enter trennen.</p>
<textarea id="text" rows="2" aria-label="Logo-Text" aria-describedby="hint-text" v-model="s.text"></textarea>
<h2>Schrift</h2>
<select id="font" aria-label="Schriftart" v-model="s.font">
<option v-for="f in fonts" :key="f" :value="f">{{ FONT_LABELS[f] || f }}</option>
</select>
<div class="row-2col">
<div>
<label for="fs">Größe: <span class="val">{{ s.fs }}</span>vw</label>
<input type="range" id="fs" min="6" max="30" step="0.5" v-model.number="s.fs" />
</div>
<div>
<label for="lh">Zeilenabstand: <span class="val">{{ s.lh.toFixed(2) }}</span></label>
<input type="range" id="lh" min="0.5" max="2" step="0.05" v-model.number="s.lh" />
</div>
</div>
<label for="ls">Buchstabenabstand: <span class="val">{{ s.ls.toFixed(3) }}</span>em</label>
<input type="range" id="ls" min="-0.15" max="0.3" step="0.005" v-model.number="s.ls" />
<h2>Farben</h2>
<div class="color-row">
<input type="color" id="c-bg" v-model="s.bg" aria-labelledby="lbl-bg" />
<span class="swatch-label" id="lbl-bg">Hintergrund</span>
<span class="hex">{{ s.bg }}</span>
</div>
<div class="color-row">
<input type="color" id="c-face" v-model="s.face" aria-labelledby="lbl-face" />
<span class="swatch-label" id="lbl-face">Face</span>
<span class="hex">{{ s.face }}</span>
</div>
<div class="color-row">
<input type="color" id="c-depth" v-model="s.depth" aria-labelledby="lbl-depth" />
<span class="swatch-label" id="lbl-depth">Tiefe</span>
<span class="hex">{{ s.depth }}</span>
</div>
<div class="color-row">
<input type="color" id="c-shadow" v-model="s.shadow" aria-labelledby="lbl-shadow" />
<span class="swatch-label" id="lbl-shadow">Schatten &amp; Kontur</span>
<span class="hex">{{ s.shadow }}</span>
</div>
<h2>Lichtrichtung</h2>
<p class="hint">Steuert alle Versätze gleichzeitig — Schatten geht in Lichtrichtung, Tiefe entgegen.</p>
<label for="angle">Winkel: <span class="val">{{ s.angle }}</span>° (0=oben, 90=rechts, 180=unten)</label>
<input type="range" id="angle" min="0" max="359" v-model.number="s.angle" />
<h2>Schichten</h2>
<p class="hint">Hinten nach vorn: Schatten · Tiefe · Kontur · Face</p>
<label for="shadow-len">Schatten-Länge: <span class="val">{{ s.shadowLen }}</span>px</label>
<input type="range" id="shadow-len" min="0" max="80" v-model.number="s.shadowLen" />
<label for="depth-len">Tiefe (in Gegenrichtung): <span class="val">{{ s.depthLen }}</span>px</label>
<input type="range" id="depth-len" min="0" max="30" v-model.number="s.depthLen" />
<label for="contour-len">Kontur (vor der Tiefe): <span class="val">{{ s.contourLen }}</span>px</label>
<input type="range" id="contour-len" min="0" max="20" v-model.number="s.contourLen" />
<h2>Komposition</h2>
<div class="row-2col">
<div>
<label for="rot">Drehung: <span class="val">{{ s.rot }}</span>°</label>
<input type="range" id="rot" min="-25" max="25" v-model.number="s.rot" />
</div>
<div>
<label for="skew">Schräge: <span class="val">{{ s.skew }}</span>°</label>
<input type="range" id="skew" min="-20" max="20" v-model.number="s.skew" />
</div>
</div>
<h2>Generiertes CSS</h2>
<code id="cssout">{{ css }}</code>
<button type="button" class="copy-btn" :class="{ copied }" @click="copy">
{{ copied ? 'Kopiert!' : 'CSS kopieren' }}
</button>
<button type="reset" class="reset-btn">Zurücksetzen</button>
</form>
</div>
</details>
</template>
+5 -3
View File
@@ -1,5 +1,7 @@
import { createApp } from 'vue'; import { mount } from 'svelte';
import App from './App.vue'; import App from './App.svelte';
import './style.css'; import './style.css';
createApp(App).mount('#app'); const app = mount(App, { target: document.getElementById('app') });
export default app;
+5
View File
@@ -0,0 +1,5 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
preprocess: vitePreprocess(),
};
+2 -2
View File
@@ -1,6 +1,6 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [svelte()],
}); });