diff --git a/package-lock.json b/package-lock.json
index 23a9aad..352ae00 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,10 @@
"version": "0.0.0",
"dependencies": {
"@cormoran/zmk-studio-react-hook": "github:cormoran/react-zmk-studio",
+ "@keyboard-hub/abyss-client": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/abyss-client",
+ "@keyboard-hub/adapter-common": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-common",
+ "@keyboard-hub/adapter-zmk": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-zmk",
+ "@keyboard-hub/shared": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/shared",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
@@ -61,6 +65,29 @@
"vite-plugin-svgr": "^4.5.0"
}
},
+ "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/abyss-client": {
+ "name": "@keyboard-hub/abyss-client",
+ "version": "0.0.0",
+ "dependencies": {
+ "@keyboard-hub/shared": "0.0.0"
+ }
+ },
+ "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-common": {
+ "name": "@keyboard-hub/adapter-common",
+ "version": "0.0.0"
+ },
+ "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-zmk": {
+ "name": "@keyboard-hub/adapter-zmk",
+ "version": "0.0.0",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.12.0",
+ "@zmkfirmware/zmk-studio-ts-client": "git+https://github.com/cormoran/zmk-studio-ts-client.git#custom-studio-protocol+bluefy"
+ }
+ },
+ "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/shared": {
+ "name": "@keyboard-hub/shared",
+ "version": "0.0.0"
+ },
"node_modules/@adobe/css-tools": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz",
@@ -133,6 +160,7 @@
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@@ -966,6 +994,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -989,6 +1018,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -2533,6 +2563,22 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@keyboard-hub/abyss-client": {
+ "resolved": "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/abyss-client",
+ "link": true
+ },
+ "node_modules/@keyboard-hub/adapter-common": {
+ "resolved": "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-common",
+ "link": true
+ },
+ "node_modules/@keyboard-hub/adapter-zmk": {
+ "resolved": "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-zmk",
+ "link": true
+ },
+ "node_modules/@keyboard-hub/shared": {
+ "resolved": "../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/shared",
+ "link": true
+ },
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
@@ -3777,6 +3823,7 @@
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
@@ -4279,8 +4326,7 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -4531,6 +4577,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -4541,6 +4588,7 @@
"integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==",
"devOptional": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -4551,6 +4599,7 @@
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
+ "peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -4665,6 +4714,7 @@
"integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.53.1",
"@typescript-eslint/types": "8.53.1",
@@ -4942,6 +4992,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -5337,6 +5388,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -6049,8 +6101,7 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/dot-case": {
"version": "3.0.4",
@@ -6202,6 +6253,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -7231,6 +7283,7 @@
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@jest/core": "^29.7.0",
"@jest/types": "^29.6.3",
@@ -9121,6 +9174,7 @@
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"cssstyle": "^4.2.1",
"data-urls": "^5.0.0",
@@ -9832,7 +9886,6 @@
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -10429,6 +10482,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -10477,7 +10531,6 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -10493,7 +10546,6 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -10571,6 +10623,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -10580,6 +10633,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -10599,6 +10653,7 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
@@ -10744,7 +10799,8 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/redux-thunk": {
"version": "3.1.0",
@@ -11508,6 +11564,7 @@
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -11630,6 +11687,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -11826,6 +11884,7 @@
"integrity": "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@oxc-project/runtime": "0.97.0",
"fdir": "^6.5.0",
@@ -12184,6 +12243,7 @@
"integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
"dev": true,
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/package.json b/package.json
index b3b3324..edcdcac 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,10 @@
},
"dependencies": {
"@cormoran/zmk-studio-react-hook": "github:cormoran/react-zmk-studio",
+ "@keyboard-hub/abyss-client": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/abyss-client",
+ "@keyboard-hub/adapter-common": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-common",
+ "@keyboard-hub/adapter-zmk": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/adapter-zmk",
+ "@keyboard-hub/shared": "file:../../../../Program/src/github.com/cormoran/keyboard-abyss/packages/shared",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
diff --git a/src/App.tsx b/src/App.tsx
index f76f255..7229ed0 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from "framer-motion";
import {
IconBattery2,
IconBluetooth,
+ IconCloudDownload,
IconHome,
IconKeyboard,
IconPointer,
@@ -27,6 +28,7 @@ import { KeymapPage } from "./pages/KeymapPage";
import { TrackballPage } from "./pages/TrackballPage";
import { SettingsPage } from "./pages/SettingsPage";
import { CustomSubsystemsPage } from "./pages/CustomSubsystemsPage";
+import { ImportExportPage } from "./pages/ImportExportPage";
const tabs: TabItem[] = [
{
@@ -71,6 +73,12 @@ const tabs: TabItem[] = [
icon:
+ {section.count - section.rows.length} more changes +
+ )} ++ Sync keymaps with Keyboard Abyss +
++ Set VITE_ABYSS_CLIENT_ID to enable Keyboard Abyss login. +
+{error}
++ Keyboard needs Studio unlock before Abyss can read or write the + keymap. +
+ ++ Login to Keyboard Abyss to load keymaps. +
+ ) : isLoadingData && keymaps.length === 0 ? ( ++ No Abyss keymaps are available. +
+ ) : ( ++ Select an Abyss keymap to preview changes. +
+ ) : !loadedKeyboard ? ( ++ Load the connected keyboard to compare keymaps. +
+ ) : diff ? ( +