From 0c8fa3a2a270747f3dbb54fe8792f3f0aec997e3 Mon Sep 17 00:00:00 2001
From: Ryan Schanzenbacher <ryan@rschanz.org>
Date: Mon, 3 Aug 2026 01:22:44 -0400
Subject: Initial commit: combined darwin + guix-linux home-manager flake

Supersedes nix-dotfiles (darwin) and guix-dotfiles' ad-hoc
nix-home-manager flake (linux). See README.md/MIGRATION.md.
---
 .../lib/components/data/keyboard.jsx               | 108 +++++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100755 users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx

(limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx')

diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx
new file mode 100755
index 0000000..d6e04f2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx
@@ -0,0 +1,108 @@
+import * as Uebersicht from "uebersicht";
+import * as DataWidget from "./data-widget.jsx";
+import * as DataWidgetLoader from "./data-widget-loader.jsx";
+import * as Icons from "../icons/icons.jsx";
+import useWidgetRefresh from "../../hooks/use-widget-refresh";
+import useServerSocket from "../../hooks/use-server-socket";
+import { useSimpleBarContext } from "../simple-bar-context.jsx";
+import * as Utils from "../../utils";
+
+export { keyboardStyles as styles } from "../../styles/components/data/keyboard";
+
+const { React } = Uebersicht;
+
+const DEFAULT_REFRESH_FREQUENCY = 20000;
+
+/**
+ * Keyboard widget component.
+ * @returns {JSX.Element|null} The rendered widget or null if not visible.
+ */
+export const Widget = React.memo(() => {
+  const { displayIndex, settings } = useSimpleBarContext();
+  const { widgets, keyboardWidgetOptions } = settings;
+  const { keyboardWidget } = widgets;
+  const { refreshFrequency, showOnDisplay, showIcon, keyboardMaxLength } =
+    keyboardWidgetOptions;
+
+  // Determine the refresh frequency for the widget
+  const refresh = React.useMemo(
+    () =>
+      Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
+    [refreshFrequency],
+  );
+
+  // Determine if the widget should be visible based on display settings
+  const visible =
+    Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && keyboardWidget;
+
+  const [state, setState] = React.useState();
+  const [loading, setLoading] = React.useState(visible);
+
+  /**
+   * Resets the widget state.
+   */
+  const resetWidget = () => {
+    setState(undefined);
+    setLoading(false);
+  };
+
+  /**
+   * Fetches the current keyboard layout or input mode.
+   */
+  const getKeyboard = React.useCallback(async () => {
+    if (!visible) return;
+    const keyboard = await Utils.cachedRun(
+      `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | awk '/KeyboardLayout Name/ {$1=$2=$3=""; print $0}'`,
+      refresh,
+    );
+    const layout = Utils.cleanupOutput(keyboard)
+      .replace(";", "")
+      .replaceAll('"', "");
+    if (layout.length) {
+      setState({ keyboard: layout });
+      setLoading(false);
+      return;
+    }
+
+    const inputMode = await Utils.cachedRun(
+      `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | awk '/"Input Mode" =/ {$1=$2=$3=""; print $0}'`,
+      refresh,
+    );
+    const cleanedInputMode = Utils.cleanupOutput(inputMode)
+      .replace(/"com.apple.inputmethod.(.*)"/, "$1")
+      .replace(";", "");
+
+    if (!cleanedInputMode.length) return setLoading(false);
+
+    const splitedInputMode = cleanedInputMode.split(".");
+    const inputModeName = splitedInputMode[splitedInputMode.length - 1];
+    setState({ keyboard: inputModeName });
+    setLoading(false);
+  }, [visible, refresh]);
+
+  // Use server socket to listen for keyboard events
+  useServerSocket("keyboard", visible, getKeyboard, resetWidget, setLoading);
+  // Refresh the widget at the specified interval
+  useWidgetRefresh(visible, getKeyboard, refresh);
+
+  if (loading) return <DataWidgetLoader.Widget className="keyboard" />;
+  if (!state) return null;
+  const { keyboard } = state;
+
+  const maxLength = Number(keyboardMaxLength) || 0;
+  const displayKeyboard =
+    maxLength > 0 ? keyboard.slice(0, maxLength) : keyboard;
+
+  if (!displayKeyboard?.length) return null;
+
+  return (
+    <DataWidget.Widget
+      classes="keyboard"
+      Icon={showIcon ? Icons.Keyboard : null}
+    >
+      {displayKeyboard}
+    </DataWidget.Widget>
+  );
+});
+
+Widget.displayName = "Keyboard";
-- 
cgit v1.3.1

