feat: basic chord trainer

fix: don't add chords from backup if identical chords already exist, fixes #30
This commit is contained in:
2023-11-18 18:35:59 +01:00
parent e84470d577
commit a0fe925ea9
6 changed files with 188 additions and 744 deletions

View File

@@ -74,6 +74,21 @@ const config: IconsConfig = {
"restore_from_trash",
"history",
"history_toggle_off",
"sentiment_satisfied",
"sentiment_dissatisfied",
"sentiment_very_satisfied",
"sentiment_neutral",
"sentiment_very_dissatisfied",
"sentiment_excited",
"sentiment_frustrated",
"sentiment_calm",
"sentiment_stressed",
"sentiment_extremely_dissatisfied",
"sentiment_sad",
"sentiment_content",
"sentiment_worried",
"timer",
"target",
],
codePoints: {
speed: "e9e4",
@@ -87,6 +102,7 @@ const config: IconsConfig = {
light_mode: "e518",
upload_file: "e9fc",
no_sound: "e710",
sentiment_extremely_dissatisfied: "f194",
},
}

734
package-lock.json generated
View File

@@ -25,9 +25,6 @@
"@tauri-apps/api": "^1.4.0",
"@tauri-apps/cli": "^1.4.0",
"@theaninova/prettier-config": "^1.0.0",
"@tiptap/core": "^2.1.12",
"@tiptap/pm": "^2.1.12",
"@tiptap/starter-kit": "^2.1.12",
"@types/dom-view-transitions": "^1.0.1",
"@types/flexsearch": "^0.7.3",
"@types/w3c-web-serial": "^1.0.3",
@@ -2869,54 +2866,6 @@
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@remirror/core-constants": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.2.tgz",
"integrity": "sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==",
"dev": true
},
"node_modules/@remirror/core-helpers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@remirror/core-helpers/-/core-helpers-3.0.0.tgz",
"integrity": "sha512-tusEgQJIqg4qKj6HSBUFcyRnWnziw3neh4T9wOmsPGHFC3w9kl5KSrDb9UAgE8uX6y32FnS7vJ955mWOl3n50A==",
"dev": true,
"dependencies": {
"@remirror/core-constants": "^2.0.2",
"@remirror/types": "^1.0.1",
"@types/object.omit": "^3.0.0",
"@types/object.pick": "^1.3.2",
"@types/throttle-debounce": "^2.1.0",
"case-anything": "^2.1.13",
"dash-get": "^1.0.2",
"deepmerge": "^4.3.1",
"fast-deep-equal": "^3.1.3",
"make-error": "^1.3.6",
"object.omit": "^3.0.0",
"object.pick": "^1.3.0",
"throttle-debounce": "^3.0.1"
}
},
"node_modules/@remirror/types": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz",
"integrity": "sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==",
"dev": true,
"dependencies": {
"type-fest": "^2.19.0"
}
},
"node_modules/@remirror/types/node_modules/type-fest": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
"dev": true,
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
@@ -3270,319 +3219,6 @@
"integrity": "sha512-DdP5OvUL6Tso+XMNiH+WQJrbvJsIGIudekZKMW4oGt060hqZIzwiASILCiDg6+OigKTC1KObvv4nTBQSjM2g1g==",
"dev": true
},
"node_modules/@tiptap/core": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.1.12.tgz",
"integrity": "sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-blockquote": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.1.12.tgz",
"integrity": "sha512-Qb3YRlCfugx9pw7VgLTb+jY37OY4aBJeZnqHzx4QThSm13edNYjasokbX0nTwL1Up4NPTcY19JUeHt6fVaVVGg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-bold": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.1.12.tgz",
"integrity": "sha512-AZGxIxcGU1/y6V2YEbKsq6BAibL8yQrbRm6EdcBnby41vj1WziewEKswhLGmZx5IKM2r2ldxld03KlfSIlKQZg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-bullet-list": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.1.12.tgz",
"integrity": "sha512-vtD8vWtNlmAZX8LYqt2yU9w3mU9rPCiHmbp4hDXJs2kBnI0Ju/qAyXFx6iJ3C3XyuMnMbJdDI9ee0spAvFz7cQ==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-code": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.1.12.tgz",
"integrity": "sha512-CRiRq5OTC1lFgSx6IMrECqmtb93a0ZZKujEnaRhzWliPBjLIi66va05f/P1vnV6/tHaC3yfXys6dxB5A4J8jxw==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-code-block": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.1.12.tgz",
"integrity": "sha512-RXtSYCVsnk8D+K80uNZShClfZjvv1EgO42JlXLVGWQdIgaNyuOv/6I/Jdf+ZzhnpsBnHufW+6TJjwP5vJPSPHA==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0",
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-document": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.1.12.tgz",
"integrity": "sha512-0QNfAkCcFlB9O8cUNSwTSIQMV9TmoEhfEaLz/GvbjwEq4skXK3bU+OQX7Ih07waCDVXIGAZ7YAZogbvrn/WbOw==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-dropcursor": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.1.12.tgz",
"integrity": "sha512-0tT/q8nL4NBCYPxr9T0Brck+RQbWuczm9nV0bnxgt0IiQXoRHutfPWdS7GA65PTuVRBS/3LOco30fbjFhkfz/A==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0",
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-gapcursor": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.1.12.tgz",
"integrity": "sha512-zFYdZCqPgpwoB7whyuwpc8EYLYjUE5QYKb8vICvc+FraBUDM51ujYhFSgJC3rhs8EjI+8GcK8ShLbSMIn49YOQ==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0",
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-hard-break": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.1.12.tgz",
"integrity": "sha512-nqKcAYGEOafg9D+2cy1E4gHNGuL12LerVa0eS2SQOb+PT8vSel9OTKU1RyZldsWSQJ5rq/w4uIjmLnrSR2w6Yw==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-heading": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.1.12.tgz",
"integrity": "sha512-MoANP3POAP68Ko9YXarfDKLM/kXtscgp6m+xRagPAghRNujVY88nK1qBMZ3JdvTVN6b/ATJhp8UdrZX96TLV2w==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-history": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.1.12.tgz",
"integrity": "sha512-6b7UFVkvPjq3LVoCTrYZAczt5sQrQUaoDWAieVClVZoFLfjga2Fwjcfgcie8IjdPt8YO2hG/sar/c07i9vM0Sg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0",
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-horizontal-rule": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.1.12.tgz",
"integrity": "sha512-RRuoK4KxrXRrZNAjJW5rpaxjiP0FJIaqpi7nFbAua2oHXgsCsG8qbW2Y0WkbIoS8AJsvLZ3fNGsQ8gpdliuq3A==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0",
"@tiptap/pm": "^2.0.0"
}
},
"node_modules/@tiptap/extension-italic": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.1.12.tgz",
"integrity": "sha512-/XYrW4ZEWyqDvnXVKbgTXItpJOp2ycswk+fJ3vuexyolO6NSs0UuYC6X4f+FbHYL5VuWqVBv7EavGa+tB6sl3A==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-list-item": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.1.12.tgz",
"integrity": "sha512-Gk7hBFofAPmNQ8+uw8w5QSsZOMEGf7KQXJnx5B022YAUJTYYxO3jYVuzp34Drk9p+zNNIcXD4kc7ff5+nFOTrg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-ordered-list": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.1.12.tgz",
"integrity": "sha512-tF6VGl+D2avCgn9U/2YLJ8qVmV6sPE/iEzVAFZuOSe6L0Pj7SQw4K6AO640QBob/d8VrqqJFHCb6l10amJOnXA==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-paragraph": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.1.12.tgz",
"integrity": "sha512-hoH/uWPX+KKnNAZagudlsrr4Xu57nusGekkJWBcrb5MCDE91BS+DN2xifuhwXiTHxnwOMVFjluc0bPzQbkArsw==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-strike": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.1.12.tgz",
"integrity": "sha512-HlhrzIjYUT8oCH9nYzEL2QTTn8d1ECnVhKvzAe6x41xk31PjLMHTUy8aYjeQEkWZOWZ34tiTmslV1ce6R3Dt8g==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/extension-text": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.1.12.tgz",
"integrity": "sha512-rCNUd505p/PXwU9Jgxo4ZJv4A3cIBAyAqlx/dtcY6cjztCQuXJhuQILPhjGhBTOLEEL4kW2wQtqzCmb7O8i2jg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0"
}
},
"node_modules/@tiptap/pm": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.1.12.tgz",
"integrity": "sha512-Q3MXXQABG4CZBesSp82yV84uhJh/W0Gag6KPm2HRWPimSFELM09Z9/5WK9RItAYE0aLhe4Krnyiczn9AAa1tQQ==",
"dev": true,
"dependencies": {
"prosemirror-changeset": "^2.2.0",
"prosemirror-collab": "^1.3.0",
"prosemirror-commands": "^1.3.1",
"prosemirror-dropcursor": "^1.5.0",
"prosemirror-gapcursor": "^1.3.1",
"prosemirror-history": "^1.3.0",
"prosemirror-inputrules": "^1.2.0",
"prosemirror-keymap": "^1.2.0",
"prosemirror-markdown": "^1.10.1",
"prosemirror-menu": "^1.2.1",
"prosemirror-model": "^1.18.1",
"prosemirror-schema-basic": "^1.2.0",
"prosemirror-schema-list": "^1.2.2",
"prosemirror-state": "^1.4.1",
"prosemirror-tables": "^1.3.0",
"prosemirror-trailing-node": "^2.0.2",
"prosemirror-transform": "^1.7.0",
"prosemirror-view": "^1.28.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
}
},
"node_modules/@tiptap/starter-kit": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.1.12.tgz",
"integrity": "sha512-+RoP1rWV7rSCit2+3wl2bjvSRiePRJE/7YNKbvH8Faz/+AMO23AFegHoUFynR7U0ouGgYDljGkkj35e0asbSDA==",
"dev": true,
"dependencies": {
"@tiptap/core": "^2.1.12",
"@tiptap/extension-blockquote": "^2.1.12",
"@tiptap/extension-bold": "^2.1.12",
"@tiptap/extension-bullet-list": "^2.1.12",
"@tiptap/extension-code": "^2.1.12",
"@tiptap/extension-code-block": "^2.1.12",
"@tiptap/extension-document": "^2.1.12",
"@tiptap/extension-dropcursor": "^2.1.12",
"@tiptap/extension-gapcursor": "^2.1.12",
"@tiptap/extension-hard-break": "^2.1.12",
"@tiptap/extension-heading": "^2.1.12",
"@tiptap/extension-history": "^2.1.12",
"@tiptap/extension-horizontal-rule": "^2.1.12",
"@tiptap/extension-italic": "^2.1.12",
"@tiptap/extension-list-item": "^2.1.12",
"@tiptap/extension-ordered-list": "^2.1.12",
"@tiptap/extension-paragraph": "^2.1.12",
"@tiptap/extension-strike": "^2.1.12",
"@tiptap/extension-text": "^2.1.12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
}
},
"node_modules/@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@@ -3673,18 +3309,6 @@
"integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
"dev": true
},
"node_modules/@types/object.omit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/object.omit/-/object.omit-3.0.2.tgz",
"integrity": "sha512-BxWU36cMP+FKD3OLFluQaj2cBev2sx2LJaHELuphHwnleq+xnEhTmuYYYx4pOT/1U/ZoR6B+RdvxWh2FD6lGGA==",
"dev": true
},
"node_modules/@types/object.pick": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@types/object.pick/-/object.pick-1.3.3.tgz",
"integrity": "sha512-qZqHmdGEALeSATMB1djT1S5szv6Wtpb7DKpHrt2XG4iyKlV7C2Xk8GmDXr1KXakOqUfX6ohw7ceruYt4NVmB1Q==",
"dev": true
},
"node_modules/@types/pug": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
@@ -3712,12 +3336,6 @@
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
"dev": true
},
"node_modules/@types/throttle-debounce": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz",
"integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==",
"dev": true
},
"node_modules/@types/trusted-types": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
@@ -4555,18 +4173,6 @@
}
]
},
"node_modules/case-anything": {
"version": "2.1.13",
"resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz",
"integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
"dev": true,
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -5270,12 +4876,6 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/dash-get": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/dash-get/-/dash-get-1.0.2.tgz",
"integrity": "sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==",
"dev": true
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -7032,30 +6632,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
"integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
"dev": true,
"dependencies": {
"is-plain-object": "^2.0.4"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-extendable/node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dev": true,
"dependencies": {
"isobject": "^3.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -7347,15 +6923,6 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -7778,15 +7345,6 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"node_modules/linkify-it": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
"integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
"dev": true,
"dependencies": {
"uc.micro": "^1.0.1"
}
},
"node_modules/load-json-file": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
@@ -8089,34 +7647,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/markdown-it": {
"version": "13.0.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz",
"integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1",
"entities": "~3.0.1",
"linkify-it": "^4.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/markdown-it/node_modules/entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
"dev": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/mathml-tag-names": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
@@ -8133,12 +7663,6 @@
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"dev": true
},
"node_modules/mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
"dev": true
},
"node_modules/memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@@ -8625,30 +8149,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.omit": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz",
"integrity": "sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==",
"dev": true,
"dependencies": {
"is-extendable": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
"integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
"dev": true,
"dependencies": {
"isobject": "^3.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -8689,12 +8189,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/orderedmap": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
"dev": true
},
"node_modules/os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
@@ -9277,213 +8771,6 @@
"node": ">= 0.6.0"
}
},
"node_modules/prosemirror-changeset": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz",
"integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==",
"dev": true,
"dependencies": {
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-collab": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz",
"integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==",
"dev": true,
"dependencies": {
"prosemirror-state": "^1.0.0"
}
},
"node_modules/prosemirror-commands": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz",
"integrity": "sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-dropcursor": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz",
"integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==",
"dev": true,
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0",
"prosemirror-view": "^1.1.0"
}
},
"node_modules/prosemirror-gapcursor": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz",
"integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==",
"dev": true,
"dependencies": {
"prosemirror-keymap": "^1.0.0",
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-view": "^1.0.0"
}
},
"node_modules/prosemirror-history": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.2.tgz",
"integrity": "sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==",
"dev": true,
"dependencies": {
"prosemirror-state": "^1.2.2",
"prosemirror-transform": "^1.0.0",
"prosemirror-view": "^1.31.0",
"rope-sequence": "^1.3.0"
}
},
"node_modules/prosemirror-inputrules": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.1.tgz",
"integrity": "sha512-3LrWJX1+ULRh5SZvbIQlwZafOXqp1XuV21MGBu/i5xsztd+9VD15x6OtN6mdqSFI7/8Y77gYUbQ6vwwJ4mr6QQ==",
"dev": true,
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-keymap": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz",
"integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==",
"dev": true,
"dependencies": {
"prosemirror-state": "^1.0.0",
"w3c-keyname": "^2.2.0"
}
},
"node_modules/prosemirror-markdown": {
"version": "1.11.2",
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.11.2.tgz",
"integrity": "sha512-Eu5g4WPiCdqDTGhdSsG9N6ZjACQRYrsAkrF9KYfdMaCmjIApH75aVncsWYOJvEk2i1B3i8jZppv3J/tnuHGiUQ==",
"dev": true,
"dependencies": {
"markdown-it": "^13.0.1",
"prosemirror-model": "^1.0.0"
}
},
"node_modules/prosemirror-menu": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz",
"integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==",
"dev": true,
"dependencies": {
"crelt": "^1.0.0",
"prosemirror-commands": "^1.0.0",
"prosemirror-history": "^1.0.0",
"prosemirror-state": "^1.0.0"
}
},
"node_modules/prosemirror-model": {
"version": "1.19.3",
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.19.3.tgz",
"integrity": "sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==",
"dev": true,
"dependencies": {
"orderedmap": "^2.0.0"
}
},
"node_modules/prosemirror-schema-basic": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.2.tgz",
"integrity": "sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.19.0"
}
},
"node_modules/prosemirror-schema-list": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.3.0.tgz",
"integrity": "sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.7.3"
}
},
"node_modules/prosemirror-state": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
"integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0",
"prosemirror-view": "^1.27.0"
}
},
"node_modules/prosemirror-tables": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.3.4.tgz",
"integrity": "sha512-z6uLSQ1BLC3rgbGwZmpfb+xkdvD7W/UOsURDfognZFYaTtc0gsk7u/t71Yijp2eLflVpffMk6X0u0+u+MMDvIw==",
"dev": true,
"dependencies": {
"prosemirror-keymap": "^1.1.2",
"prosemirror-model": "^1.8.1",
"prosemirror-state": "^1.3.1",
"prosemirror-transform": "^1.2.1",
"prosemirror-view": "^1.13.3"
}
},
"node_modules/prosemirror-trailing-node": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.7.tgz",
"integrity": "sha512-8zcZORYj/8WEwsGo6yVCRXFMOfBo0Ub3hCUvmoWIZYfMP26WqENU0mpEP27w7mt8buZWuGrydBewr0tOArPb1Q==",
"dev": true,
"dependencies": {
"@remirror/core-constants": "^2.0.2",
"@remirror/core-helpers": "^3.0.0",
"escape-string-regexp": "^4.0.0"
},
"peerDependencies": {
"prosemirror-model": "^1.19.0",
"prosemirror-state": "^1.4.2",
"prosemirror-view": "^1.31.2"
}
},
"node_modules/prosemirror-trailing-node/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/prosemirror-transform": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.8.0.tgz",
"integrity": "sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.0.0"
}
},
"node_modules/prosemirror-view": {
"version": "1.32.3",
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.32.3.tgz",
"integrity": "sha512-tP7AUTxisM0m3PDxs6vDWgTjgcbFo4fnwg2M/5NHlgMqUJgBNOqSUZETBZKmLD7AxGN3GZ5yqEzQv9r9VCZKrg==",
"dev": true,
"dependencies": {
"prosemirror-model": "^1.16.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -9900,12 +9187,6 @@
"fsevents": "~2.3.2"
}
},
"node_modules/rope-sequence": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
"integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
"dev": true
},
"node_modules/rrweb-cssom": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
@@ -11058,15 +10339,6 @@
"node": ">=10"
}
},
"node_modules/throttle-debounce": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/throttleit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
@@ -11441,12 +10713,6 @@
"node": ">=14.17"
}
},
"node_modules/uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
"dev": true
},
"node_modules/ufo": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.0.tgz",

