From 209483fd360cd99a3fdc0cc226a0cdbce27abbb9 Mon Sep 17 00:00:00 2001 From: Pongstr Date: Fri, 13 Dec 2024 00:18:13 +0200 Subject: [PATCH 1/5] chore(fix-lint): init lint fixes --- .eslintrc.cjs | 14 +++ .prettierrc | 5 +- package-lock.json | 28 +++++ package.json | 1 + src/AboutModal.tsx | 12 +- src/App.tsx | 36 +++--- src/AppFooter.tsx | 6 +- src/AppHeader.tsx | 39 +++---- src/ConnectModal.tsx | 14 +-- src/GenericModal.tsx | 2 +- src/UnlockModal.tsx | 9 +- src/behaviors/BehaviorBindingPicker.tsx | 15 +-- src/behaviors/HidUsagePicker.tsx | 33 +++--- src/keyboard/HidUsageLabel.tsx | 10 +- src/keyboard/Key.tsx | 8 +- src/keyboard/Keyboard.tsx | 139 ++++++++++++++---------- src/keyboard/Keymap.tsx | 2 +- src/keyboard/LayerPicker.tsx | 30 ++--- src/keyboard/PhysicalLayout.tsx | 21 ++-- src/keyboard/PhysicalLayoutPicker.tsx | 12 +- src/misc/ExternalLink.tsx | 2 +- src/misc/LicenseNoticeModal.tsx | 8 +- src/misc/Tooltip.tsx | 2 +- src/misc/useModalRef.ts | 6 +- src/rpc/useConnectedDeviceData.ts | 13 ++- src/tauri/ble.ts | 20 ++-- src/tauri/serial.ts | 20 ++-- src/undoRedo.ts | 6 +- src/usePubSub.ts | 4 +- 29 files changed, 292 insertions(+), 225 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 200a1665..d2b2b15d 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -6,11 +6,25 @@ module.exports = { "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended", "plugin:storybook/recommended", + "plugin:tailwindcss/recommended", ], ignorePatterns: ["dist", ".eslintrc.cjs"], parser: "@typescript-eslint/parser", plugins: ["react-refresh"], rules: { + "tailwindcss/no-custom-classname": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + args: "all", + argsIgnorePattern: "^_", + caughtErrors: "all", + caughtErrorsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + varsIgnorePattern: "^_", + ignoreRestSiblings: true, + }, + ], "react-refresh/only-export-components": [ "warn", { allowConstantExport: true }, diff --git a/.prettierrc b/.prettierrc index 0967ef42..32d463b8 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1,4 @@ -{} +{ + "tabWidth": 2, + "semi": true +} diff --git a/package-lock.json b/package-lock.json index 314418dc..31d59f03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", "eslint-plugin-storybook": "^0.8.0", + "eslint-plugin-tailwindcss": "^3.17.5", "postcss": "^8.4.38", "prettier": "3.3.2", "run-script-os": "^1.1.6", @@ -6460,6 +6461,23 @@ "node": ">=4.0" } }, + "node_modules/eslint-plugin-tailwindcss": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.17.5.tgz", + "integrity": "sha512-8Mi7p7dm+mO1dHgRHHFdPu4RDTBk69Cn4P0B40vRQR+MrguUpwmKwhZy1kqYe3Km8/4nb+cyrCF+5SodOEmaow==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.5", + "postcss": "^8.4.4" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "tailwindcss": "^3.4.0" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "dev": true, @@ -15294,6 +15312,16 @@ } } }, + "eslint-plugin-tailwindcss": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.17.5.tgz", + "integrity": "sha512-8Mi7p7dm+mO1dHgRHHFdPu4RDTBk69Cn4P0B40vRQR+MrguUpwmKwhZy1kqYe3Km8/4nb+cyrCF+5SodOEmaow==", + "dev": true, + "requires": { + "fast-glob": "^3.2.5", + "postcss": "^8.4.4" + } + }, "eslint-scope": { "version": "7.2.2", "dev": true, diff --git a/package.json b/package.json index 68d2f2ac..f4dd8d5b 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", "eslint-plugin-storybook": "^0.8.0", + "eslint-plugin-tailwindcss": "^3.17.5", "postcss": "^8.4.38", "prettier": "3.3.2", "run-script-os": "^1.1.6", diff --git a/src/AboutModal.tsx b/src/AboutModal.tsx index 8ecf5940..73bf1397 100644 --- a/src/AboutModal.tsx +++ b/src/AboutModal.tsx @@ -179,8 +179,8 @@ export const AboutModal = ({ open, onClose }: AboutModalProps) => { const ref = useModalRef(open, true); return ( - -
+ +

The ZMK Project:{" "} website,{" "} @@ -193,20 +193,20 @@ export const AboutModal = ({ open, onClose }: AboutModalProps) => {

-

+

ZMK Studio is made possible thanks to the generous donation of time from our contributors, as well as the financial sponsorship from the following vendors:

-
+
{sponsors.map((s) => { const heightVariants = { [SponsorSize.Large]: "h-16", @@ -218,7 +218,7 @@ export const AboutModal = ({ open, onClose }: AboutModalProps) => {
diff --git a/src/App.tsx b/src/App.tsx index e09ed0cb..fa7af5dd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -68,19 +68,19 @@ const TRANSPORTS: TransportFactory[] = [ async function listen_for_notifications( notification_stream: ReadableStream, - signal: AbortSignal + signal: AbortSignal, ): Promise { - let reader = notification_stream.getReader(); + const reader = notification_stream.getReader(); const onAbort = () => { reader.cancel(); reader.releaseLock(); }; signal.addEventListener("abort", onAbort, { once: true }); do { - let pub = usePub(); + const pub = usePub(); try { - let { done, value } = await reader.read(); + const { done, value } = await reader.read(); if (done) { break; } @@ -93,7 +93,7 @@ async function listen_for_notifications( pub("rpc_notification", value); const subsystem = Object.entries(value).find( - ([_k, v]) => v !== undefined + ([_k, v]) => v !== undefined, ); if (!subsystem) { continue; @@ -126,11 +126,11 @@ async function connect( transport: RpcTransport, setConn: Dispatch, setConnectedDeviceName: Dispatch, - signal: AbortSignal + signal: AbortSignal, ) { - let conn = await create_rpc_connection(transport, { signal }); + const conn = await create_rpc_connection(transport, { signal }); - let details = await Promise.race([ + const details = await Promise.race([ call_rpc(conn, { core: { getDeviceInfo: true } }) .then((r) => r?.core?.getDeviceInfo) .catch((e) => { @@ -171,11 +171,11 @@ function App() { const [connectionAbort, setConnectionAbort] = useState(new AbortController()); const [lockState, setLockState] = useState( - LockState.ZMK_STUDIO_CORE_LOCK_STATE_LOCKED + LockState.ZMK_STUDIO_CORE_LOCK_STATE_LOCKED, ); - useSub("rpc_notification.core.lockStateChanged", (ls) => { - setLockState(ls); + useSub("rpc_notification.core.lockStateChanged", (ls: unknown) => { + setLockState(ls as LockState); }); useEffect(() => { @@ -189,13 +189,13 @@ function App() { return; } - let locked_resp = await call_rpc(conn.conn, { + const locked_resp = await call_rpc(conn.conn, { core: { getLockState: true }, }); setLockState( locked_resp.core?.getLockState || - LockState.ZMK_STUDIO_CORE_LOCK_STATE_LOCKED + LockState.ZMK_STUDIO_CORE_LOCK_STATE_LOCKED, ); } @@ -208,7 +208,7 @@ function App() { return; } - let resp = await call_rpc(conn.conn, { keymap: { saveChanges: true } }); + const resp = await call_rpc(conn.conn, { keymap: { saveChanges: true } }); if (!resp.keymap?.saveChanges || resp.keymap?.saveChanges.err) { console.error("Failed to save changes", resp.keymap?.saveChanges); } @@ -223,7 +223,7 @@ function App() { return; } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { keymap: { discardChanges: true }, }); if (!resp.keymap?.discardChanges) { @@ -243,7 +243,7 @@ function App() { return; } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { core: { resetSettings: true }, }); if (!resp.core?.resetSettings) { @@ -277,7 +277,7 @@ function App() { setConnectionAbort(ac); connect(t, setConn, setConnectedDeviceName, ac.signal); }, - [setConn, setConnectedDeviceName, setConnectedDeviceName] + [setConn, setConnectedDeviceName, setConnectedDeviceName], ); return ( @@ -295,7 +295,7 @@ function App() { open={showLicenseNotice} onClose={() => setShowLicenseNotice(false)} /> -
+
{ return ( -
+
© 2024 - The ZMK Contributors -{" "} - + About ZMK Studio {" "} -{" "} - + License NOTICE
diff --git a/src/AppHeader.tsx b/src/AppHeader.tsx index 52a6658d..5a5dc3fe 100644 --- a/src/AppHeader.tsx +++ b/src/AppHeader.tsx @@ -52,21 +52,22 @@ export const AppHeader = ({ ) { setShowSettingsReset(false); } - }, [lockState, showSettingsReset]); + }, [connectionState.conn, lockState, showSettingsReset]); const showSettingsRef = useModalRef(showSettingsReset); const [unsaved, setUnsaved] = useConnectedDeviceData( { keymap: { checkUnsavedChanges: true } }, - (r) => r.keymap?.checkUnsavedChanges + (r) => r.keymap?.checkUnsavedChanges, ); - useSub("rpc_notification.keymap.unsavedChangesStatusChanged", (unsaved) => - setUnsaved(unsaved) + useSub( + "rpc_notification.keymap.unsavedChangesStatusChanged", + (unsaved: boolean) => setUnsaved(unsaved), ); return ( -
-
+
+
ZMK Logo

Studio

@@ -78,15 +79,15 @@ export const AppHeader = ({ Studio and restore the stock keymap

Continue?

-
+
- + )} @@ -138,30 +139,30 @@ export const AppHeader = ({ {onRedo && ( )}
diff --git a/src/ConnectModal.tsx b/src/ConnectModal.tsx index e84d6ae9..19f34c41 100644 --- a/src/ConnectModal.tsx +++ b/src/ConnectModal.tsx @@ -38,7 +38,7 @@ function deviceList( async function LoadEm() { setRefreshing(true); - let entries: Array<[TransportFactory, AvailableDevice]> = []; + const entries: Array<[TransportFactory, AvailableDevice]> = []; for (const t of transports.filter((t) => t.pick_and_connect)) { const devices = await t.pick_and_connect?.list(); if (!devices) { @@ -91,7 +91,7 @@ function deviceList(
- + {all_mods.map((m) => ( {mod_labels[m]} diff --git a/src/keyboard/HidUsageLabel.tsx b/src/keyboard/HidUsageLabel.tsx index aa15195c..dbf55e3e 100644 --- a/src/keyboard/HidUsageLabel.tsx +++ b/src/keyboard/HidUsageLabel.tsx @@ -12,20 +12,20 @@ function remove_prefix(s?: string) { } export const HidUsageLabel = ({ hid_usage }: HidUsageLabelProps) => { - let [page, id] = hid_usage_page_and_id_from_usage(hid_usage); + const [page, id] = hid_usage_page_and_id_from_usage(hid_usage); // TODO: Do something with implicit mods! - page &= 0xff; + let _page = page; - let labels = hid_usage_get_labels(page, id); + const labels = hid_usage_get_labels((_page &= 0xff), id); return ( ); diff --git a/src/keyboard/Key.tsx b/src/keyboard/Key.tsx index 80babd4d..decb19c7 100644 --- a/src/keyboard/Key.tsx +++ b/src/keyboard/Key.tsx @@ -56,7 +56,7 @@ export const Key = ({ const children = Children.map(props.children, (c) => (
{c}
@@ -64,7 +64,7 @@ export const Key = ({ return (
20 ? "-md" : "" - } transition-all duration-100 m-auto p-0 b-0 box-border grid grid-rows-[0_var(--zmk-key-center-height)_0] grid-cols-[0_var(--zmk-key-center-width)_0] data-[zoomer=true]:hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] data-[zoomer=true]:hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] shadow-[0_0_0_1px_inset] shadow-base-content data-[zoomer=true]:shadow-base-200 data-[zoomer=true]:hover:shadow-base-content data-[zoomer=true]:hover:z-50 text-base-content bg-base-100 aria-selected:bg-primary aria-selected:text-primary-content grow @container`} + } b-0 m-auto box-border grid grow grid-cols-[0_var(--zmk-key-center-width)_0] grid-rows-[0_var(--zmk-key-center-height)_0] bg-base-100 p-0 text-base-content shadow-[0_0_0_1px_inset] shadow-base-content transition-all duration-100 @container aria-selected:bg-primary aria-selected:text-primary-content data-[zoomer=true]:shadow-base-200 data-[zoomer=true]:hover:z-50 data-[zoomer=true]:hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] data-[zoomer=true]:hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] data-[zoomer=true]:hover:shadow-base-content`} > {header && ( - + {header} )} diff --git a/src/keyboard/Keyboard.tsx b/src/keyboard/Keyboard.tsx index e8ffaf75..8b6fff8b 100644 --- a/src/keyboard/Keyboard.tsx +++ b/src/keyboard/Keyboard.tsx @@ -29,14 +29,18 @@ import { BehaviorBindingPicker } from "../behaviors/BehaviorBindingPicker"; import { produce } from "immer"; import { LockStateContext } from "../rpc/LockStateContext"; import { LockState } from "@zmkfirmware/zmk-studio-ts-client/core"; -import { deserializeLayoutZoom, LayoutZoom } from "./PhysicalLayout"; +import { LayoutZoom } from "./PhysicalLayout"; import { useLocalStorageState } from "../misc/useLocalStorageState"; type BehaviorMap = Record; +function deserializeLayoutZoom(value: string): LayoutZoom { + return value === "auto" ? "auto" : parseFloat(value) || "auto"; +} + function useBehaviors(): BehaviorMap { - let connection = useContext(ConnectionContext); - let lockState = useContext(LockStateContext); + const connection = useContext(ConnectionContext); + const lockState = useContext(LockStateContext); const [behaviors, setBehaviors] = useState({}); @@ -56,25 +60,25 @@ function useBehaviors(): BehaviorMap { return; } - let get_behaviors: Request = { + const get_behaviors: Request = { behaviors: { listAllBehaviors: true }, requestId: 0, }; - let behavior_list = await call_rpc(connection.conn, get_behaviors); + const behavior_list = await call_rpc(connection.conn, get_behaviors); if (!ignore) { - let behavior_map: BehaviorMap = {}; - for (let behaviorId of behavior_list.behaviors?.listAllBehaviors + const behavior_map: BehaviorMap = {}; + for (const behaviorId of behavior_list.behaviors?.listAllBehaviors ?.behaviors || []) { if (ignore) { break; } - let details_req = { + const details_req = { behaviors: { getBehaviorDetails: { behaviorId } }, requestId: 0, }; - let behavior_details = await call_rpc(connection.conn, details_req); - let dets: GetBehaviorDetailsResponse | undefined = + const behavior_details = await call_rpc(connection.conn, details_req); + const dets: GetBehaviorDetailsResponse | undefined = behavior_details?.behaviors?.getBehaviorDetails; if (dets) { @@ -103,13 +107,13 @@ function useLayouts(): [ PhysicalLayout[] | undefined, React.Dispatch>, number, - React.Dispatch> + React.Dispatch>, ] { - let connection = useContext(ConnectionContext); - let lockState = useContext(LockStateContext); + const connection = useContext(ConnectionContext); + const lockState = useContext(LockStateContext); const [layouts, setLayouts] = useState( - undefined + undefined, ); const [selectedPhysicalLayoutIndex, setSelectedPhysicalLayoutIndex] = useState(0); @@ -130,14 +134,14 @@ function useLayouts(): [ return; } - let response = await call_rpc(connection.conn, { + const response = await call_rpc(connection.conn, { keymap: { getPhysicalLayouts: true }, }); if (!ignore) { setLayouts(response?.keymap?.getPhysicalLayouts?.layouts); setSelectedPhysicalLayoutIndex( - response?.keymap?.getPhysicalLayouts?.activeLayoutIndex || 0 + response?.keymap?.getPhysicalLayouts?.activeLayoutIndex || 0, ); } } @@ -171,12 +175,16 @@ export default function Keyboard() { console.log("Got the keymap!"); return keymap?.keymap?.getKeymap; }, - true + true, ); - const [keymapScale, setKeymapScale] = useLocalStorageState("keymapScale", "auto", { - deserialize: deserializeLayoutZoom, - }); + const [keymapScale, setKeymapScale] = useLocalStorageState( + "keymapScale", + "auto", + { + deserialize: deserializeLayoutZoom, + }, + ); const [selectedLayerIndex, setSelectedLayerIndex] = useState(0); const [selectedKeyPosition, setSelectedKeyPosition] = useState< @@ -198,27 +206,27 @@ export default function Keyboard() { return; } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { keymap: { setActivePhysicalLayout: selectedPhysicalLayoutIndex }, }); - let new_keymap = resp?.keymap?.setActivePhysicalLayout?.ok; + const new_keymap = resp?.keymap?.setActivePhysicalLayout?.ok; if (new_keymap) { setKeymap(new_keymap); } else { console.error( "Failed to set the active physical layout err:", - resp?.keymap?.setActivePhysicalLayout?.err + resp?.keymap?.setActivePhysicalLayout?.err, ); } } performSetRequest(); - }, [selectedPhysicalLayoutIndex]); + }, [conn.conn, layouts, selectedPhysicalLayoutIndex, setKeymap]); - let doSelectPhysicalLayout = useCallback( + const doSelectPhysicalLayout = useCallback( (i: number) => { - let oldLayout = selectedPhysicalLayoutIndex; + const oldLayout = selectedPhysicalLayoutIndex; undoRedo?.(async () => { setSelectedPhysicalLayoutIndex(i); @@ -227,14 +235,14 @@ export default function Keyboard() { }; }); }, - [undoRedo, selectedPhysicalLayoutIndex] + [selectedPhysicalLayoutIndex, undoRedo, setSelectedPhysicalLayoutIndex], ); - let doUpdateBinding = useCallback( + const doUpdateBinding = useCallback( (binding: BehaviorBinding) => { if (!keymap || selectedKeyPosition === undefined) { console.error( - "Can't update binding without a selected key position and loaded keymap" + "Can't update binding without a selected key position and loaded keymap", ); return; } @@ -248,7 +256,7 @@ export default function Keyboard() { throw new Error("Not connected"); } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { keymap: { setLayerBinding: { layerId, keyPosition, binding } }, }); @@ -257,9 +265,10 @@ export default function Keyboard() { SetLayerBindingResponse.SET_LAYER_BINDING_RESP_OK ) { setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers[layer].bindings[keyPosition] = binding; - }) + }), ); } else { console.error("Failed to set binding", resp.keymap?.setLayerBinding); @@ -270,7 +279,7 @@ export default function Keyboard() { return; } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { keymap: { setLayerBinding: { layerId, keyPosition, binding: oldBinding }, }, @@ -280,19 +289,26 @@ export default function Keyboard() { SetLayerBindingResponse.SET_LAYER_BINDING_RESP_OK ) { setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers[layer].bindings[keyPosition] = oldBinding; - }) + }), ); - } else { } }; }); }, - [conn, keymap, undoRedo, selectedLayerIndex, selectedKeyPosition] + [ + keymap, + selectedKeyPosition, + selectedLayerIndex, + undoRedo, + conn.conn, + setKeymap, + ], ); - let selectedBinding = useMemo(() => { + const selectedBinding = useMemo(() => { if (keymap == null || selectedKeyPosition == null) { return null; } @@ -307,7 +323,7 @@ export default function Keyboard() { return; } - let resp = await call_rpc(conn.conn, { + const resp = await call_rpc(conn.conn, { keymap: { moveLayer: { startIndex, destIndex } }, }); @@ -324,7 +340,7 @@ export default function Keyboard() { return () => doMove(end, start); }); }, - [undoRedo] + [conn.conn, setKeymap, undoRedo], ); const addLayer = useCallback(() => { @@ -338,10 +354,11 @@ export default function Keyboard() { if (resp.keymap?.addLayer?.ok) { const newSelection = keymap.layers.length; setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers.push(resp.keymap!.addLayer!.ok!.layer); draft.availableLayers--; - }) + }), ); setSelectedLayerIndex(newSelection); @@ -365,24 +382,25 @@ export default function Keyboard() { console.log(resp); if (resp.keymap?.removeLayer?.ok) { setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers.splice(layerIndex, 1); draft.availableLayers++; - }) + }), ); } else { console.error("Remove error", resp.keymap?.removeLayer?.err); throw new Error( - "Failed to remove layer:" + resp.keymap?.removeLayer?.err + "Failed to remove layer:" + resp.keymap?.removeLayer?.err, ); } } undoRedo?.(async () => { - let index = await doAdd(); + const index = await doAdd(); return () => doRemove(index); }); - }, [conn, undoRedo, keymap]); + }, [undoRedo, conn.conn, keymap, setKeymap]); const removeLayer = useCallback(() => { async function doRemove(layerIndex: number): Promise { @@ -399,15 +417,16 @@ export default function Keyboard() { setSelectedLayerIndex(layerIndex - 1); } setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers.splice(layerIndex, 1); draft.availableLayers++; - }) + }), ); } else { console.error("Remove error", resp.keymap?.removeLayer?.err); throw new Error( - "Failed to remove layer:" + resp.keymap?.removeLayer?.err + "Failed to remove layer:" + resp.keymap?.removeLayer?.err, ); } } @@ -424,16 +443,17 @@ export default function Keyboard() { console.log(resp); if (resp.keymap?.restoreLayer?.ok) { setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { draft.layers.splice(atIndex, 0, resp!.keymap!.restoreLayer!.ok); draft.availableLayers--; - }) + }), ); setSelectedLayerIndex(atIndex); } else { console.error("Remove error", resp.keymap?.restoreLayer?.err); throw new Error( - "Failed to restore layer:" + resp.keymap?.restoreLayer?.err + "Failed to restore layer:" + resp.keymap?.restoreLayer?.err, ); } } @@ -442,13 +462,13 @@ export default function Keyboard() { throw new Error("No keymap loaded"); } - let index = selectedLayerIndex; - let layerId = keymap.layers[index].id; + const index = selectedLayerIndex; + const layerId = keymap.layers[index].id; undoRedo?.(async () => { await doRemove(index); return () => doRestore(layerId, index); }); - }, [conn, undoRedo, selectedLayerIndex]); + }, [keymap, selectedLayerIndex, undoRedo, conn.conn, setKeymap]); const changeLayerName = useCallback( (id: number, oldName: string, newName: string) => { @@ -466,16 +486,17 @@ export default function Keyboard() { SetLayerPropsResponse.SET_LAYER_PROPS_RESP_OK ) { setKeymap( + // eslint-disable-next-line @typescript-eslint/no-explicit-any produce((draft: any) => { const layer_index = draft.layers.findIndex( - (l: Layer) => l.id == layerId + (l: Layer) => l.id == layerId, ); draft.layers[layer_index].name = name; - }) + }), ); } else { throw new Error( - "Failed to change layer name:" + resp.keymap?.setLayerProps + "Failed to change layer name:" + resp.keymap?.setLayerProps, ); } } @@ -487,12 +508,12 @@ export default function Keyboard() { }; }); }, - [conn, undoRedo, keymap] + [undoRedo, conn.conn, setKeymap], ); return ( -
-
+
+
{layouts && (
{layouts && keymap && behaviors && ( -
+
- - + {(l) => ( {l.name} -
+
{children} - + ); }; diff --git a/src/misc/LicenseNoticeModal.tsx b/src/misc/LicenseNoticeModal.tsx index 62500a65..cd4f79d2 100644 --- a/src/misc/LicenseNoticeModal.tsx +++ b/src/misc/LicenseNoticeModal.tsx @@ -17,24 +17,24 @@ export const LicenseNoticeModal = ({ return (
-
+

ZMK Studio is released under the open source Apache 2.0 license. A copy of the NOTICE file from the ZMK Studio repository is included here:

-
{NOTICE}
+
{NOTICE}
); diff --git a/src/misc/Tooltip.tsx b/src/misc/Tooltip.tsx index 5839383d..889e71b5 100644 --- a/src/misc/Tooltip.tsx +++ b/src/misc/Tooltip.tsx @@ -9,7 +9,7 @@ export const Tooltip = ({ children, label }: TooltipProps) => { return ( {children} - + {label} diff --git a/src/misc/useModalRef.ts b/src/misc/useModalRef.ts index 30205cd4..eb147a83 100644 --- a/src/misc/useModalRef.ts +++ b/src/misc/useModalRef.ts @@ -3,11 +3,11 @@ import { MutableRefObject, useEffect, useRef } from "react"; export function useModalRef( open: boolean, closeOnOutsideClick?: boolean, - allowCancel?: boolean + allowCancel?: boolean, ): MutableRefObject { const ref = useRef(null); - let reopen = async () => { + const reopen = async () => { // We do this in a timeout so it runs after the modal has actually closed. setTimeout(() => ref.current?.showModal()); }; @@ -46,7 +46,7 @@ export function useModalRef( ref.current?.close(); ref.current?.removeEventListener("cancel", reopen); } - }, [open, closeOnOutsideClick]); + }, [open, allowCancel, closeOnOutsideClick]); return ref; } diff --git a/src/rpc/useConnectedDeviceData.ts b/src/rpc/useConnectedDeviceData.ts index b64e41d5..a756d872 100644 --- a/src/rpc/useConnectedDeviceData.ts +++ b/src/rpc/useConnectedDeviceData.ts @@ -10,11 +10,11 @@ import { LockState } from "@zmkfirmware/zmk-studio-ts-client/core"; export function useConnectedDeviceData( req: Omit, response_mapper: (resp: RequestResponse) => T | undefined, - requireUnlock?: boolean + requireUnlock?: boolean, ): [T | undefined, React.Dispatch>] { - let connection = useContext(ConnectionContext); - let lockState = useContext(LockStateContext); - let [data, setData] = useState(undefined); + const connection = useContext(ConnectionContext); + const lockState = useContext(LockStateContext); + const [data, setData] = useState(undefined); useEffect( () => { @@ -33,7 +33,7 @@ export function useConnectedDeviceData( return; } - let response = response_mapper(await call_rpc(connection.conn, req)); + const response = response_mapper(await call_rpc(connection.conn, req)); if (!ignore) { setData(response); @@ -47,9 +47,10 @@ export function useConnectedDeviceData( ignore = true; }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps requireUnlock ? [connection, requireUnlock, lockState] - : [connection, requireUnlock] + : [connection, requireUnlock], ); return [data, setData]; diff --git a/src/tauri/ble.ts b/src/tauri/ble.ts index 90ca63ea..c711a675 100644 --- a/src/tauri/ble.ts +++ b/src/tauri/ble.ts @@ -13,37 +13,37 @@ export async function connect(dev: AvailableDevice): Promise { throw new Error("Failed to connect"); } - let abortController = new AbortController(); + const abortController = new AbortController(); - let writable = new WritableStream({ - async write(chunk, _controller) { + const writable = new WritableStream({ + async write(chunk, _) { await invoke("transport_send_data", new Uint8Array(chunk)); }, }); - let { writable: response_writable, readable } = new TransformStream(); + const { writable: response_writable, readable } = new TransformStream(); const unlisten_data = await listen( "connection_data", async (event: { payload: Array }) => { - let writer = response_writable.getWriter(); + const writer = response_writable.getWriter(); await writer.write(new Uint8Array(event.payload)); writer.releaseLock(); - } + }, ); const unlisten_disconnected = await listen( "connection_disconnected", - async (_ev: any) => { + async (_: unknown) => { unlisten_data(); unlisten_disconnected(); response_writable.close(); - } + }, ); - let signal = abortController.signal; + const signal = abortController.signal; - let abort_cb = async (_reason: any) => { + const abort_cb = async (_: unknown) => { unlisten_data(); unlisten_disconnected(); await invoke("transport_close"); diff --git a/src/tauri/serial.ts b/src/tauri/serial.ts index 806049d6..e24239f1 100644 --- a/src/tauri/serial.ts +++ b/src/tauri/serial.ts @@ -13,37 +13,37 @@ export async function connect(dev: AvailableDevice): Promise { throw new Error("Failed to connect"); } - let abortController = new AbortController(); + const abortController = new AbortController(); - let writable = new WritableStream({ - async write(chunk, _controller) { + const writable = new WritableStream({ + async write(chunk, _) { await invoke("transport_send_data", new Uint8Array(chunk)); }, }); - let { writable: response_writable, readable } = new TransformStream(); + const { writable: response_writable, readable } = new TransformStream(); const unlisten_data = await listen( "connection_data", async (event: { payload: Array }) => { - let writer = response_writable.getWriter(); + const writer = response_writable.getWriter(); await writer.write(new Uint8Array(event.payload)); writer.releaseLock(); - } + }, ); const unlisten_disconnected = await listen( "connection_disconnected", - async (_ev: any) => { + async (_ev: unknown) => { unlisten_data(); unlisten_disconnected(); response_writable.close(); - } + }, ); - let signal = abortController.signal; + const signal = abortController.signal; - let abort_cb = async (_reason: any) => { + const abort_cb = async (_: unknown) => { unlisten_data(); unlisten_disconnected(); await invoke("transport_close"); diff --git a/src/undoRedo.ts b/src/undoRedo.ts index 5690830c..8e139120 100644 --- a/src/undoRedo.ts +++ b/src/undoRedo.ts @@ -29,7 +29,7 @@ export function useUndoRedo(): [ const doIt = async (doCb: DoCallback, preserveRedo?: boolean) => { setLocked(true); - let undo = await doCb(); + const undo = await doCb(); setUndoStack([[doCb, undo], ...undoStack]); if (!preserveRedo) { @@ -48,7 +48,7 @@ export function useUndoRedo(): [ } setLocked(true); - let [doCb, undoCb] = undoStack[0]; + const [doCb, undoCb] = undoStack[0]; setUndoStack(undoStack.slice(1)); setRedoStack([doCb, ...redoStack]); @@ -66,7 +66,7 @@ export function useUndoRedo(): [ throw new Error("redo invoked with no operations to redo"); } - let doCb = redoStack[0]; + const doCb = redoStack[0]; setRedoStack(redoStack.slice(1)); diff --git a/src/usePubSub.ts b/src/usePubSub.ts index fa2bfe42..251b7739 100644 --- a/src/usePubSub.ts +++ b/src/usePubSub.ts @@ -3,12 +3,14 @@ import { useEffect } from "react"; const emitter = new Emittery(); +// eslint-disable-next-line @typescript-eslint/no-explicit-any export const usePub = () => (name: PropertyKey, data: any) => emitter.emit(name, data); export const useSub = ( name: PropertyKey, - callback: (data: any) => void | Promise + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback: (data: any) => void | Promise, ) => { const unsub = () => emitter.off(name, callback); From c5d9fc69382754232d832c94a01858adbbca70d9 Mon Sep 17 00:00:00 2001 From: Pongstr Date: Sat, 21 Dec 2024 12:49:57 +0200 Subject: [PATCH 2/5] chore(fix-lint): small refactor for `usePubSub` - fixed: React Hook "usePub" is called in function "listen_for_notifications" - `usePub` is no longer neccessary, calling `emitter.emit` is okay - `useSub` added generic typing, small refactor - fixed: updated components that utilizes `usePub` + `useSub` --- src/App.tsx | 44 +++++++++--------- src/AppHeader.tsx | 4 +- src/ConnectModal.tsx | 103 +++++++++++++++++++++++-------------------- src/usePubSub.ts | 22 +++------ 4 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index fa7af5dd..c5b96b38 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -21,7 +21,7 @@ import { } from "./tauri/serial"; import Keyboard from "./keyboard/Keyboard"; import { UndoRedoContext, useUndoRedo } from "./undoRedo"; -import { usePub, useSub } from "./usePubSub"; +import { emitter, useSub } from "./usePubSub"; import { LockState } from "@zmkfirmware/zmk-studio-ts-client/core"; import { LockStateContext } from "./rpc/LockStateContext"; import { UnlockModal } from "./UnlockModal"; @@ -77,8 +77,6 @@ async function listen_for_notifications( }; signal.addEventListener("abort", onAbort, { once: true }); do { - const pub = usePub(); - try { const { done, value } = await reader.read(); if (done) { @@ -90,7 +88,7 @@ async function listen_for_notifications( } console.log("Notification", value); - pub("rpc_notification", value); + await emitter.emit("rpc_notification", value); const subsystem = Object.entries(value).find( ([_k, v]) => v !== undefined, @@ -109,17 +107,18 @@ async function listen_for_notifications( const [eventName, eventData] = event; const topic = ["rpc_notification", subId, eventName].join("."); - pub(topic, eventData); + await emitter.emit(topic, eventData); } catch (e) { signal.removeEventListener("abort", onAbort); reader.releaseLock(); throw e; } + // eslint-disable-next-line no-constant-condition } while (true); signal.removeEventListener("abort", onAbort); reader.releaseLock(); - notification_stream.cancel(); + await notification_stream.cancel(); } async function connect( @@ -128,7 +127,7 @@ async function connect( setConnectedDeviceName: Dispatch, signal: AbortSignal, ) { - const conn = await create_rpc_connection(transport, { signal }); + const conn = create_rpc_connection(transport, { signal }); const details = await Promise.race([ call_rpc(conn, { core: { getDeviceInfo: true } }) @@ -174,9 +173,10 @@ function App() { LockState.ZMK_STUDIO_CORE_LOCK_STATE_LOCKED, ); - useSub("rpc_notification.core.lockStateChanged", (ls: unknown) => { - setLockState(ls as LockState); - }); + useSub( + "rpc_notification.core.lockStateChanged", + (ls) => void setLockState(ls), + ); useEffect(() => { if (!conn) { @@ -199,8 +199,8 @@ function App() { ); } - updateLockState(); - }, [conn, setLockState]); + updateLockState().then(console.info).catch(console.error); + }, [conn, reset, setLockState]); const save = useCallback(() => { async function doSave() { @@ -214,7 +214,7 @@ function App() { } } - doSave(); + doSave().then(console.info).catch(console.error); }, [conn]); const discard = useCallback(() => { @@ -234,8 +234,8 @@ function App() { setConn({ conn: conn.conn }); } - doDiscard(); - }, [conn]); + doDiscard().then(console.info).catch(console.error); + }, [conn.conn, reset]); const resetSettings = useCallback(() => { async function doReset() { @@ -254,8 +254,8 @@ function App() { setConn({ conn: conn.conn }); } - doReset(); - }, [conn]); + doReset().then(console.info).catch(console.error); + }, [conn.conn, reset]); const disconnect = useCallback(() => { async function doDisconnect() { @@ -268,16 +268,18 @@ function App() { setConnectionAbort(new AbortController()); } - doDisconnect(); - }, [conn]); + doDisconnect().then(console.info).catch(console.error); + }, [conn.conn, connectionAbort]); const onConnect = useCallback( (t: RpcTransport) => { const ac = new AbortController(); setConnectionAbort(ac); - connect(t, setConn, setConnectedDeviceName, ac.signal); + connect(t, setConn, setConnectedDeviceName, ac.signal) + .then(console.info) + .catch(console.error); }, - [setConn, setConnectedDeviceName, setConnectedDeviceName], + [setConn, setConnectedDeviceName], ); return ( diff --git a/src/AppHeader.tsx b/src/AppHeader.tsx index 5a5dc3fe..8b34f906 100644 --- a/src/AppHeader.tsx +++ b/src/AppHeader.tsx @@ -60,9 +60,9 @@ export const AppHeader = ({ (r) => r.keymap?.checkUnsavedChanges, ); - useSub( + useSub( "rpc_notification.keymap.unsavedChangesStatusChanged", - (unsaved: boolean) => setUnsaved(unsaved), + (unsaved) => void setUnsaved(unsaved), ); return ( diff --git a/src/ConnectModal.tsx b/src/ConnectModal.tsx index 19f34c41..333b5bbe 100644 --- a/src/ConnectModal.tsx +++ b/src/ConnectModal.tsx @@ -25,10 +25,10 @@ export interface ConnectModalProps { onTransportCreated: (t: RpcTransport) => void; } -function deviceList( +function useDeviceList( open: boolean, transports: TransportFactory[], - onTransportCreated: (t: RpcTransport) => void + onTransportCreated: (t: RpcTransport) => void, ) { const [devices, setDevices] = useState< Array<[TransportFactory, AvailableDevice]> @@ -36,7 +36,7 @@ function deviceList( const [selectedDev, setSelectedDev] = useState(new Set()); const [refreshing, setRefreshing] = useState(false); - async function LoadEm() { + const LoadEm = useCallback(async () => { setRefreshing(true); const entries: Array<[TransportFactory, AvailableDevice]> = []; for (const t of transports.filter((t) => t.pick_and_connect)) { @@ -48,27 +48,27 @@ function deviceList( entries.push( ...devices.map<[TransportFactory, AvailableDevice]>((d) => { return [t, d]; - }) + }), ); } setDevices(entries); setRefreshing(false); - } + }, [transports]); useEffect(() => { setSelectedDev(new Set()); setDevices([]); - LoadEm(); - }, [transports, open, setDevices]); + LoadEm().then(console.info).catch(console.error); + }, [transports, open, setDevices, LoadEm]); const onRefresh = useCallback(() => { setSelectedDev(new Set()); setDevices([]); - LoadEm(); - }, [setDevices]); + LoadEm().then(console.info).catch(console.error); + }, [LoadEm]); const onSelect = useCallback( async (keys: Selection) => { @@ -83,7 +83,7 @@ function deviceList( .catch((e) => alert(e)); } }, - [devices, onTransportCreated] + [devices, onTransportCreated], ); return ( @@ -127,9 +127,9 @@ function deviceList( ); } -function simpleDevicePicker( +function useSimpleDevicePicker( transports: TransportFactory[], - onTransportCreated: (t: RpcTransport) => void + onTransportCreated: (t: RpcTransport) => void, ) { const [availableDevices, setAvailableDevices] = useState< AvailableDevice[] | undefined @@ -146,45 +146,45 @@ function simpleDevicePicker( let ignore = false; - if (selectedTransport.connect) { - async function connectTransport() { - try { - const transport = await selectedTransport?.connect?.(); - - if (!ignore) { - if (transport) { - onTransportCreated(transport); - } - setSelectedTransport(undefined); + async function connectTransport() { + try { + const transport = await selectedTransport?.connect?.(); + + if (!ignore) { + if (transport) { + onTransportCreated(transport); } - } catch (e) { - if (!ignore) { - console.error(e); - if (e instanceof Error && !(e instanceof UserCancelledError)) { - alert(e.message); - } - setSelectedTransport(undefined); + setSelectedTransport(undefined); + } + } catch (e) { + if (!ignore) { + console.error(e); + if (e instanceof Error && !(e instanceof UserCancelledError)) { + alert(e.message); } + setSelectedTransport(undefined); } } + } - connectTransport(); - } else { - async function loadAvailableDevices() { - const devices = await selectedTransport?.pick_and_connect?.list(); + async function loadAvailableDevices() { + const devices = await selectedTransport?.pick_and_connect?.list(); - if (!ignore) { - setAvailableDevices(devices); - } + if (!ignore) { + setAvailableDevices(devices); } + } - loadAvailableDevices(); + if (selectedTransport.connect) { + connectTransport().then(console.info).catch(console.error); + return; } + loadAvailableDevices().then(console.info).catch(console.error); return () => { ignore = true; }; - }, [selectedTransport]); + }, [onTransportCreated, selectedTransport]); const connections = transports.map((t) => (
  • @@ -197,6 +197,7 @@ function simpleDevicePicker(
  • )); + return (

    Select a connection type.

    @@ -209,7 +210,7 @@ function simpleDevicePicker( className="m-1 p-1" onClick={async () => { onTransportCreated( - await selectedTransport!.pick_and_connect!.connect(d) + await selectedTransport!.pick_and_connect!.connect(d), ); setSelectedTransport(undefined); }} @@ -258,19 +259,24 @@ function noTransportsOptionsPrompt() { ); } -function connectOptions( +function useConnectOptions( transports: TransportFactory[], onTransportCreated: (t: RpcTransport) => void, - open?: boolean + open?: boolean, ) { const useSimplePicker = useMemo( () => transports.every((t) => !t.pick_and_connect), - [transports] + [transports], + ); + + const devicePicker = useSimpleDevicePicker(transports, onTransportCreated); + const deviceList = useDeviceList( + open || false, + transports, + onTransportCreated, ); - return useSimplePicker - ? simpleDevicePicker(transports, onTransportCreated) - : deviceList(open || false, transports, onTransportCreated); + return useSimplePicker ? devicePicker : deviceList; } export const ConnectModal = ({ @@ -282,12 +288,13 @@ export const ConnectModal = ({ const haveTransports = useMemo(() => transports.length > 0, [transports]); + const connectOpts = useConnectOptions(transports, onTransportCreated, open); + const noTransportOpts = noTransportsOptionsPrompt(); + return (

    Welcome to ZMK Studio

    - {haveTransports - ? connectOptions(transports, onTransportCreated, open) - : noTransportsOptionsPrompt()} + {haveTransports ? connectOpts : noTransportOpts}
    ); }; diff --git a/src/usePubSub.ts b/src/usePubSub.ts index 251b7739..4c135917 100644 --- a/src/usePubSub.ts +++ b/src/usePubSub.ts @@ -1,24 +1,16 @@ import Emittery from "emittery"; import { useEffect } from "react"; -const emitter = new Emittery(); +export const emitter = new Emittery(); -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const usePub = () => (name: PropertyKey, data: any) => - emitter.emit(name, data); - -export const useSub = ( +export const useSub = ( name: PropertyKey, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - callback: (data: any) => void | Promise, + callback: (data: T) => void | Promise, ) => { - const unsub = () => emitter.off(name, callback); - - // Be sure we unsub if unmounted. useEffect(() => { emitter.on(name, callback); - return () => unsub(); - }); - - return unsub; + return () => { + emitter.off(name, callback); + }; + }, [name, callback]); }; From ff4a505f097db2d53260996349be96e064a50cbb Mon Sep 17 00:00:00 2001 From: Pongstr Date: Sat, 21 Dec 2024 12:55:46 +0200 Subject: [PATCH 3/5] chore(fix-lint): list should have unique "key" prop --- src/behaviors/ParameterValuePicker.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/behaviors/ParameterValuePicker.tsx b/src/behaviors/ParameterValuePicker.tsx index ca0aaae4..f5c626e8 100644 --- a/src/behaviors/ParameterValuePicker.tsx +++ b/src/behaviors/ParameterValuePicker.tsx @@ -24,8 +24,10 @@ export const ParameterValuePicker = ({ className="h-8 rounded" onChange={(e) => onValueChanged(parseInt(e.target.value))} > - {values.map((v) => ( - + {values.map((v, i) => ( + ))}
    @@ -66,7 +68,9 @@ export const ParameterValuePicker = ({ onChange={(e) => onValueChanged(parseInt(e.target.value))} > {layers.map(({ name, id }) => ( - + ))}
    From 1097c909d78d4dc7cbe83632970a7c88c92448dd Mon Sep 17 00:00:00 2001 From: Pongstr Date: Sat, 21 Dec 2024 22:45:11 +0200 Subject: [PATCH 4/5] chore(fix-lint): refactor connect modal small refactor to adhere to rules of hooks. --- src/ConnectModal.tsx | 63 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/ConnectModal.tsx b/src/ConnectModal.tsx index 333b5bbe..96c6aa3f 100644 --- a/src/ConnectModal.tsx +++ b/src/ConnectModal.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { FC, useCallback, useEffect, useMemo, useState } from "react"; import type { RpcTransport } from "@zmkfirmware/zmk-studio-ts-client/transport/index"; import { UserCancelledError } from "@zmkfirmware/zmk-studio-ts-client/transport/errors"; @@ -25,11 +25,11 @@ export interface ConnectModalProps { onTransportCreated: (t: RpcTransport) => void; } -function useDeviceList( - open: boolean, - transports: TransportFactory[], - onTransportCreated: (t: RpcTransport) => void, -) { +const DeviceList: FC = ({ + open, + transports, + onTransportCreated, +}) => { const [devices, setDevices] = useState< Array<[TransportFactory, AvailableDevice]> >([]); @@ -125,12 +125,12 @@ function useDeviceList(
    ); -} +}; -function useSimpleDevicePicker( - transports: TransportFactory[], - onTransportCreated: (t: RpcTransport) => void, -) { +const SimpleDevicePicker: FC> = ({ + transports, + onTransportCreated, +}) => { const [availableDevices, setAvailableDevices] = useState< AvailableDevice[] | undefined >(undefined); @@ -222,9 +222,9 @@ function useSimpleDevicePicker( )}
    ); -} +}; -function noTransportsOptionsPrompt() { +const NoTransportsOptionsPrompt: FC = () => { return (

    @@ -257,27 +257,24 @@ function noTransportsOptionsPrompt() {

    ); -} +}; -function useConnectOptions( - transports: TransportFactory[], - onTransportCreated: (t: RpcTransport) => void, - open?: boolean, -) { - const useSimplePicker = useMemo( +const ConnectOptions: FC = ({ + open, + transports, + onTransportCreated, +}) => { + const simpleMode = useMemo( () => transports.every((t) => !t.pick_and_connect), [transports], ); - const devicePicker = useSimpleDevicePicker(transports, onTransportCreated); - const deviceList = useDeviceList( - open || false, - transports, - onTransportCreated, - ); + if (simpleMode) { + return ; + } - return useSimplePicker ? devicePicker : deviceList; -} + return ; +}; export const ConnectModal = ({ open, @@ -285,16 +282,16 @@ export const ConnectModal = ({ onTransportCreated, }: ConnectModalProps) => { const dialog = useModalRef(open || false, false, false); - const haveTransports = useMemo(() => transports.length > 0, [transports]); - const connectOpts = useConnectOptions(transports, onTransportCreated, open); - const noTransportOpts = noTransportsOptionsPrompt(); - return (

    Welcome to ZMK Studio

    - {haveTransports ? connectOpts : noTransportOpts} + {haveTransports ? ( + + ) : ( + + )}
    ); }; From 5386a8d4dc480ba16641090529142d5372f54635 Mon Sep 17 00:00:00 2001 From: Pongstr Date: Mon, 23 Dec 2024 21:06:42 +0200 Subject: [PATCH 5/5] chore(fix-lint): enable tw no-custom-classname --- .eslintrc.cjs | 1 - src/keyboard/Key.tsx | 13 +++++++------ src/keyboard/LayerPicker.tsx | 12 ++++++------ src/misc/LicenseNoticeModal.tsx | 8 ++------ tailwind.config.js | 5 +---- 5 files changed, 16 insertions(+), 23 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d2b2b15d..a12d8f7e 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -12,7 +12,6 @@ module.exports = { parser: "@typescript-eslint/parser", plugins: ["react-refresh"], rules: { - "tailwindcss/no-custom-classname": "off", "@typescript-eslint/no-unused-vars": [ "error", { diff --git a/src/keyboard/Key.tsx b/src/keyboard/Key.tsx index decb19c7..94656997 100644 --- a/src/keyboard/Key.tsx +++ b/src/keyboard/Key.tsx @@ -33,7 +33,7 @@ interface KeyDimension { function makeSize( { width, height }: KeyDimension, - oneU: number + oneU: number, ): CSSProperties { width *= oneU; height *= oneU; @@ -64,7 +64,7 @@ export const Key = ({ return (
    20 ? "-md" : "" - } b-0 m-auto box-border grid grow grid-cols-[0_var(--zmk-key-center-width)_0] grid-rows-[0_var(--zmk-key-center-height)_0] bg-base-100 p-0 text-base-content shadow-[0_0_0_1px_inset] shadow-base-content transition-all duration-100 @container aria-selected:bg-primary aria-selected:text-primary-content data-[zoomer=true]:shadow-base-200 data-[zoomer=true]:hover:z-50 data-[zoomer=true]:hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] data-[zoomer=true]:hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] data-[zoomer=true]:hover:shadow-base-content`} + className={[ + oneU > 20 ? "rounded-md" : "rounded", + "m-auto box-border grid grow grid-cols-[0_var(--zmk-key-center-width)_0] grid-rows-[0_var(--zmk-key-center-height)_0] bg-base-100 p-0 text-base-content shadow-[0_0_0_1px_inset] shadow-base-content transition-all duration-100 @container aria-selected:bg-primary aria-selected:text-primary-content data-[zoomer=true]:shadow-base-200 data-[zoomer=true]:hover:z-50 data-[zoomer=true]:hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] data-[zoomer=true]:hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] data-[zoomer=true]:hover:shadow-base-content", + ].join(" ")} > {header && ( - + {header} )} diff --git a/src/keyboard/LayerPicker.tsx b/src/keyboard/LayerPicker.tsx index 4f000158..df7da7df 100644 --- a/src/keyboard/LayerPicker.tsx +++ b/src/keyboard/LayerPicker.tsx @@ -32,7 +32,7 @@ interface LayerPickerProps { onLayerNameChanged?: ( id: number, oldName: string, - newName: string + newName: string, ) => void | Promise; } @@ -53,7 +53,7 @@ const EditLabelModal = ({ handleSaveNewLabel: ( id: number, oldName: string, - newName: string | null + newName: string | null, ) => void; }) => { const ref = useModalRef(open); @@ -115,7 +115,7 @@ export const LayerPicker = ({ ...props }: LayerPickerProps) => { const [editLabelData, setEditLabelData] = useState( - null + null, ); const layer_items = useMemo(() => { @@ -135,7 +135,7 @@ export const LayerPicker = ({ onLayerClicked?.(layer_items.findIndex((l) => s.has(l.id))); }, - [onLayerClicked, layer_items] + [onLayerClicked, layer_items], ); const { dragAndDropHooks } = useDragAndDrop({ @@ -162,7 +162,7 @@ export const LayerPicker = ({ onLayerNameChanged?.(id, oldName, newName); } }, - [onLayerNameChanged] + [onLayerNameChanged], ); return ( @@ -216,7 +216,7 @@ export const LayerPicker = ({ {(layer_item) => ( {layer_item.name} +

    @@ -34,7 +30,7 @@ export const LicenseNoticeModal = ({ Close

    -
    {NOTICE}
    +
    {NOTICE}
    ); diff --git a/tailwind.config.js b/tailwind.config.js index 2f14d267..27b2d3a3 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -8,6 +8,7 @@ export default { extend: { fontFamily: { sans: ["Inter", "system-ui"], + keycap: ["Inter", "system-ui"], }, colors: { primary: @@ -24,10 +25,6 @@ export default { "base-300": "light-dark(#E5E6E6, #15191e)", }, }, - - fontFamily: { - keycap: ["Inter", "system-ui"], - }, }, plugins: [contQueries, trac({ prefix: "rac" })], };