Compare commits
6 Commits
54865e7551
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd4f632c85 | ||
|
|
dbfc23068c | ||
|
|
42d87e5275 | ||
|
|
3a4be8d359 | ||
|
|
048120adae | ||
|
|
8a3165a26d |
479
react-advanced-tag1/package-lock.json
generated
479
react-advanced-tag1/package-lock.json
generated
@@ -9,7 +9,8 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"react-router-dom": "^7.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
@@ -22,7 +23,8 @@
|
|||||||
"globals": "^15.15.0",
|
"globals": "^15.15.0",
|
||||||
"typescript": "~5.7.2",
|
"typescript": "~5.7.2",
|
||||||
"typescript-eslint": "^8.24.1",
|
"typescript-eslint": "^8.24.1",
|
||||||
"vite": "^6.2.0"
|
"vite": "^6.2.0",
|
||||||
|
"vitest": "^3.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@@ -1392,6 +1394,12 @@
|
|||||||
"@babel/types": "^7.20.7"
|
"@babel/types": "^7.20.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/estree/-/estree-1.0.7.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@types/estree/-/estree-1.0.7.tgz",
|
||||||
@@ -1665,6 +1673,119 @@
|
|||||||
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
|
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vitest/expect": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/expect/-/expect-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/spy": "3.1.1",
|
||||||
|
"@vitest/utils": "3.1.1",
|
||||||
|
"chai": "^5.2.0",
|
||||||
|
"tinyrainbow": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/mocker": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/mocker/-/mocker-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/spy": "3.1.1",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"magic-string": "^0.30.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"msw": "^2.4.9",
|
||||||
|
"vite": "^5.0.0 || ^6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"msw": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vite": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/pretty-format": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/pretty-format/-/pretty-format-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tinyrainbow": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/runner": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/runner/-/runner-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/utils": "3.1.1",
|
||||||
|
"pathe": "^2.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/snapshot": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/snapshot/-/snapshot-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/pretty-format": "3.1.1",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"pathe": "^2.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/spy": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/spy/-/spy-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tinyspy": "^3.0.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vitest/utils": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/@vitest/utils/-/utils-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/pretty-format": "3.1.1",
|
||||||
|
"loupe": "^3.1.3",
|
||||||
|
"tinyrainbow": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.1",
|
"version": "8.14.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/acorn/-/acorn-8.14.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/acorn/-/acorn-8.14.1.tgz",
|
||||||
@@ -1728,6 +1849,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/assertion-error": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/assertion-error/-/assertion-error-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -1792,6 +1923,16 @@
|
|||||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cac": {
|
||||||
|
"version": "6.7.14",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cac/-/cac-6.7.14.tgz",
|
||||||
|
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/callsites": {
|
"node_modules/callsites": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/callsites/-/callsites-3.1.0.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/callsites/-/callsites-3.1.0.tgz",
|
||||||
@@ -1823,6 +1964,23 @@
|
|||||||
],
|
],
|
||||||
"license": "CC-BY-4.0"
|
"license": "CC-BY-4.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/chai": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/chai/-/chai-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"assertion-error": "^2.0.1",
|
||||||
|
"check-error": "^2.1.1",
|
||||||
|
"deep-eql": "^5.0.1",
|
||||||
|
"loupe": "^3.1.0",
|
||||||
|
"pathval": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/chalk/-/chalk-4.1.2.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/chalk/-/chalk-4.1.2.tgz",
|
||||||
@@ -1840,6 +1998,16 @@
|
|||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/check-error": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/check-error/-/check-error-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@@ -1874,6 +2042,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cookie/-/cookie-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@@ -1914,6 +2091,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-eql": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/deep-eql/-/deep-eql-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
@@ -1928,6 +2115,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/es-module-lexer": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.25.2",
|
"version": "0.25.2",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/esbuild/-/esbuild-0.25.2.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/esbuild/-/esbuild-0.25.2.tgz",
|
||||||
@@ -2160,6 +2354,16 @@
|
|||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/estree-walker": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esutils": {
|
"node_modules/esutils": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/esutils/-/esutils-2.0.3.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/esutils/-/esutils-2.0.3.tgz",
|
||||||
@@ -2170,6 +2374,16 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expect-type": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/expect-type/-/expect-type-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@@ -2554,6 +2768,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/loupe": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/loupe/-/loupe-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/lru-cache/-/lru-cache-5.1.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||||
@@ -2564,6 +2785,16 @@
|
|||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/magic-string": {
|
||||||
|
"version": "0.30.17",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/magic-string/-/magic-string-0.30.17.tgz",
|
||||||
|
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/merge2/-/merge2-1.4.1.tgz",
|
||||||
@@ -2724,6 +2955,23 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pathe": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/pathe/-/pathe-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/pathval": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/pathval/-/pathval-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
@@ -2845,6 +3093,46 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "7.5.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/react-router/-/react-router-7.5.0.tgz",
|
||||||
|
"integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/cookie": "^0.6.0",
|
||||||
|
"cookie": "^1.0.1",
|
||||||
|
"set-cookie-parser": "^2.6.0",
|
||||||
|
"turbo-stream": "2.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "7.5.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/react-router-dom/-/react-router-dom-7.5.0.tgz",
|
||||||
|
"integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react-router": "7.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/resolve-from": {
|
"node_modules/resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/resolve-from/-/resolve-from-4.0.0.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||||
@@ -2946,6 +3234,12 @@
|
|||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/set-cookie-parser": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@@ -2969,6 +3263,13 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/siginfo": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/siginfo/-/siginfo-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@@ -2979,6 +3280,20 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stackback": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/stackback/-/stackback-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/std-env": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/std-env/-/std-env-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/strip-json-comments": {
|
"node_modules/strip-json-comments": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||||
@@ -3005,6 +3320,50 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tinybench": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/tinybench/-/tinybench-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/tinyexec": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/tinyexec/-/tinyexec-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/tinypool": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/tinypool/-/tinypool-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.0.0 || >=20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tinyrainbow": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tinyspy": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/tinyspy/-/tinyspy-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
@@ -3031,6 +3390,12 @@
|
|||||||
"typescript": ">=4.8.4"
|
"typescript": ">=4.8.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/turbo-stream": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/type-check/-/type-check-0.4.0.tgz",
|
||||||
@@ -3194,6 +3559,99 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite-node": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/vite-node/-/vite-node-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cac": "^6.7.14",
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"es-module-lexer": "^1.6.0",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"vite": "^5.0.0 || ^6.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"vite-node": "vite-node.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vitest": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/vitest/-/vitest-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitest/expect": "3.1.1",
|
||||||
|
"@vitest/mocker": "3.1.1",
|
||||||
|
"@vitest/pretty-format": "^3.1.1",
|
||||||
|
"@vitest/runner": "3.1.1",
|
||||||
|
"@vitest/snapshot": "3.1.1",
|
||||||
|
"@vitest/spy": "3.1.1",
|
||||||
|
"@vitest/utils": "3.1.1",
|
||||||
|
"chai": "^5.2.0",
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"expect-type": "^1.2.0",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"std-env": "^3.8.1",
|
||||||
|
"tinybench": "^2.9.0",
|
||||||
|
"tinyexec": "^0.3.2",
|
||||||
|
"tinypool": "^1.0.2",
|
||||||
|
"tinyrainbow": "^2.0.0",
|
||||||
|
"vite": "^5.0.0 || ^6.0.0",
|
||||||
|
"vite-node": "3.1.1",
|
||||||
|
"why-is-node-running": "^2.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"vitest": "vitest.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/vitest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@edge-runtime/vm": "*",
|
||||||
|
"@types/debug": "^4.1.12",
|
||||||
|
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||||
|
"@vitest/browser": "3.1.1",
|
||||||
|
"@vitest/ui": "3.1.1",
|
||||||
|
"happy-dom": "*",
|
||||||
|
"jsdom": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@edge-runtime/vm": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/debug": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@vitest/browser": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@vitest/ui": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"happy-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"jsdom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/which/-/which-2.0.2.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/which/-/which-2.0.2.tgz",
|
||||||
@@ -3210,6 +3668,23 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/why-is-node-running": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"siginfo": "^2.0.0",
|
||||||
|
"stackback": "0.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"why-is-node-running": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/word-wrap/-/word-wrap-1.2.5.tgz",
|
"resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"react-router-dom": "^7.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
"globals": "^15.15.0",
|
"globals": "^15.15.0",
|
||||||
"typescript": "~5.7.2",
|
"typescript": "~5.7.2",
|
||||||
"typescript-eslint": "^8.24.1",
|
"typescript-eslint": "^8.24.1",
|
||||||
"vite": "^6.2.0"
|
"vite": "^6.2.0",
|
||||||
|
"vitest": "^3.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
height: 6em;
|
height: 6em;
|
||||||
@@ -40,3 +35,8 @@
|
|||||||
.read-the-docs {
|
.read-the-docs {
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
|
import { Route, Routes } from 'react-router-dom'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
// import EffectExercises from './components/exercises/EffectExercises'
|
// import EffectExercises from './components/exercises/EffectExercises'
|
||||||
import UserEffect from './components/exercises/UserEffect'
|
|
||||||
import { UserOverview } from './components/exercises/UserOverview'
|
|
||||||
import Heading from './components/globals/Heading'
|
|
||||||
import MainLayout from './layouts/MainLayout'
|
import MainLayout from './layouts/MainLayout'
|
||||||
|
import HomePage from './routes/HomePage'
|
||||||
|
import UsersPage from './routes/UsersPage'
|
||||||
|
import EffectExercisesPage from './routes/EffectExercisesPage'
|
||||||
|
import FormsPage from './routes/FormsPage'
|
||||||
|
import MemoCallbackPage from './routes/MemoCallbackPage'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
return <MainLayout>
|
return <MainLayout>
|
||||||
<Heading />
|
<Routes>
|
||||||
{/* <EffectExercises /> */}
|
<Route path="/" element={<HomePage />} />
|
||||||
<UserEffect />
|
<Route path="/user" element={<UsersPage />} />
|
||||||
<UserOverview />
|
<Route path="/effect" element={<EffectExercisesPage />} />
|
||||||
|
<Route path="/forms" element={<FormsPage />} />
|
||||||
|
<Route path="/memocallback" element={<MemoCallbackPage />} />
|
||||||
|
</Routes>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ export default function Navigation () {
|
|||||||
return (
|
return (
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li>home</li>
|
<li><a href="/">Home</a></li>
|
||||||
<li>test</li>
|
<li><a href="/user">Users</a></li>
|
||||||
|
<li><a href="/effect">Effects</a></li>
|
||||||
|
<li><a href="/forms">Forms</a></li>
|
||||||
|
<li><a href="/memocallback">Memo und Callback</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>);
|
</nav>);
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ const Header = () => {
|
|||||||
console.log("Header rendered");
|
console.log("Header rendered");
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<h2>My Application</h2>
|
<h1>My Application</h1>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import React, { memo } from "react";
|
||||||
|
|
||||||
|
interface SearchProps {
|
||||||
|
onChange: (text: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Search({ onChange }: SearchProps): React.ReactElement {
|
||||||
|
console.log("Search rendered");
|
||||||
|
return <input type="text" onChange={(e) => onChange(e.target.value)} placeholder="Search user..." />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Search);
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { shuffleArray, users } from "../../../utils/shuffle";
|
||||||
|
import Search from "./Search";
|
||||||
|
|
||||||
|
export default function MemoCallback() {
|
||||||
|
console.log("MemoCallback rendered");
|
||||||
|
|
||||||
|
const [allUsers, setAllUsers] = useState(users);
|
||||||
|
|
||||||
|
const handleSearch = useCallback((text: string) => {
|
||||||
|
const filteredUsers = users.filter((user) => {
|
||||||
|
return user.toLowerCase().includes(text.toLowerCase());
|
||||||
|
});
|
||||||
|
setAllUsers(filteredUsers);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleShuffle = () => {
|
||||||
|
setAllUsers(shuffleArray(users));
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListOfUsers = allUsers.map((user) => {
|
||||||
|
return <p key={user}>{user}</p>;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button onClick={handleShuffle}>Shuffle</button>
|
||||||
|
<Search onChange={handleSearch} />
|
||||||
|
<div>
|
||||||
|
{ListOfUsers}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { FormEvent, useRef, useState } from "react";
|
||||||
|
import useLocalStorage from "../../../hooks/useLocalStorage";
|
||||||
|
|
||||||
|
interface FormValues {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RefExercise(): React.ReactElement {
|
||||||
|
console.log("RefExercise rendered");
|
||||||
|
|
||||||
|
const emailRef = useRef<HTMLInputElement>(null);
|
||||||
|
const passwordRef = useRef<HTMLInputElement>(null);
|
||||||
|
const {setStoredValue, value: formDataValues} = useLocalStorage<FormValues>("formdata", {
|
||||||
|
email: "",
|
||||||
|
password: ""
|
||||||
|
} );
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
console.log("submit", {
|
||||||
|
email: emailRef.current?.value,
|
||||||
|
password: passwordRef.current?.value
|
||||||
|
});
|
||||||
|
setStoredValue({
|
||||||
|
email: emailRef.current?.value || "",
|
||||||
|
password: passwordRef.current?.value || ""
|
||||||
|
});
|
||||||
|
passwordRef.current?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
strasse: "",
|
||||||
|
city: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[event.target.name]: event.target.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeSubmit = () => {
|
||||||
|
const strasse = document.querySelector('input[name="strasse"]') as HTMLInputElement;
|
||||||
|
const city = document.querySelector('input[name="city"]') as HTMLInputElement;
|
||||||
|
console.log("submit", {
|
||||||
|
strasse: strasse.value,
|
||||||
|
city: city.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFormSubmit(e: FormEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
const data = new FormData(e.target as HTMLFormElement);
|
||||||
|
console.log('handleFormSubmit', {
|
||||||
|
email: data.get('email'),
|
||||||
|
password: data.get('password')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "3rem" }}>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||||||
|
<h3>values by ref</h3>
|
||||||
|
<input type="text" placeholder="email" ref={emailRef} defaultValue={formDataValues?.email}/>
|
||||||
|
<input type="text" placeholder="password" ref={passwordRef} defaultValue={formDataValues?.password}/>
|
||||||
|
<button onClick={handleSubmit}>Submit</button>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||||||
|
<h3>change event (bad way, but validation is possible)</h3>
|
||||||
|
<input type="text" name="strasse" placeholder="Strasse" onChange={handleChange} />
|
||||||
|
<input type="text" name="city" placeholder="Stadt" onChange={handleChange}/>
|
||||||
|
<button onClick={handleChangeSubmit}>submit</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<form onSubmit={handleFormSubmit} style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||||||
|
<h3>By Form Event</h3>
|
||||||
|
<input type="text" name="email" placeholder="Email" />
|
||||||
|
<input type="text" name="password" placeholder="password" />
|
||||||
|
<button type="submit">Send</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ export default function UserEffect() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const start = performance.now(); // Start measuring performance
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// Using AbortController to cancel the fetch request if the component unmounts
|
// Using AbortController to cancel the fetch request if the component unmounts
|
||||||
@@ -33,6 +35,9 @@ export default function UserEffect() {
|
|||||||
return response.json();
|
return response.json();
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
setUser(data);
|
setUser(data);
|
||||||
|
const end = performance.now(); // End measuring performance
|
||||||
|
const timeTaken = end - start; // Calculate the time taken
|
||||||
|
console.log(`Fetch completed in ${Math.round(timeTaken)} milliseconds`);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error("There was a problem with the fetch operation:", error);
|
console.error("There was a problem with the fetch operation:", error);
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import { useFetch } from "../../hooks/useFetch";
|
import { useFetch } from "../../hooks/useFetch";
|
||||||
|
import { useMediaQuery } from "../../hooks/useMediaQuery";
|
||||||
|
|
||||||
export function UserOverview() {
|
export function UserOverview() {
|
||||||
const {data, loading, error} = useFetch("https://jsonplaceholder.typicode.com/users");
|
const {data, loading, error} = useFetch("https://jsonplaceholder.typicode.com/users");
|
||||||
|
|
||||||
|
const isMobile = useMediaQuery('(max-width: 600px)');
|
||||||
|
|
||||||
|
console.log("isMobile", isMobile);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <p>Error: {error}</p>;
|
return <p>Error: {error}</p>;
|
||||||
}
|
}
|
||||||
@@ -18,7 +23,7 @@ export function UserOverview() {
|
|||||||
<ul>
|
<ul>
|
||||||
{data.map((user: { id: number; name: string; email: string; website: string }) => (
|
{data.map((user: { id: number; name: string; email: string; website: string }) => (
|
||||||
<li key={user.id}>
|
<li key={user.id}>
|
||||||
<strong>{user.name}</strong> ({user.email}) - {user.website}
|
<strong>{user.name}</strong> <div style={{display: isMobile ? 'none' : 'block' }}>({user.email}) - {user.website}</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export default function Heading({title = "Hallo Teilnehmer"}: {title?: string}): React.ReactElement {
|
export default function Heading({title = "Hallo Teilnehmer"}: {title?: string}): React.ReactElement {
|
||||||
console.log("Heading rendered");
|
console.log("Heading rendered");
|
||||||
return (
|
return (
|
||||||
<h1 >
|
<h2 >
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h2>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
39
react-advanced-tag1/src/hooks/useLocalStorage.ts
Normal file
39
react-advanced-tag1/src/hooks/useLocalStorage.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function useLocalStorage<T>(key: string, initialValue: T | null) {
|
||||||
|
const [value, setValue] = useState<T | null>(() => {
|
||||||
|
try {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
const storedValue = localStorage.getItem(key);
|
||||||
|
return storedValue ? JSON.parse(storedValue) : initialValue;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading from localStorage", error);
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const setStoredValue = (newValue: T) => {
|
||||||
|
try {
|
||||||
|
const valueToStore = newValue instanceof Function ? newValue(value) : newValue;
|
||||||
|
setValue(valueToStore);
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error writing to localStorage", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeStoredValue = () => {
|
||||||
|
try {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
setValue(null);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error removing from localStorage", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {value, setStoredValue, removeStoredValue};
|
||||||
|
}
|
||||||
31
react-advanced-tag1/src/hooks/useMediaQuery.ts
Normal file
31
react-advanced-tag1/src/hooks/useMediaQuery.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom hook to check if a media query matches the current viewport.
|
||||||
|
* @param query - The media query string (e.g., '(max-width: 600px)')
|
||||||
|
* @returns A boolean indicating whether the media query matches.
|
||||||
|
*/
|
||||||
|
export function useMediaQuery(query: string) {
|
||||||
|
const [matches, setMatches] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const mediaQueryList = window.matchMedia(query);
|
||||||
|
const handleChange = (event: MediaQueryListEvent) => {
|
||||||
|
setMatches(event.matches);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the initial value
|
||||||
|
setMatches(mediaQueryList.matches);
|
||||||
|
|
||||||
|
// Add event listener
|
||||||
|
mediaQueryList.addEventListener('change', handleChange);
|
||||||
|
|
||||||
|
// Cleanup function to remove the event listener
|
||||||
|
return () => {
|
||||||
|
mediaQueryList.removeEventListener('change', handleChange);
|
||||||
|
};
|
||||||
|
}, [query]);
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
@@ -25,7 +25,6 @@ a:hover {
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|||||||
56
react-advanced-tag1/src/layouts/MainLayout.css
Normal file
56
react-advanced-tag1/src/layouts/MainLayout.css
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#root {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
header nav li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav a {
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
header nav a.active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Footer from "../components/Footer";
|
import Footer from "../components/Footer";
|
||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
|
import './MainLayout.css'
|
||||||
|
|
||||||
export default function MainLayout({children}: {children: React.ReactNode | React.ReactElement | React.ReactElement[]}): React.ReactElement {
|
export default function MainLayout({children}: {children: React.ReactNode | React.ReactElement | React.ReactElement[]}): React.ReactElement {
|
||||||
|
|
||||||
@@ -17,9 +18,13 @@ export default function MainLayout({children}: {children: React.ReactNode | Reac
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
|
<div className="content">
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
<button onClick={handleClick}>Click</button>
|
<button onClick={handleClick}>Click</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ import { StrictMode } from 'react'
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
)
|
||||||
|
|||||||
11
react-advanced-tag1/src/routes/EffectExercisesPage.tsx
Normal file
11
react-advanced-tag1/src/routes/EffectExercisesPage.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import EffectExercises from "../components/exercises/EffectExercises";
|
||||||
|
import Heading from "../components/globals/Heading"
|
||||||
|
|
||||||
|
export default function EffectExercisesPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Heading title="Effekte" />
|
||||||
|
<EffectExercises />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
11
react-advanced-tag1/src/routes/FormsPage.tsx
Normal file
11
react-advanced-tag1/src/routes/FormsPage.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import RefExercise from "../components/exercises/RefExercise";
|
||||||
|
import Heading from "../components/globals/Heading";
|
||||||
|
|
||||||
|
export default function FormsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Heading title="Formulare" />
|
||||||
|
<RefExercise />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
react-advanced-tag1/src/routes/HomePage.tsx
Normal file
10
react-advanced-tag1/src/routes/HomePage.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import Heading from "../components/globals/Heading"
|
||||||
|
|
||||||
|
export default function HomePage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading title="Willkommen" />
|
||||||
|
<p>Willkommen auf der Startseite!</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
11
react-advanced-tag1/src/routes/MemoCallbackPage.tsx
Normal file
11
react-advanced-tag1/src/routes/MemoCallbackPage.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import MemoCallback from "../components/exercises/MemoCallback";
|
||||||
|
import Heading from "../components/globals/Heading";
|
||||||
|
|
||||||
|
export default function MemoCallbackPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading title="Memo und Callback" />
|
||||||
|
<MemoCallback />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
13
react-advanced-tag1/src/routes/UsersPage.tsx
Normal file
13
react-advanced-tag1/src/routes/UsersPage.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import UserEffect from "../components/exercises/UserEffect";
|
||||||
|
import { UserOverview } from "../components/exercises/UserOverview";
|
||||||
|
import Heading from "../components/globals/Heading";
|
||||||
|
|
||||||
|
export default function UsersPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Heading title="Benutzer" />
|
||||||
|
<UserEffect />
|
||||||
|
<UserOverview />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
22
react-advanced-tag1/src/utils/shuffle.test.ts
Normal file
22
react-advanced-tag1/src/utils/shuffle.test.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { shuffleArray, users } from './shuffle';
|
||||||
|
|
||||||
|
describe('shuffleArray', () => {
|
||||||
|
it('should shuffle the array and return a new order', () => {
|
||||||
|
const originalArray = [...users];
|
||||||
|
const shuffledArray = shuffleArray([...users]);
|
||||||
|
|
||||||
|
expect(shuffledArray).not.toEqual(originalArray); // Ensure the order is different
|
||||||
|
expect(shuffledArray.sort()).toEqual(originalArray.sort()); // Ensure all elements are still present
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty array when input is empty', () => {
|
||||||
|
const result = shuffleArray([]);
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle arrays with one element', () => {
|
||||||
|
const result = shuffleArray(['onlyElement']);
|
||||||
|
expect(result).toEqual(['onlyElement']);
|
||||||
|
});
|
||||||
|
});
|
||||||
11
react-advanced-tag1/src/utils/shuffle.ts
Normal file
11
react-advanced-tag1/src/utils/shuffle.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export function shuffleArray(array: string[]){
|
||||||
|
for(let i = array.length -1; i>0; i--){
|
||||||
|
|
||||||
|
const j = Math.floor(Math.random()* (i +1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...array]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const users =['John', 'Peter', 'Stefanie', 'Marta', 'Klaus', 'Anna']
|
||||||
Reference in New Issue
Block a user