View File

@@ -109,7 +109,11 @@ export function restoreFromFile(
export function getChangesFromChordFile(file: CharaChordFile) {
const changes: Change[] = []
const existingChords = new Set(get(chords).map(({phrase, actions}) => JSON.stringify({phrase, actions})))
for (const [input, output] of file.chords) {
if (existingChords.has(JSON.stringify({actions: input, phrase: output}))) {
continue
}
changes.push({
type: ChangeType.Chord,
actions: input,

View File

@@ -0,0 +1 @@
<h1>Layout Bootcamp</h1>

View File

@@ -13,6 +13,10 @@
let pressedKeys = new Set<number>()
let editing = false
function compare(a: number, b: number) {
return a - b
}
function edit() {
pressedKeys = new Set()
editing = true
@@ -29,16 +33,12 @@
if (!editing) return
editing = false
if (pressedKeys.size < 2) return
if (!chord)
return dispatch(
"submit",
[...pressedKeys].sort((a, b) => a - b),
)
if (!chord) return dispatch("submit", [...pressedKeys].sort(compare))
changes.update(changes => {
changes.push({
type: ChangeType.Chord,
id: chord!.id,
actions: [...pressedKeys].sort((a, b) => a - b),
actions: [...pressedKeys].sort(compare),
phrase: chord!.phrase,
})
return changes
@@ -49,6 +49,7 @@
<button
class:deleted={chord && chord.phrase.length === 0}
class:edited={chord && chord.actionsChanged}
class:invalid={chord && chord.actions.toSorted(compare).some((it, i) => chord?.actions[i] !== it)}
on:click={edit}
on:keydown={keydown}
on:keyup={keyup}
@@ -58,10 +59,7 @@
{:else if !editing && !chord}
<span>{$LL.configure.chords.NEW_CHORD()}</span>
{/if}
<ActionString
display="keys"
actions={editing ? [...pressedKeys].sort((a, b) => a - b) : chord?.actions ?? []}
/>
<ActionString display="keys" actions={editing ? [...pressedKeys].sort(compare) : chord?.actions ?? []} />
<sup></sup>
</button>
@@ -117,6 +115,10 @@
}
}
.invalid {
color: var(--md-sys-color-error);
}
.deleted {
color: var(--md-sys-color-error);

View File

@@ -0,0 +1,155 @@
<script lang="ts">
import {chords} from "$lib/undo-redo"
import Action from "$lib/components/Action.svelte"
import {onDestroy, onMount} from "svelte"
import {KEYMAP_CODES} from "$lib/serial/keymap-codes"
import {fly} from "svelte/transition"
import type {Chord} from "$lib/serial/chord"
const speedRating = [
[400, "+100", "excited", true],
[700, "+50", "satisfied", true],
[1400, "+25", "neutral", true],
[3000, "0", "dissatisfied", false],
[Infinity, "-50", "sad", false],
] as const
const accuracyRating = [
[2, "+100", "calm", true],
[3, "+50", "content", false],
[5, "+25", "stressed", false],
[7, "0", "frustrated", false],
[14, "-25", "very_dissatisfied", false],
[Infinity, "-50", "extremely_dissatisfied", false],
] as const
let next: Chord[] = []
let nextHandle: number
let took: number | undefined
let delta = 0
let speed: readonly [number, string, string, boolean] | undefined
let accuracy: readonly [number, string, string, boolean] | undefined
let progress = 0
let attempts = 0
let userInput = ""
onMount(() => {
runTest()
})
function runTest() {
if (took === undefined) {
took = performance.now()
delta = 0
attempts = 0
userInput = ""
if (next.length === 0) {
next = Array.from({length: 5}, () => $chords[Math.floor(Math.random() * $chords.length)])
} else {
next.shift()
next.push($chords[Math.floor(Math.random() * $chords.length)])
next = next
}
}
if (userInput === next[0].phrase.map(it => (it === 32 ? " " : KEYMAP_CODES[it]!.id)).join("") + " ") {
took = undefined
speed = speedRating.find(([max]) => delta <= max)
accuracy = accuracyRating.find(([max]) => attempts <= max)
progress++
} else {
delta = performance.now() - took
}
nextHandle = requestAnimationFrame(runTest)
}
let debounceTimer = 0
function backspace(event: KeyboardEvent) {
if (event.code === "Backspace") {
userInput = userInput.slice(0, -1)
}
}
function input(event: KeyboardEvent) {
const stamp = performance.now()
if (stamp - debounceTimer > 50) {
attempts++
}
debounceTimer = stamp
userInput += event.key
}
onDestroy(() => {
if (nextHandle) {
cancelAnimationFrame(nextHandle)
}
})
</script>
<svelte:window on:keydown={backspace} on:keypress={input} />
<h1>Vocabulary Trainer</h1>
{#if next[0]}
<div class="row">
{#key progress}
<div in:fly={{duration: 300, x: -48}} out:fly={{duration: 1000, x: 128}} class="rating">
{#if speed}
<span class="rating-item">
<span style:color="var(--md-sys-color-{speed[3] ? `primary` : `error`})" class="icon">timer</span>
{speed[1]}
<span class="icon">sentiment_{speed[2]}</span>
</span>
{/if}
{#if accuracy}
<span class="rating-item">
<span style:color="var(--md-sys-color-{accuracy[3] ? `primary` : `error`})" class="icon"
>target</span
>
{accuracy[1]}
<span class="icon">sentiment_{accuracy[2]}</span>
</span>
{/if}
</div>
{/key}
</div>
<div class="hint" style:opacity={delta > 3000 ? 1 : 0}>
{#each next[0].actions as action}
<Action {action} display="keys" />
{/each}
</div>
<div>
{userInput}
</div>
{#each next as chord, i}
<div class="words" style:opacity={1 - i / next.length}>
{#each chord.phrase as action}
<Action {action} />
{/each}
</div>
{/each}
{:else}
<p>You don't have any chords</p>
{/if}
<style lang="scss">
.row {
position: relative;
height: 48px;
}
.rating-item {
display: flex;
gap: 8px;
justify-content: flex-start;
}
.rating {
position: absolute;
left: -48px;
width: max-content;
}
</style>