Full Code of chikobara/dotfiles for AI

main d0b9365e830f cached
749 files
2.5 MB
702.2k tokens
240 symbols
1 requests
Download .txt
Showing preview only (2,801K chars total). Download the full file or copy to clipboard to get everything.
Repository: chikobara/dotfiles
Branch: main
Commit: d0b9365e830f
Files: 749
Total size: 2.5 MB

Directory structure:
gitextract_9l3ptfwt/

├── .config/
│   ├── ags/
│   │   ├── .eslintignore
│   │   ├── .eslintrc.js
│   │   ├── .github/
│   │   │   ├── ISSUE_TEMPLATE/
│   │   │   │   ├── bug_report.md
│   │   │   │   └── feature_request.md
│   │   │   └── workflows/
│   │   │       └── ci.yml
│   │   ├── .gitignore
│   │   ├── .gitmodules
│   │   ├── .prettierignore
│   │   ├── .prettierrc
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── config.js
│   │   ├── customModules/
│   │   │   ├── PollVar.ts
│   │   │   ├── config.ts
│   │   │   ├── cpu/
│   │   │   │   ├── computeCPU.ts
│   │   │   │   └── index.ts
│   │   │   ├── kblayout/
│   │   │   │   ├── getLayout.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── layouts.ts
│   │   │   ├── module.ts
│   │   │   ├── netstat/
│   │   │   │   ├── computeNetwork.ts
│   │   │   │   └── index.ts
│   │   │   ├── power/
│   │   │   │   └── index.ts
│   │   │   ├── ram/
│   │   │   │   ├── computeRam.ts
│   │   │   │   └── index.ts
│   │   │   ├── storage/
│   │   │   │   ├── computeStorage.ts
│   │   │   │   └── index.ts
│   │   │   ├── submap/
│   │   │   │   ├── helpers.ts
│   │   │   │   └── index.ts
│   │   │   ├── theme.ts
│   │   │   ├── updates/
│   │   │   │   └── index.ts
│   │   │   ├── utils.ts
│   │   │   └── weather/
│   │   │       └── index.ts
│   │   ├── directoryMonitorService.ts
│   │   ├── flake.nix
│   │   ├── globals/
│   │   │   ├── dropdown.ts
│   │   │   ├── mousePos.ts
│   │   │   ├── network.ts
│   │   │   ├── notification.ts
│   │   │   ├── useTheme.ts
│   │   │   ├── utilities.ts
│   │   │   ├── variables.ts
│   │   │   ├── weather.ts
│   │   │   └── window.ts
│   │   ├── globals.d.ts
│   │   ├── install_fonts.sh
│   │   ├── lib/
│   │   │   ├── constants/
│   │   │   │   └── colors.ts
│   │   │   ├── icons.ts
│   │   │   ├── option.ts
│   │   │   ├── session.ts
│   │   │   ├── shared/
│   │   │   │   ├── media.ts
│   │   │   │   └── notifications.ts
│   │   │   ├── types/
│   │   │   │   ├── audio.d.ts
│   │   │   │   ├── bar.d.ts
│   │   │   │   ├── customModules/
│   │   │   │   │   ├── generic.d.ts
│   │   │   │   │   ├── kbLayout.d.ts
│   │   │   │   │   ├── network.d.ts
│   │   │   │   │   └── utils.d.ts
│   │   │   │   ├── defaults/
│   │   │   │   │   ├── bar.ts
│   │   │   │   │   ├── netstat.ts
│   │   │   │   │   ├── options.ts
│   │   │   │   │   └── weather.ts
│   │   │   │   ├── dropdownmenu.d.ts
│   │   │   │   ├── filechooser.d.ts
│   │   │   │   ├── globals.d.ts
│   │   │   │   ├── gpustat.d.ts
│   │   │   │   ├── mpris.d.ts
│   │   │   │   ├── network.d.ts
│   │   │   │   ├── notification.d.ts
│   │   │   │   ├── options.d.ts
│   │   │   │   ├── popupwindow.d.ts
│   │   │   │   ├── power.d.ts
│   │   │   │   ├── powerprofiles.d.ts
│   │   │   │   ├── systray.d.ts
│   │   │   │   ├── utils.d.ts
│   │   │   │   ├── variable.d.ts
│   │   │   │   ├── volume.d.ts
│   │   │   │   ├── weather.d.ts
│   │   │   │   ├── widget.d.ts
│   │   │   │   └── workspace.d.ts
│   │   │   ├── utils.ts
│   │   │   └── variables.ts
│   │   ├── main.ts
│   │   ├── modules/
│   │   │   ├── bar/
│   │   │   │   ├── Bar.ts
│   │   │   │   ├── Exports.ts
│   │   │   │   ├── SideEffects.ts
│   │   │   │   ├── battery/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── bluetooth/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── clock/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── media/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── menu/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── network/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── notifications/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── systray/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── utils.ts
│   │   │   │   ├── volume/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── window_title/
│   │   │   │   │   └── index.ts
│   │   │   │   └── workspaces/
│   │   │   │       ├── helpers.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── utils.ts
│   │   │   │       └── variants/
│   │   │   │           ├── default.ts
│   │   │   │           └── occupied.ts
│   │   │   ├── icons/
│   │   │   │   ├── index.ts
│   │   │   │   └── weather.ts
│   │   │   ├── menus/
│   │   │   │   ├── audio/
│   │   │   │   │   ├── active/
│   │   │   │   │   │   ├── SelectedInput.ts
│   │   │   │   │   │   ├── SelectedPlayback.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── available/
│   │   │   │   │   │   ├── InputDevices.ts
│   │   │   │   │   │   ├── PlaybackDevices.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── bluetooth/
│   │   │   │   │   ├── devices/
│   │   │   │   │   │   ├── connectedControls.ts
│   │   │   │   │   │   ├── devicelist.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── label.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── calendar/
│   │   │   │   │   ├── calendar.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── time/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── weather/
│   │   │   │   │       ├── hourly/
│   │   │   │   │       │   ├── icon/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── temperature/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   ├── time/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   └── utils.ts
│   │   │   │   │       ├── icon/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── stats/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       └── temperature/
│   │   │   │   │           └── index.ts
│   │   │   │   ├── dashboard/
│   │   │   │   │   ├── controls/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── directories/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── profile/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── shortcuts/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── stats/
│   │   │   │   │       └── index.ts
│   │   │   │   ├── energy/
│   │   │   │   │   ├── brightness/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── profiles/
│   │   │   │   │       └── index.ts
│   │   │   │   ├── main.ts
│   │   │   │   ├── media/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── bar.ts
│   │   │   │   │   │   ├── controls.ts
│   │   │   │   │   │   └── mediainfo.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── media.ts
│   │   │   │   ├── network/
│   │   │   │   │   ├── ethernet/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── wifi/
│   │   │   │   │       ├── APStaging.ts
│   │   │   │   │       ├── WirelessAPs.ts
│   │   │   │   │       └── index.ts
│   │   │   │   ├── notifications/
│   │   │   │   │   ├── controls/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── notification/
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── body/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── close/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── header/
│   │   │   │   │   │   │   ├── icon.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── image/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── placeholder/
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── pager/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── power/
│   │   │   │   │   ├── helpers/
│   │   │   │   │   │   └── actions.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── verification.ts
│   │   │   │   ├── powerDropdown/
│   │   │   │   │   ├── button.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── shared/
│   │   │   │       ├── dropdown/
│   │   │   │       │   ├── eventBoxes/
│   │   │   │       │   │   └── index.ts
│   │   │   │       │   ├── index.ts
│   │   │   │       │   └── locationHandler/
│   │   │   │       │       └── index.ts
│   │   │   │       └── popup/
│   │   │   │           └── index.ts
│   │   │   ├── notifications/
│   │   │   │   ├── actions/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── body/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── close/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── header/
│   │   │   │   │   ├── icon.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── image/
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── osd/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── icon/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── label/
│   │   │   │       └── index.ts
│   │   │   └── shared/
│   │   │       └── barItemBox.ts
│   │   ├── nix/
│   │   │   └── default.nix
│   │   ├── options.ts
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   ├── README.md
│   │   │   ├── checkUpdates.sh
│   │   │   ├── color_generation/
│   │   │   │   ├── applycolor.sh
│   │   │   │   ├── colorgen.sh
│   │   │   │   ├── generate_colors_material.py
│   │   │   │   ├── pywal_to_material.scss
│   │   │   │   ├── randomwall.sh
│   │   │   │   ├── schemes/
│   │   │   │   │   └── scheme_morevibrant.py
│   │   │   │   ├── specials/
│   │   │   │   │   ├── _material_badapple-l.scss
│   │   │   │   │   └── _material_badapple.scss
│   │   │   │   ├── switchcolor.sh
│   │   │   │   └── switchwall.sh
│   │   │   ├── fillThemes.js
│   │   │   ├── fillThemes.sh
│   │   │   ├── grimblast.sh
│   │   │   ├── hyprland/
│   │   │   │   ├── get_keybinds.py
│   │   │   │   └── workspace_action.sh
│   │   │   ├── quickscripts/
│   │   │   │   └── nixos-trim-generations.sh
│   │   │   ├── record-script.sh
│   │   │   ├── sway/
│   │   │   │   └── swayToRelativeWs.sh
│   │   │   ├── templates/
│   │   │   │   ├── fuzzel/
│   │   │   │   │   └── fuzzel.ini
│   │   │   │   ├── gradience/
│   │   │   │   │   └── preset.json
│   │   │   │   ├── hypr/
│   │   │   │   │   ├── hyprland/
│   │   │   │   │   │   └── colors.conf
│   │   │   │   │   └── hyprlock.conf
│   │   │   │   └── terminal/
│   │   │   │       ├── scheme-base.json
│   │   │   │       ├── scheme-monochrome.json
│   │   │   │       └── sequences.txt
│   │   │   └── wayland-idle-inhibitor.py
│   │   ├── scss/
│   │   │   ├── main.scss
│   │   │   ├── optionsTrackers.ts
│   │   │   ├── style/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── audio.scss
│   │   │   │   │   ├── bar.scss
│   │   │   │   │   ├── battery.scss
│   │   │   │   │   ├── bluetooth.scss
│   │   │   │   │   ├── clock.scss
│   │   │   │   │   ├── media.scss
│   │   │   │   │   ├── menu.scss
│   │   │   │   │   ├── network.scss
│   │   │   │   │   ├── notifications.scss
│   │   │   │   │   ├── power.scss
│   │   │   │   │   ├── systray.scss
│   │   │   │   │   ├── window_title.scss
│   │   │   │   │   └── workspace.scss
│   │   │   │   ├── colors.scss
│   │   │   │   ├── common/
│   │   │   │   │   ├── common.scss
│   │   │   │   │   ├── floating-widget.scss
│   │   │   │   │   ├── general.scss
│   │   │   │   │   └── widget-button.scss
│   │   │   │   ├── customModules/
│   │   │   │   │   └── style.scss
│   │   │   │   ├── highlights.scss
│   │   │   │   ├── menus/
│   │   │   │   │   ├── audiomenu.scss
│   │   │   │   │   ├── bluetooth.scss
│   │   │   │   │   ├── calendar.scss
│   │   │   │   │   ├── dashboard.scss
│   │   │   │   │   ├── energy.scss
│   │   │   │   │   ├── media.scss
│   │   │   │   │   ├── menu.scss
│   │   │   │   │   ├── network.scss
│   │   │   │   │   ├── notifications.scss
│   │   │   │   │   ├── power.scss
│   │   │   │   │   └── powerdropdown.scss
│   │   │   │   ├── notifications/
│   │   │   │   │   └── popups.scss
│   │   │   │   ├── osd/
│   │   │   │   │   └── index.scss
│   │   │   │   └── settings/
│   │   │   │       └── dialog.scss
│   │   │   └── style.ts
│   │   ├── services/
│   │   │   ├── Brightness.ts
│   │   │   ├── Cpu.ts
│   │   │   ├── Ram.ts
│   │   │   ├── Storage.ts
│   │   │   ├── Wallpaper.ts
│   │   │   ├── bluetooth.py
│   │   │   ├── matugen/
│   │   │   │   ├── index.ts
│   │   │   │   └── variations.ts
│   │   │   ├── screen_record.sh
│   │   │   └── snapshot.sh
│   │   ├── themes/
│   │   │   ├── catppuccin_frappe.json
│   │   │   ├── catppuccin_frappe_split.json
│   │   │   ├── catppuccin_latte.json
│   │   │   ├── catppuccin_latte_split.json
│   │   │   ├── catppuccin_macchiato.json
│   │   │   ├── catppuccin_macchiato_split.json
│   │   │   ├── catppuccin_mocha.json
│   │   │   ├── catppuccin_mocha_split.json
│   │   │   ├── cyberpunk.json
│   │   │   ├── cyberpunk_split.json
│   │   │   ├── dracula.json
│   │   │   ├── dracula_split.json
│   │   │   ├── everforest.json
│   │   │   ├── everforest_split.json
│   │   │   ├── gruvbox.json
│   │   │   ├── gruvbox_split.json
│   │   │   ├── monochrome.json
│   │   │   ├── monochrome_split.json
│   │   │   ├── nord.json
│   │   │   ├── nord_split.json
│   │   │   ├── one_dark.json
│   │   │   ├── one_dark_split.json
│   │   │   ├── rose_pine.json
│   │   │   ├── rose_pine_moon.json
│   │   │   ├── rose_pine_moon_split.json
│   │   │   ├── rose_pine_split.json
│   │   │   ├── tokyo_night.json
│   │   │   └── tokyo_night_split.json
│   │   ├── tsconfig.json
│   │   └── widget/
│   │       ├── RegularWindow.ts
│   │       └── settings/
│   │           ├── SettingsDialog.ts
│   │           ├── pages/
│   │           │   ├── config/
│   │           │   │   ├── bar/
│   │           │   │   │   └── index.ts
│   │           │   │   ├── general/
│   │           │   │   │   └── index.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── menus/
│   │           │   │   │   ├── clock.ts
│   │           │   │   │   ├── dashboard.ts
│   │           │   │   │   └── power.ts
│   │           │   │   ├── notifications/
│   │           │   │   │   └── index.ts
│   │           │   │   └── osd/
│   │           │   │       └── index.ts
│   │           │   └── theme/
│   │           │       ├── bar/
│   │           │       │   └── index.ts
│   │           │       ├── index.ts
│   │           │       ├── menus/
│   │           │       │   ├── battery.ts
│   │           │       │   ├── bluetooth.ts
│   │           │       │   ├── clock.ts
│   │           │       │   ├── dashboard.ts
│   │           │       │   ├── index.ts
│   │           │       │   ├── matugen.ts
│   │           │       │   ├── media.ts
│   │           │       │   ├── network.ts
│   │           │       │   ├── notifications.ts
│   │           │       │   ├── power.ts
│   │           │       │   ├── systray.ts
│   │           │       │   └── volume.ts
│   │           │       ├── notifications/
│   │           │       │   └── index.ts
│   │           │       └── osd/
│   │           │           └── index.ts
│   │           ├── shared/
│   │           │   ├── FileChooser.ts
│   │           │   ├── Header.ts
│   │           │   ├── Inputter.ts
│   │           │   ├── Label.ts
│   │           │   ├── Option.ts
│   │           │   └── components/
│   │           │       ├── boolean.ts
│   │           │       ├── color.ts
│   │           │       ├── enum.ts
│   │           │       ├── font.ts
│   │           │       ├── image.ts
│   │           │       ├── import.ts
│   │           │       ├── number.ts
│   │           │       ├── object.ts
│   │           │       ├── string.ts
│   │           │       └── wallpaper.ts
│   │           └── side_effects/
│   │               └── index.ts
│   ├── fuzzel/
│   │   └── fuzzel.ini
│   ├── hypr/
│   │   ├── hypridle.conf
│   │   ├── hyprland/
│   │   │   ├── colors.conf
│   │   │   ├── env.conf
│   │   │   ├── execs.conf
│   │   │   ├── general.conf
│   │   │   ├── keybinds.conf
│   │   │   └── rules.conf
│   │   ├── hyprland.conf
│   │   ├── hyprlock/
│   │   │   └── status.sh
│   │   ├── hyprlock.conf
│   │   ├── monitors.conf
│   │   ├── shaders/
│   │   │   ├── chromatic_abberation.frag
│   │   │   ├── crt.frag
│   │   │   ├── drugs.frag
│   │   │   ├── extradark.frag
│   │   │   ├── invert.frag
│   │   │   └── solarized.frag
│   │   └── workspaces.conf
│   ├── kitty/
│   │   ├── current-theme.conf
│   │   ├── kitty-hyprland.conf
│   │   ├── kitty-themes/
│   │   │   ├── .all-contributorsrc
│   │   │   ├── .tools/
│   │   │   │   ├── README.md
│   │   │   │   ├── color_table.sh
│   │   │   │   ├── convert.py
│   │   │   │   ├── convert_conf.swift
│   │   │   │   ├── extract-vscode.sh
│   │   │   │   ├── generate_conf.sh
│   │   │   │   ├── generate_theme_preview.sh
│   │   │   │   ├── generate_themes_previews.sh
│   │   │   │   ├── libcapture.sh
│   │   │   │   ├── markdown.sh
│   │   │   │   ├── palette.py
│   │   │   │   ├── preview.py
│   │   │   │   ├── previews.sh
│   │   │   │   ├── template.conf
│   │   │   │   ├── template.conf.j2
│   │   │   │   └── windowid.swift
│   │   │   ├── CONTRIBUTING.md
│   │   │   ├── LICENSE.md
│   │   │   ├── README.md
│   │   │   └── themes/
│   │   │       ├── 3024_Day.conf
│   │   │       ├── 3024_Night.conf
│   │   │       ├── AdventureTime.conf
│   │   │       ├── Afterglow.conf
│   │   │       ├── AlienBlood.conf
│   │   │       ├── Alucard.conf
│   │   │       ├── Apprentice.conf
│   │   │       ├── Argonaut.conf
│   │   │       ├── Arthur.conf
│   │   │       ├── AtelierSulphurpool.conf
│   │   │       ├── Atom.conf
│   │   │       ├── AtomOneLight.conf
│   │   │       ├── Batman.conf
│   │   │       ├── Belafonte_Day.conf
│   │   │       ├── Belafonte_Night.conf
│   │   │       ├── BirdsOfParadise.conf
│   │   │       ├── Blazer.conf
│   │   │       ├── Borland.conf
│   │   │       ├── Bright_Lights.conf
│   │   │       ├── Broadcast.conf
│   │   │       ├── Brogrammer.conf
│   │   │       ├── C64.conf
│   │   │       ├── CLRS.conf
│   │   │       ├── Chalk.conf
│   │   │       ├── Chalkboard.conf
│   │   │       ├── Ciapre.conf
│   │   │       ├── Cobalt2.conf
│   │   │       ├── Cobalt_Neon.conf
│   │   │       ├── CrayonPonyFish.conf
│   │   │       ├── Dark_Pastel.conf
│   │   │       ├── Darkside.conf
│   │   │       ├── Desert.conf
│   │   │       ├── DimmedMonokai.conf
│   │   │       ├── DotGov.conf
│   │   │       ├── Dracula.conf
│   │   │       ├── Dumbledore.conf
│   │   │       ├── Duotone_Dark.conf
│   │   │       ├── ENCOM.conf
│   │   │       ├── Earthsong.conf
│   │   │       ├── Elemental.conf
│   │   │       ├── Espresso.conf
│   │   │       ├── Espresso_Libre.conf
│   │   │       ├── Fideloper.conf
│   │   │       ├── FishTank.conf
│   │   │       ├── Flat.conf
│   │   │       ├── Flatland.conf
│   │   │       ├── Floraverse.conf
│   │   │       ├── FrontEndDelight.conf
│   │   │       ├── FunForrest.conf
│   │   │       ├── Galaxy.conf
│   │   │       ├── Github.conf
│   │   │       ├── Glacier.conf
│   │   │       ├── GoaBase.conf
│   │   │       ├── Grape.conf
│   │   │       ├── Grass.conf
│   │   │       ├── Hardcore.conf
│   │   │       ├── Harper.conf
│   │   │       ├── Highway.conf
│   │   │       ├── Hipster_Green.conf
│   │   │       ├── Homebrew.conf
│   │   │       ├── Hurtado.conf
│   │   │       ├── Hybrid.conf
│   │   │       ├── IC_Green_PPL.conf
│   │   │       ├── IC_Orange_PPL.conf
│   │   │       ├── IR_Black.conf
│   │   │       ├── Jackie_Brown.conf
│   │   │       ├── Japanesque.conf
│   │   │       ├── Jellybeans.conf
│   │   │       ├── JetBrains_Darcula.conf
│   │   │       ├── Kibble.conf
│   │   │       ├── Later_This_Evening.conf
│   │   │       ├── Lavandula.conf
│   │   │       ├── LiquidCarbon.conf
│   │   │       ├── LiquidCarbonTransparent.conf
│   │   │       ├── LiquidCarbonTransparentInverse.conf
│   │   │       ├── Man_Page.conf
│   │   │       ├── Material.conf
│   │   │       ├── MaterialDark.conf
│   │   │       ├── Mathias.conf
│   │   │       ├── Medallion.conf
│   │   │       ├── Misterioso.conf
│   │   │       ├── Molokai.conf
│   │   │       ├── MonaLisa.conf
│   │   │       ├── Monokai.conf
│   │   │       ├── Monokai_Classic.conf
│   │   │       ├── Monokai_Pro.conf
│   │   │       ├── Monokai_Pro_(Filter_Machine).conf
│   │   │       ├── Monokai_Pro_(Filter_Octagon).conf
│   │   │       ├── Monokai_Pro_(Filter_Ristretto).conf
│   │   │       ├── Monokai_Pro_(Filter_Spectrum).conf
│   │   │       ├── Monokai_Soda.conf
│   │   │       ├── N0tch2k.conf
│   │   │       ├── Neopolitan.conf
│   │   │       ├── Neutron.conf
│   │   │       ├── NightLion_v1.conf
│   │   │       ├── NightLion_v2.conf
│   │   │       ├── Nova.conf
│   │   │       ├── Novel.conf
│   │   │       ├── Obsidian.conf
│   │   │       ├── Ocean.conf
│   │   │       ├── OceanicMaterial.conf
│   │   │       ├── Ollie.conf
│   │   │       ├── OneDark.conf
│   │   │       ├── Parasio_Dark.conf
│   │   │       ├── PaulMillr.conf
│   │   │       ├── PencilDark.conf
│   │   │       ├── PencilLight.conf
│   │   │       ├── Piatto_Light.conf
│   │   │       ├── Pnevma.conf
│   │   │       ├── Pro.conf
│   │   │       ├── Red_Alert.conf
│   │   │       ├── Red_Sands.conf
│   │   │       ├── Relaxed_Afterglow.conf
│   │   │       ├── Renault_Style.conf
│   │   │       ├── Renault_Style_Light.conf
│   │   │       ├── Rippedcasts.conf
│   │   │       ├── Royal.conf
│   │   │       ├── SeaShells.conf
│   │   │       ├── Seafoam_Pastel.conf
│   │   │       ├── Seti.conf
│   │   │       ├── Shaman.conf
│   │   │       ├── Slate.conf
│   │   │       ├── Smyck.conf
│   │   │       ├── SoftServer.conf
│   │   │       ├── Solarized_Darcula.conf
│   │   │       ├── Solarized_Dark.conf
│   │   │       ├── Solarized_Dark_-_Patched.conf
│   │   │       ├── Solarized_Dark_Higher_Contrast.conf
│   │   │       ├── Solarized_Light.conf
│   │   │       ├── Source_Code_X.conf
│   │   │       ├── SpaceGray.conf
│   │   │       ├── SpaceGray_Eighties.conf
│   │   │       ├── SpaceGray_Eighties_Dull.conf
│   │   │       ├── Spacedust.conf
│   │   │       ├── Spiderman.conf
│   │   │       ├── Spring.conf
│   │   │       ├── Square.conf
│   │   │       ├── Sundried.conf
│   │   │       ├── Symfonic.conf
│   │   │       ├── Tango_Dark.conf
│   │   │       ├── Tango_Light.conf
│   │   │       ├── Teerb.conf
│   │   │       ├── Thayer_Bright.conf
│   │   │       ├── The_Hulk.conf
│   │   │       ├── Tomorrow.conf
│   │   │       ├── Tomorrow_Night.conf
│   │   │       ├── Tomorrow_Night_Blue.conf
│   │   │       ├── Tomorrow_Night_Bright.conf
│   │   │       ├── Tomorrow_Night_Eighties.conf
│   │   │       ├── ToyChest.conf
│   │   │       ├── Treehouse.conf
│   │   │       ├── Twilight.conf
│   │   │       ├── Ubuntu.conf
│   │   │       ├── Urple.conf
│   │   │       ├── Vaughn.conf
│   │   │       ├── VibrantInk.conf
│   │   │       ├── WarmNeon.conf
│   │   │       ├── Wez.conf
│   │   │       ├── WildCherry.conf
│   │   │       ├── Wombat.conf
│   │   │       ├── Wryan.conf
│   │   │       ├── Zenburn.conf
│   │   │       ├── ayu.conf
│   │   │       ├── ayu_light.conf
│   │   │       ├── ayu_mirage.conf
│   │   │       ├── gruvbox_dark.conf
│   │   │       ├── gruvbox_light.conf
│   │   │       ├── idleToes.conf
│   │   │       ├── rose-pine-moon.conf
│   │   │       └── snazzy.conf
│   │   └── kitty.conf
│   ├── qt5ct/
│   │   └── qt5ct.conf
│   ├── qt6ct/
│   │   ├── colors/
│   │   │   ├── Catppuccin-Latte.conf
│   │   │   └── Catppuccin-Mocha.conf
│   │   └── qt6ct.conf
│   ├── rofi/
│   │   ├── applets/
│   │   │   ├── bin/
│   │   │   │   ├── appasroot.sh
│   │   │   │   ├── apps.sh
│   │   │   │   ├── battery.sh
│   │   │   │   ├── brightness.sh
│   │   │   │   ├── mpd.sh
│   │   │   │   ├── powermenu.sh
│   │   │   │   ├── quicklinks.sh
│   │   │   │   ├── screenshot.sh
│   │   │   │   └── volume.sh
│   │   │   ├── shared/
│   │   │   │   ├── colors.rasi
│   │   │   │   ├── fonts.rasi
│   │   │   │   └── theme.bash
│   │   │   ├── type-1/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-2/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-3/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-4/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   └── type-5/
│   │   │       ├── style-1.rasi
│   │   │       ├── style-2.rasi
│   │   │       └── style-3.rasi
│   │   ├── colors/
│   │   │   ├── adapta.rasi
│   │   │   ├── arc.rasi
│   │   │   ├── black.rasi
│   │   │   ├── catppuccin.rasi
│   │   │   ├── cyberpunk.rasi
│   │   │   ├── dracula.rasi
│   │   │   ├── everforest.rasi
│   │   │   ├── gruvbox.rasi
│   │   │   ├── lovelace.rasi
│   │   │   ├── navy.rasi
│   │   │   ├── nord.rasi
│   │   │   ├── onedark.rasi
│   │   │   ├── paper.rasi
│   │   │   ├── solarized.rasi
│   │   │   ├── tokyonight.rasi
│   │   │   └── yousai.rasi
│   │   ├── config.rasi
│   │   ├── launchers/
│   │   │   ├── type-1/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-11.rasi
│   │   │   │   ├── style-12.rasi
│   │   │   │   ├── style-13.rasi
│   │   │   │   ├── style-14.rasi
│   │   │   │   ├── style-15.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-2/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-11.rasi
│   │   │   │   ├── style-12.rasi
│   │   │   │   ├── style-13.rasi
│   │   │   │   ├── style-14.rasi
│   │   │   │   ├── style-15.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-3/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-4/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-5/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   └── style-5.rasi
│   │   │   ├── type-6/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   └── type-7/
│   │   │       ├── launcher.sh
│   │   │       ├── style-1.rasi
│   │   │       ├── style-10.rasi
│   │   │       ├── style-2.rasi
│   │   │       ├── style-3.rasi
│   │   │       ├── style-4.rasi
│   │   │       ├── style-5.rasi
│   │   │       ├── style-6.rasi
│   │   │       ├── style-7.rasi
│   │   │       ├── style-8.rasi
│   │   │       └── style-9.rasi
│   │   └── powermenu/
│   │       ├── type-1/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-2/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-10.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   ├── style-5.rasi
│   │       │   ├── style-6.rasi
│   │       │   ├── style-7.rasi
│   │       │   ├── style-8.rasi
│   │       │   └── style-9.rasi
│   │       ├── type-3/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   ├── confirm.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-4/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   ├── confirm.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-5/
│   │       │   ├── powermenu.sh
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       └── type-6/
│   │           ├── powermenu.sh
│   │           ├── style-1.rasi
│   │           ├── style-2.rasi
│   │           ├── style-3.rasi
│   │           ├── style-4.rasi
│   │           └── style-5.rasi
│   ├── wlogout/
│   │   ├── layout
│   │   └── style.css
│   └── zshrc.d/
│       ├── auto-Hypr.sh
│       ├── dots-hyprland.zsh
│       └── shortcuts.zsh
├── .fastfetch_conf.jsonc
├── .fonts/
│   ├── .uuid
│   └── CustomTkinter_shapes_font.otf
├── .gitattributes
├── .zprofile
├── .zshenv
├── .zshrc
├── README.md
├── backup.sh
└── hyprpanel_config.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .config/ags/.eslintignore
================================================
types
node_modules


================================================
FILE: .config/ags/.eslintrc.js
================================================
module.exports = {
    parser: '@typescript-eslint/parser',
    parserOptions: {
        project: 'tsconfig.json',
        tsconfigRootDir: __dirname,
        sourceType: 'module',
    },
    plugins: ['@typescript-eslint', 'import'],
    extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
    root: true,
    ignorePatterns: ['.eslintrc.js', 'types/**/*.ts', 'scripts/**/*.js'],
    env: {
        es6: true,
        browser: true,
    },
    rules: {
        '@typescript-eslint/interface-name-prefix': 'off',
        '@typescript-eslint/explicit-function-return-type': 'error',
        '@typescript-eslint/explicit-module-boundary-types': 'error',
        '@typescript-eslint/no-explicit-any': 'error',
        'import/extensions': ['off'],
        'import/no-unresolved': 'off',
        quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }],
    },
};


================================================
FILE: .config/ags/.github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help HyprPanel improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - Distribution: [e.g. Arch Linux]
 - Window Manager/Desktop Environment: [e.g. Hyprland]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .config/ags/.github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .config/ags/.github/workflows/ci.yml
================================================
name: CI

on:
    pull_request:
        branches:
            - master

jobs:
    code_quality:
        runs-on: ubuntu-latest

        steps:
            - name: Checkout main repository
              uses: actions/checkout@v3

            - name: Clone ags-types to temp dir
              uses: actions/checkout@v3
              with:
                  repository: Jas-SinghFSU/ags-types
                  path: temp-ags-types

            - name: Copy types to types/
              run: |
                  rm -rf types
                  mkdir -p types
                  cp -R temp-ags-types/types/* types/
                  rm -rf temp-ags-types

            - name: Node Setup
              uses: actions/setup-node@v3
              with:
                  node-version: '21'

            - name: Install Dependencies
              run: npm install

            - name: ESLint
              run: npm run lint

            - name: Type Check
              run: npx tsc --noEmit --pretty --extendedDiagnostics


================================================
FILE: .config/ags/.gitignore
================================================
.weather.json
node_modules


================================================
FILE: .config/ags/.gitmodules
================================================
[submodule "external/ags-types"]
	path = external/ags-types
	url = https://github.com/Jas-SinghFSU/ags-types.git


================================================
FILE: .config/ags/.prettierignore
================================================
.eslintrc.js
types/**/*.ts


================================================
FILE: .config/ags/.prettierrc
================================================
{
    "singleQuote": true,
    "semi": true,
    "trailingComma": "all",
    "printWidth": 120,
    "tabWidth": 4,
    "useTabs": false
}


================================================
FILE: .config/ags/LICENSE
================================================
MIT License

Copyright (c) 2024 Jas Singh

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: .config/ags/README.md
================================================
<p align="center">
  <a href="https://hyprpanel.com" target="_blank" rel="noopener noreferrer">
    <img width="180" src="./assets/hyprpanel.png" alt="Hyprpanel logo">
  </a>
</p>
<br/>
<p align="center">
  <a href="https://hyprpanel.com/getting_started/installation.html"><img src="https://img.shields.io/badge/Wiki-hyprpanel-orange?style=flat&logo=wiki" alt="wiki"></a>
  <a href="https://discord.gg/MNpg7Z2b3a"><img src="https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord" alt="discord chat"></a>
</p>
<br/>

# HyprPanel 🚀

A panel built for Hyprland with [AGS](https://github.com/Aylur/ags)

![HyprPanel1](./assets/hp1.png)
![HyprPanel2](./assets/hp2.png)

## Installation

The [HyprPanel Wiki](https://hyprpanel.com/getting_started/installation.html) contains in depth instructions for installing the panel and all of its dependencies. The instructions below are general instructions for installing the panel.

## Requirements

Bun

```sh
curl -fsSL https://bun.sh/install | bash && \
  sudo ln -s $HOME/.bun/bin/bun /usr/local/bin/bun
```

Additional dependencies:

```sh
pipewire
libgtop
bluez
bluez-utils
grimblast
gpu-screen-recorder
hyprpicker
btop
networkmanager
matugen
wl-clipboard
swww
dart-sass
brightnessctl
gnome-bluetooth-3.0
```

Optional Dependencies:

```sh
## Used for Tracking GPU Usage in your Dashboard (NVidia only)
python
python-gpustat

## Only if a pywal hook from wallpaper changes applied through settings is desired
pywal

## To check for pacman updates in the default script used in the updates module
pacman-contrib

## To switch between power profiles in battery module
power-profiles-daemon
```

### Arch

pacman:

```bash
sudo pacman -S pipewire libgtop bluez bluez-utils btop networkmanager dart-sass wl-clipboard brightnessctl swww python gnome-bluetooth-3.0 pacman-contrib power-profiles-daemon
```

AUR:

```bash
yay -S grimblast-git gpu-screen-recorder hyprpicker matugen-bin python-gpustat aylurs-gtk-shell-git
```

### Fedora

COPR - Add [solopasha/hyprland](https://copr.fedorainfracloud.org/coprs/solopasha/hyprland/) for most hyprland-related dependencies, and [hues-sueh/packages](https://copr.fedorainfracloud.org/coprs/heus-sueh/packages/) for matugen. Both provide the `swww` package, so prioritise the former repo:

```bash
sudo dnf copr enable solopasha/hyprland
sudo dnf copr enable heus-sueh/packages
sudo dnf config-manager --save --setopt=copr:copr.fedorainfracloud.org:heus-sueh:packages.priority=200
```

DNF:

```bash
sudo dnf install pipewire libgtop2 bluez bluez-tools grimblast hyprpicker btop NetworkManager  wl-clipboard swww brightnessctl gnome-bluetooth aylurs-gtk-shell power-profiles-daemon gvfs
```

bun:

```bash
bun install -g sass
```

flatpak:

```bash
flatpak install flathub --system com.dec05eba.gpu_screen_recorder
```

#### Optional Dependencies

pip:

```bash
sudo dnf install python python3-pip; pip install gpustat pywal
```

### NixOS

For NixOS/Home-Manager, see [NixOS & Home-Manager instructions](#nixos--home-manager).

## Instructions

### AGS

Once everything is installed you need to put the contents of this repo in `~/.config/ags`.
If you already have something in `~/.config/ags`, it's recommended that you back it up with:

```bash
mv $HOME/.config/ags $HOME/.config/ags.bkup
```

Otherwise you can use this command to install the panel:

```bash
git clone https://github.com/Jas-SinghFSU/HyprPanel.git && \
  ln -s $(pwd)/HyprPanel $HOME/.config/ags
```

### Nerd Fonts

Additionally, you need to ensure that you have a [Nerd Font](https://www.nerdfonts.com/font-downloads) installed for your icons to render properly.

### Launch the panel

Afterwards you can run the panel with the following command in your terminal:

```bash
ags
```

Or you can add it to your Hyprland config (hyprland.conf) to auto-start with:

```bash
exec-once = ags
```

### NixOS & Home-Manager

Alternatively, if you're using NixOS and/or Home-Manager, you can setup AGS using the provided Nix Flake. First, add the repository to your Flake's inputs, and enable the overlay.

```nix
# flake.nix

{
  inputs.hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
  # ...

  outputs = { self, nixpkgs, ... }@inputs:
  let
    # ...
	system = "x86_64-linux"; # change to whatever your system should be.
    pkgs = import nixpkgs {
	  inherit system;
	  # ...
	  overlays = [
        inputs.hyprpanel.overlay
	  ];
	};
  in {
    # ...
  }
}
```

Once you've set up the overlay, you can reference HyprPanel with `pkgs.hyprpanel` as if it were any other Nix package. This means you can reference it as a NixOS system/user package, a Home-Manager user package, or as a direct reference in your Hyprland configuration (if your configuration is managed by Home-Manager). The first three methods will add it to your `$PATH` (first globally, second two user-only), however the final will not.

```nix
# configuration.nix

# install it as a system package
environment.systemPackages = with pkgs; [
  # ...
  hyprpanel
  # ...
];

# or install it as a user package
users.users.<username>.packages = with pkgs; [
  # ...
  hyprpanel
  # ...
];


# home.nix

# install it as a user package with home-manager
home.packages = with pkgs; [
  # ...
  hyprpanel
  # ...
];

# or reference it directly in your Hyprland configuration
wayland.windowManager.hyprland.settings.exec-once = [
  "${pkgs.hyprpanel}/bin/hyprpanel"
];

```

### Notifications

HyprPanel handles notifications through the AGS built-in notification service. If you're already using a notification daemon such as Dunst or Mako, you may have to stop them to prevent conflicts with HyprPanel.

> NOTE: If your system is in a language other than English, the resource monitor in the dashboard may not work properly.

## Configuration

The HyprPanel comes with a configuration menu which is available by opening the Dashboard menu (click the button in the bar with the default - Arch - icon) and then clicking the Gear icon.

### Size

The panel is automatically scaled based on your font size in `Configuration > General`.

### Specifying bar layouts per monitor

To specify layouts for each monitor you can create a JSON object such as:

```JSON
{
    "0": {
        "left": [
            "dashboard",
            "workspaces",
            "windowtitle"
        ],
        "middle": [
            "media"
        ],
        "right": [
            "volume",
            "clock",
            "notifications"
        ]
    },
    "1": {
        "left": [
            "dashboard",
            "workspaces",
            "windowtitle"
        ],
        "middle": [
            "media"
        ],
        "right": [
            "volume",
            "clock",
            "notifications"
        ]
    },
    "2": {
        "left": [
            "dashboard",
            "workspaces",
            "windowtitle"
        ],
        "middle": [
            "media"
        ],
        "right": [
            "volume",
            "network",
            "bluetooth",
            "systray",
            "clock",
            "notifications"
        ]
    }
}
```

Where each monitor is defined by its index (0, 1, 2 in this case) and each section (left, middle, right) contains one or more of the following modules:

```js
'battery';
'dashboard';
'workspaces';
'windowtitle';
'media';
'notifications';
'volume';
'network';
'bluetooth';
'clock';
'systray';
```

Since the text-box in the options dialog isn't sufficient, it is recommended that you create this JSON configuration in a text editor elsewhere and paste it into the layout text-box under Configuration > Bar > "Bar Layouts for Monitors".

### Additional Configuration

#### GPU Tracking

If you have an NVidia GPU, you can track your GPU usage in your Dashboard by going to your `Settings > Configuration > Dashboard Menu > Track GPU` and turning it on.


================================================
FILE: .config/ags/config.js
================================================
import GLib from 'gi://GLib';

const main = '/tmp/ags/hyprpanel/main.js';
const entry = `${App.configDir}/main.ts`;
const bundler = GLib.getenv('AGS_BUNDLER') || 'bun';

const v = {
    ags: pkg.version?.split('.').map(Number) || [],
    expect: [1, 8, 1],
};

try {
    switch (bundler) {
        case 'bun':
            await Utils.execAsync([
                'bun',
                'build',
                entry,
                '--outfile',
                main,
                '--external',
                'resource://*',
                '--external',
                'gi://*',
                '--external',
                'file://*',
            ]);
            break;

        case 'esbuild':
            await Utils.execAsync([
                'esbuild',
                '--bundle',
                entry,
                '--format=esm',
                `--outfile=${main}`,
                '--external:resource://*',
                '--external:gi://*',
                '--external:file://*',
            ]);
            break;

        default:
            throw `"${bundler}" is not a valid bundler`;
    }

    if (v.ags[1] < v.expect[1] || v.ags[2] < v.expect[2]) {
        print(`HyprPanel needs atleast v${v.expect.join('.')} of AGS, yours is v${v.ags.join('.')}`);
        App.quit();
    }

    await import(`file://${main}`);
} catch (error) {
    console.error(error);
    App.quit();
}

export {};


================================================
FILE: .config/ags/customModules/PollVar.ts
================================================
import GLib from 'gi://GLib?version=2.0';
import { GenericFunction } from 'lib/types/customModules/generic';
import { Bind } from 'lib/types/variable';
import { Variable as VariableType } from 'types/variable';

/**
 * @param {VariableType<T>} targetVariable - The Variable to update with the function's result.
 * @param {Array<Bind>} trackers - Array of trackers to watch.
 * @param {Bind} pollingInterval - The polling interval in milliseconds.
 * @param {GenericFunction<T, P>} someFunc - The function to execute at each interval, which updates the Variable.
 * @param  {...P} params - Parameters to pass to someFunc.
 */
export const pollVariable = <T, P extends unknown[], F extends GenericFunction<T, P>>(
    targetVariable: VariableType<T>,
    trackers: Array<Bind>,
    pollingInterval: Bind,
    someFunc: F,
    ...params: P
): void => {
    let intervalInstance: number | null = null;

    const intervalFn = (pollIntrvl: number): void => {
        if (intervalInstance !== null) {
            GLib.source_remove(intervalInstance);
        }

        intervalInstance = Utils.interval(pollIntrvl, () => {
            targetVariable.value = someFunc(...params);
        });
    };

    Utils.merge([pollingInterval, ...trackers], (pollIntrvl: number) => {
        intervalFn(pollIntrvl);
    });
};

/**
 * @param {VariableType<T>} targetVariable - The Variable to update with the result of the command.
 * @param {Array<Bind>} trackers - Array of trackers to watch.
 * @param {Bind} pollingInterval - The polling interval in milliseconds.
 * @param {string} someCommand - The bash command to execute.
 * @param {GenericFunction<T, [unknown, ...P]>} someFunc - The function to execute after processing the command result;
 * with the first argument being the result of the command execution.
 * @param  {...P} params - Additional parameters to pass to someFunc.
 */
export const pollVariableBash = <T, P extends unknown[], F extends GenericFunction<T, [string, ...P]>>(
    targetVariable: VariableType<T>,
    trackers: Array<Bind>,
    pollingInterval: Bind,
    someCommand: string,
    someFunc: F,
    ...params: P
): void => {
    let intervalInstance: number | null = null;

    const intervalFn = (pollIntrvl: number): void => {
        if (intervalInstance !== null) {
            GLib.source_remove(intervalInstance);
        }

        intervalInstance = Utils.interval(pollIntrvl, () => {
            Utils.execAsync(`bash -c "${someCommand}"`)
                .then((res: string) => {
                    try {
                        targetVariable.value = someFunc(res, ...params);
                    } catch (error) {
                        console.warn(`An error occurred when running interval bash function: ${error}`);
                    }
                })
                .catch((err) => console.error(`Error running command "${someCommand}": ${err}`));
        });
    };

    Utils.merge([pollingInterval, ...trackers], (pollIntrvl: number) => {
        intervalFn(pollIntrvl);
    });
};


================================================
FILE: .config/ags/customModules/config.ts
================================================
import { Option } from 'widget/settings/shared/Option';
import { Header } from 'widget/settings/shared/Header';

import options from 'options';
import Scrollable from 'types/widgets/scrollable';
import { Attribute, GtkWidget } from 'lib/types/widget';

export const CustomModuleSettings = (): Scrollable<GtkWidget, Attribute> =>
    Widget.Scrollable({
        vscroll: 'automatic',
        hscroll: 'automatic',
        class_name: 'menu-theme-page customModules paged-container',
        child: Widget.Box({
            class_name: 'menu-theme-page paged-container',
            vertical: true,
            children: [
                /*
                 ************************************
                 *            GENERAL               *
                 ************************************
                 */
                Header('General'),
                Option({
                    opt: options.bar.customModules.scrollSpeed,
                    title: 'Scrolling Speed',
                    type: 'number',
                }),

                /*
                 ************************************
                 *              RAM                 *
                 ************************************
                 */
                Header('RAM'),
                Option({
                    opt: options.theme.bar.buttons.modules.ram.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.ram.icon,
                    title: 'Ram Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.ram.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.ram.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.ram.labelType,
                    title: 'Label Type',
                    type: 'enum',
                    enums: ['used/total', 'used', 'free', 'percentage'],
                }),
                Option({
                    opt: options.bar.customModules.ram.round,
                    title: 'Round',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.ram.pollingInterval,
                    title: 'Polling Interval',
                    type: 'number',
                    min: 100,
                    max: 60 * 24 * 1000,
                    increment: 1000,
                }),
                Option({
                    opt: options.bar.customModules.ram.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.ram.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.ram.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),

                /*
                 ************************************
                 *             CPU                  *
                 ************************************
                 */
                Header('CPU'),
                Option({
                    opt: options.theme.bar.buttons.modules.cpu.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.cpu.icon,
                    title: 'Cpu Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.cpu.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.round,
                    title: 'Round',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.cpu.pollingInterval,
                    title: 'Polling Interval',
                    type: 'number',
                    min: 100,
                    max: 60 * 24 * 1000,
                    increment: 1000,
                }),
                Option({
                    opt: options.bar.customModules.cpu.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.cpu.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),

                /*
                 ************************************
                 *           STORAGE                *
                 ************************************
                 */
                Header('Storage'),
                Option({
                    opt: options.theme.bar.buttons.modules.storage.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.storage.icon,
                    title: 'Storage Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.storage.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.storage.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.storage.labelType,
                    title: 'Label Type',
                    type: 'enum',
                    enums: ['used/total', 'used', 'free', 'percentage'],
                }),
                Option({
                    opt: options.bar.customModules.storage.round,
                    title: 'Round',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.storage.pollingInterval,
                    title: 'Polling Interval',
                    type: 'number',
                    min: 100,
                    max: 60 * 24 * 1000,
                    increment: 1000,
                }),
                Option({
                    opt: options.bar.customModules.storage.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.storage.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.storage.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),

                /*
                 ************************************
                 *           NETSTAT                *
                 ************************************
                 */
                Header('Netstat'),
                Option({
                    opt: options.theme.bar.buttons.modules.netstat.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.netstat.networkInterface,
                    title: 'Network Interface',
                    subtitle:
                        "Name of the network interface to poll.\nHINT: Get list of interfaces with 'cat /proc/net/dev'",
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.netstat.icon,
                    title: 'Netstat Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.netstat.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.netstat.rateUnit,
                    title: 'Rate Unit',
                    type: 'enum',
                    enums: ['GiB', 'MiB', 'KiB', 'auto'],
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.netstat.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.netstat.labelType,
                    title: 'Label Type',
                    type: 'enum',
                    enums: ['full', 'in', 'out'],
                }),
                Option({
                    opt: options.bar.customModules.netstat.round,
                    title: 'Round',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.netstat.pollingInterval,
                    title: 'Polling Interval',
                    type: 'number',
                    min: 100,
                    max: 60 * 24 * 1000,
                    increment: 1000,
                }),
                Option({
                    opt: options.bar.customModules.netstat.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.netstat.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.netstat.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),

                /*
                 ************************************
                 *       KEYBOARD LAYOUT            *
                 ************************************
                 */
                Header('Keyboard Layout'),
                Option({
                    opt: options.theme.bar.buttons.modules.kbLayout.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.icon,
                    title: 'Keyboard Layout Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.labelType,
                    title: 'Label Type',
                    type: 'enum',
                    enums: ['layout', 'code'],
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.kbLayout.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.kbLayout.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),

                /*
                 ************************************
                 *            UPDATES               *
                 ************************************
                 */
                Header('Updates'),
                Option({
                    opt: options.theme.bar.buttons.modules.updates.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.updates.updateCommand,
                    title: 'Check Updates Command',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.icon,
                    title: 'Updates Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.updates.padZero,
                    title: 'Pad with 0',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.updates.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.pollingInterval,
                    title: 'Polling Interval',
                    type: 'number',
                    subtitle: "WARNING: Be careful of your package manager's rate limit.",
                    min: 100,
                    max: 60 * 24 * 1000,
                    increment: 1000,
                }),
                Option({
                    opt: options.bar.customModules.updates.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.updates.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),

                /*
                 ************************************
                 *            SUBMAP                *
                 ************************************
                 */
                Header('Submap'),
                Option({
                    opt: options.theme.bar.buttons.modules.submap.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.submap.showSubmapName,
                    title: 'Show Submap Name',
                    subtitle:
                        'When enabled, the name of the current submap will be displayed' +
                        ' instead of the Submap Enabled or Disabled text.',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.submap.enabledIcon,
                    title: 'Enabled Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.disabledIcon,
                    title: 'Disabled Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.enabledText,
                    title: 'Enabled Text',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.disabledText,
                    title: 'Disabled Text',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.submap.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.submap.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),

                /*
                 ************************************
                 *            WEATHER               *
                 ************************************
                 */
                Header('Weather'),
                Option({
                    opt: options.theme.bar.buttons.modules.weather.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.weather.label,
                    title: 'Show Label',
                    type: 'boolean',
                }),
                Option({
                    opt: options.bar.customModules.weather.unit,
                    title: 'Units',
                    type: 'enum',
                    enums: ['imperial', 'metric'],
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.weather.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.weather.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.weather.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.weather.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.weather.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.weather.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),

                /*
                 ************************************
                 *            POWER                 *
                 ************************************
                 */
                Header('Power'),
                Option({
                    opt: options.theme.bar.buttons.modules.power.enableBorder,
                    title: 'Button Border',
                    type: 'boolean',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.power.spacing,
                    title: 'Spacing',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.icon,
                    title: 'Power Button Icon',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.leftClick,
                    title: 'Left Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.rightClick,
                    title: 'Right Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.middleClick,
                    title: 'Middle Click',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.scrollUp,
                    title: 'Scroll Up',
                    type: 'string',
                }),
                Option({
                    opt: options.bar.customModules.power.scrollDown,
                    title: 'Scroll Down',
                    type: 'string',
                }),
            ],
        }),
    });


================================================
FILE: .config/ags/customModules/cpu/computeCPU.ts
================================================
// @ts-expect-error: This import is a special directive that tells the compiler to use the GTop library
import GTop from 'gi://GTop';

let previousCpuData = new GTop.glibtop_cpu();
GTop.glibtop_get_cpu(previousCpuData);

// FIX: Consolidate with Cpu service class
export const computeCPU = (): number => {
    const currentCpuData = new GTop.glibtop_cpu();
    GTop.glibtop_get_cpu(currentCpuData);

    // Calculate the differences from the previous to current data
    const totalDiff = currentCpuData.total - previousCpuData.total;
    const idleDiff = currentCpuData.idle - previousCpuData.idle;

    const cpuUsagePercentage = totalDiff > 0 ? ((totalDiff - idleDiff) / totalDiff) * 100 : 0;

    previousCpuData = currentCpuData;

    return cpuUsagePercentage;
};


================================================
FILE: .config/ags/customModules/cpu/index.ts
================================================
import options from 'options';

// Module initializer
import { module } from '../module';

import Button from 'types/widgets/button';

// Utility Methods
import { inputHandler } from 'customModules/utils';
import { computeCPU } from './computeCPU';
import { pollVariable } from 'customModules/PollVar';
import { BarBoxChild } from 'lib/types/bar';
import { Attribute, Child } from 'lib/types/widget';

// All the user configurable options for the cpu module that are needed
const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval, icon } =
    options.bar.customModules.cpu;

export const cpuUsage = Variable(0);

pollVariable(
    // Variable to poll and update with the result of the function passed in
    cpuUsage,
    // Variables that should trigger the polling function to update when they change
    [round.bind('value')],
    // Interval at which to poll
    pollingInterval.bind('value'),
    // Function to execute to get the network data
    computeCPU,
);

export const Cpu = (): BarBoxChild => {
    const renderLabel = (cpuUsg: number, rnd: boolean): string => {
        return rnd ? `${Math.round(cpuUsg)}%` : `${cpuUsg.toFixed(2)}%`;
    };

    const cpuModule = module({
        textIcon: icon.bind('value'),
        label: Utils.merge([cpuUsage.bind('value'), round.bind('value')], (cpuUsg, rnd) => {
            return renderLabel(cpuUsg, rnd);
        }),
        tooltipText: 'CPU',
        boxClass: 'cpu',
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return cpuModule;
};


================================================
FILE: .config/ags/customModules/kblayout/getLayout.ts
================================================
import {
    HyprctlDeviceLayout,
    HyprctlKeyboard,
    KbLabelType,
    LayoutKeys,
    LayoutValues,
} from 'lib/types/customModules/kbLayout';
import { layoutMap } from './layouts';

export const getKeyboardLayout = (obj: string, format: KbLabelType): LayoutKeys | LayoutValues => {
    const hyprctlDevices: HyprctlDeviceLayout = JSON.parse(obj);
    const keyboards = hyprctlDevices['keyboards'];

    if (keyboards.length === 0) {
        return format === 'code' ? 'Unknown' : 'Unknown Layout';
    }

    let mainKb = keyboards.find((kb: HyprctlKeyboard) => kb.main);

    if (!mainKb) {
        mainKb = keyboards[keyboards.length - 1];
    }

    const layout: LayoutKeys = mainKb['active_keymap'] as LayoutKeys;
    const foundLayout: LayoutValues = layoutMap[layout];

    return format === 'code' ? foundLayout || layout : layout;
};


================================================
FILE: .config/ags/customModules/kblayout/index.ts
================================================
const hyprland = await Service.import('hyprland');

import options from 'options';
import { module } from '../module';

import { inputHandler } from 'customModules/utils';
import Gtk from 'types/@girs/gtk-3.0/gtk-3.0';
import Button from 'types/widgets/button';
import Label from 'types/widgets/label';
import { getKeyboardLayout } from './getLayout';
import { BarBoxChild } from 'lib/types/bar';
import { Attribute, Child } from 'lib/types/widget';

const { label, labelType, icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } =
    options.bar.customModules.kbLayout;

export const KbInput = (): BarBoxChild => {
    const keyboardModule = module({
        textIcon: icon.bind('value'),
        tooltipText: '',
        labelHook: (self: Label<Gtk.Widget>): void => {
            self.hook(
                hyprland,
                () => {
                    Utils.execAsync('hyprctl devices -j')
                        .then((obj) => {
                            self.label = getKeyboardLayout(obj, labelType.value);
                        })
                        .catch((err) => {
                            console.error(err);
                        });
                },
                'keyboard-layout',
            );

            self.hook(labelType, () => {
                Utils.execAsync('hyprctl devices -j')
                    .then((obj) => {
                        self.label = getKeyboardLayout(obj, labelType.value);
                    })
                    .catch((err) => {
                        console.error(err);
                    });
            });
        },

        boxClass: 'kblayout',
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return keyboardModule;
};


================================================
FILE: .config/ags/customModules/kblayout/layouts.ts
================================================
export const layoutMap = {
    'Abkhazian (Russia)': 'RU (Ab)',
    Akan: 'GH (Akan)',
    Albanian: 'AL',
    'Albanian (Plisi)': 'AL (Plisi)',
    'Albanian (Veqilharxhi)': 'AL (Veqilharxhi)',
    Amharic: 'ET',
    Arabic: 'ARA',
    'Arabic (Algeria)': 'DZ (Ar)',
    'Arabic (AZERTY, Eastern Arabic numerals)': 'ARA (Azerty Digits)',
    'Arabic (AZERTY)': 'ARA (Azerty)',
    'Arabic (Buckwalter)': 'ARA (Buckwalter)',
    'Arabic (Eastern Arabic numerals)': 'ARA (Digits)',
    'Arabic (Macintosh)': 'ARA (Mac)',
    'Arabic (Morocco)': 'MA',
    'Arabic (OLPC)': 'ARA (Olpc)',
    'Arabic (Pakistan)': 'PK (Ara)',
    'Arabic (QWERTY, Eastern Arabic numerals)': 'ARA (Qwerty Digits)',
    'Arabic (QWERTY)': 'ARA (Qwerty)',
    'Arabic (Syria)': 'SY',
    Armenian: 'AM',
    'Armenian (alt. eastern)': 'AM (Eastern-Alt)',
    'Armenian (alt. phonetic)': 'AM (Phonetic-Alt)',
    'Armenian (eastern)': 'AM (Eastern)',
    'Armenian (phonetic)': 'AM (Phonetic)',
    'Armenian (western)': 'AM (Western)',
    'Asturian (Spain, with bottom-dot H and L)': 'ES (Ast)',
    Avatime: 'GH (Avn)',
    Azerbaijani: 'AZ',
    'Azerbaijani (Cyrillic)': 'AZ (Cyrillic)',
    'Azerbaijani (Iran)': 'IR (Azb)',
    Bambara: 'ML',
    Bangla: 'BD',
    'Bangla (India, Baishakhi InScript)': 'IN (Ben Inscript)',
    'Bangla (India, Baishakhi)': 'IN (Ben Baishakhi)',
    'Bangla (India, Bornona)': 'IN (Ben Bornona)',
    'Bangla (India, Gitanjali)': 'IN (Ben Gitanjali)',
    'Bangla (India, Probhat)': 'IN (Ben Probhat)',
    'Bangla (India)': 'IN (Ben)',
    'Bangla (Probhat)': 'BD (Probhat)',
    Bashkirian: 'RU (Bak)',
    Belarusian: 'BY',
    'Belarusian (intl.)': 'BY (Intl)',
    'Belarusian (Latin)': 'BY (Latin)',
    'Belarusian (legacy)': 'BY (Legacy)',
    'Belarusian (phonetic)': 'BY (Phonetic)',
    Belgian: 'BE',
    'Belgian (alt.)': 'BE (Oss)',
    'Belgian (ISO, alt.)': 'BE (Iso-Alternate)',
    'Belgian (Latin-9 only, alt.)': 'BE (Oss Latin9)',
    'Belgian (no dead keys)': 'BE (Nodeadkeys)',
    'Belgian (Wang 724 AZERTY)': 'BE (Wang)',
    'Berber (Algeria, Latin)': 'DZ',
    'Berber (Algeria, Tifinagh)': 'DZ (Ber)',
    'Berber (Morocco, Tifinagh alt.)': 'MA (Tifinagh-Alt)',
    'Berber (Morocco, Tifinagh extended phonetic)': 'MA (Tifinagh-Extended-Phonetic)',
    'Berber (Morocco, Tifinagh extended)': 'MA (Tifinagh-Extended)',
    'Berber (Morocco, Tifinagh phonetic, alt.)': 'MA (Tifinagh-Alt-Phonetic)',
    'Berber (Morocco, Tifinagh phonetic)': 'MA (Tifinagh-Phonetic)',
    'Berber (Morocco, Tifinagh)': 'MA (Tifinagh)',
    Bosnian: 'BA',
    'Bosnian (US, with Bosnian digraphs)': 'BA (Unicodeus)',
    'Bosnian (US)': 'BA (Us)',
    'Bosnian (with Bosnian digraphs)': 'BA (Unicode)',
    'Bosnian (with guillemets)': 'BA (Alternatequotes)',
    Braille: 'BRAI',
    'Braille (left-handed inverted thumb)': 'BRAI (Left Hand Invert)',
    'Braille (left-handed)': 'BRAI (Left Hand)',
    'Braille (right-handed inverted thumb)': 'BRAI (Right Hand Invert)',
    'Braille (right-handed)': 'BRAI (Right Hand)',
    'Breton (France)': 'FR (Bre)',
    Bulgarian: 'BG',
    'Bulgarian (enhanced)': 'BG (Bekl)',
    'Bulgarian (new phonetic)': 'BG (Bas Phonetic)',
    'Bulgarian (traditional phonetic)': 'BG (Phonetic)',
    Burmese: 'MM',
    'Burmese Zawgyi': 'MM (Zawgyi)',
    'Cameroon (AZERTY, intl.)': 'CM (Azerty)',
    'Cameroon (Dvorak, intl.)': 'CM (Dvorak)',
    'Cameroon Multilingual (QWERTY, intl.)': 'CM (Qwerty)',
    'Canadian (CSA)': 'CA (Multix)',
    'Catalan (Spain, with middle-dot L)': 'ES (Cat)',
    Cherokee: 'US (Chr)',
    Chinese: 'CN',
    Chuvash: 'RU (Cv)',
    'Chuvash (Latin)': 'RU (Cv Latin)',
    CloGaelach: 'IE (CloGaelach)',
    'Crimean Tatar (Turkish Alt-Q)': 'UA (Crh Alt)',
    'Crimean Tatar (Turkish F)': 'UA (Crh F)',
    'Crimean Tatar (Turkish Q)': 'UA (Crh)',
    Croatian: 'HR',
    'Croatian (US, with Croatian digraphs)': 'HR (Unicodeus)',
    'Croatian (US)': 'HR (Us)',
    'Croatian (with Croatian digraphs)': 'HR (Unicode)',
    'Croatian (with guillemets)': 'HR (Alternatequotes)',
    Czech: 'CZ',
    'Czech (QWERTY, extended backslash)': 'CZ (Qwerty Bksl)',
    'Czech (QWERTY, Macintosh)': 'CZ (Qwerty-Mac)',
    'Czech (QWERTY)': 'CZ (Qwerty)',
    'Czech (UCW, only accented letters)': 'CZ (Ucw)',
    'Czech (US, Dvorak, UCW support)': 'CZ (Dvorak-Ucw)',
    'Czech (with <\\|> key)': 'CZ (Bksl)',
    Danish: 'DK',
    'Danish (Dvorak)': 'DK (Dvorak)',
    'Danish (Macintosh, no dead keys)': 'DK (Mac Nodeadkeys)',
    'Danish (Macintosh)': 'DK (Mac)',
    'Danish (no dead keys)': 'DK (Nodeadkeys)',
    'Danish (Windows)': 'DK (Winkeys)',
    Dari: 'AF',
    'Dari (Afghanistan, OLPC)': 'AF (Fa-Olpc)',
    Dhivehi: 'MV',
    Dutch: 'NL',
    'Dutch (Macintosh)': 'NL (Mac)',
    'Dutch (standard)': 'NL (Std)',
    'Dutch (US)': 'NL (Us)',
    Dzongkha: 'BT',
    'English (Australian)': 'AU',
    'English (Cameroon)': 'CM',
    'English (Canada)': 'CA (Eng)',
    'English (classic Dvorak)': 'US (Dvorak-Classic)',
    'English (Colemak-DH ISO)': 'US (Colemak Dh Iso)',
    'English (Colemak-DH)': 'US (Colemak Dh)',
    'English (Colemak)': 'US (Colemak)',
    'English (Dvorak, alt. intl.)': 'US (Dvorak-Alt-Intl)',
    'English (Dvorak, intl., with dead keys)': 'US (Dvorak-Intl)',
    'English (Dvorak, left-handed)': 'US (Dvorak-L)',
    'English (Dvorak, Macintosh)': 'US (Dvorak-Mac)',
    'English (Dvorak, right-handed)': 'US (Dvorak-R)',
    'English (Dvorak)': 'US (Dvorak)',
    'English (Ghana, GILLBT)': 'GH (Gillbt)',
    'English (Ghana, multilingual)': 'GH (Generic)',
    'English (Ghana)': 'GH',
    'English (India, with rupee)': 'IN (Eng)',
    'English (intl., with AltGr dead keys)': 'US (Altgr-Intl)',
    'English (Macintosh)': 'US (Mac)',
    'English (Mali, US, intl.)': 'ML (Us-Intl)',
    'English (Mali, US, Macintosh)': 'ML (Us-Mac)',
    'English (Nigeria)': 'NG',
    'English (Norman)': 'US (Norman)',
    'English (programmer Dvorak)': 'US (Dvp)',
    'English (South Africa)': 'ZA',
    'English (the divide/multiply toggle the layout)': 'US (Olpc2)',
    'English (UK, Colemak-DH)': 'GB (Colemak Dh)',
    'English (UK, Colemak)': 'GB (Colemak)',
    'English (UK, Dvorak, with UK punctuation)': 'GB (Dvorakukp)',
    'English (UK, Dvorak)': 'GB (Dvorak)',
    'English (UK, extended, Windows)': 'GB (Extd)',
    'English (UK, intl., with dead keys)': 'GB (Intl)',
    'English (UK, Macintosh, intl.)': 'GB (Mac Intl)',
    'English (UK, Macintosh)': 'GB (Mac)',
    'English (UK)': 'GB',
    'English (US, alt. intl.)': 'US (Alt-Intl)',
    'English (US, euro on 5)': 'US (Euro)',
    'English (US, intl., with dead keys)': 'US (Intl)',
    'English (US, Symbolic)': 'US (Symbolic)',
    'English (US)': 'US',
    'English (Workman, intl., with dead keys)': 'US (Workman-Intl)',
    'English (Workman)': 'US (Workman)',
    Esperanto: 'EPO',
    'Esperanto (Brazil, Nativo)': 'BR (Nativo-Epo)',
    'Esperanto (legacy)': 'EPO (Legacy)',
    'Esperanto (Portugal, Nativo)': 'PT (Nativo-Epo)',
    Estonian: 'EE',
    'Estonian (Dvorak)': 'EE (Dvorak)',
    'Estonian (no dead keys)': 'EE (Nodeadkeys)',
    'Estonian (US)': 'EE (Us)',
    Ewe: 'GH (Ewe)',
    Faroese: 'FO',
    'Faroese (no dead keys)': 'FO (Nodeadkeys)',
    Filipino: 'PH',
    'Filipino (Capewell-Dvorak, Baybayin)': 'PH (Capewell-Dvorak-Bay)',
    'Filipino (Capewell-Dvorak, Latin)': 'PH (Capewell-Dvorak)',
    'Filipino (Capewell-QWERF 2006, Baybayin)': 'PH (Capewell-Qwerf2k6-Bay)',
    'Filipino (Capewell-QWERF 2006, Latin)': 'PH (Capewell-Qwerf2k6)',
    'Filipino (Colemak, Baybayin)': 'PH (Colemak-Bay)',
    'Filipino (Colemak, Latin)': 'PH (Colemak)',
    'Filipino (Dvorak, Baybayin)': 'PH (Dvorak-Bay)',
    'Filipino (Dvorak, Latin)': 'PH (Dvorak)',
    'Filipino (QWERTY, Baybayin)': 'PH (Qwerty-Bay)',
    Finnish: 'FI',
    'Finnish (classic, no dead keys)': 'FI (Nodeadkeys)',
    'Finnish (classic)': 'FI (Classic)',
    'Finnish (Macintosh)': 'FI (Mac)',
    'Finnish (Windows)': 'FI (Winkeys)',
    French: 'FR',
    'French (alt., Latin-9 only)': 'FR (Oss Latin9)',
    'French (alt., no dead keys)': 'FR (Oss Nodeadkeys)',
    'French (alt.)': 'FR (Oss)',
    'French (AZERTY, AFNOR)': 'FR (Afnor)',
    'French (AZERTY)': 'FR (Azerty)',
    'French (BEPO, AFNOR)': 'FR (Bepo Afnor)',
    'French (BEPO, Latin-9 only)': 'FR (Bepo Latin9)',
    'French (BEPO)': 'FR (Bepo)',
    'French (Cameroon)': 'CM (French)',
    'French (Canada, Dvorak)': 'CA (Fr-Dvorak)',
    'French (Canada, legacy)': 'CA (Fr-Legacy)',
    'French (Canada)': 'CA',
    'French (Democratic Republic of the Congo)': 'CD',
    'French (Dvorak)': 'FR (Dvorak)',
    'French (legacy, alt., no dead keys)': 'FR (Latin9 Nodeadkeys)',
    'French (legacy, alt.)': 'FR (Latin9)',
    'French (Macintosh)': 'FR (Mac)',
    'French (Mali, alt.)': 'ML (Fr-Oss)',
    'French (Morocco)': 'MA (French)',
    'French (no dead keys)': 'FR (Nodeadkeys)',
    'French (Switzerland, Macintosh)': 'CH (Fr Mac)',
    'French (Switzerland, no dead keys)': 'CH (Fr Nodeadkeys)',
    'French (Switzerland)': 'CH (Fr)',
    'French (Togo)': 'TG',
    'French (US)': 'FR (Us)',
    'Friulian (Italy)': 'IT (Fur)',
    Fula: 'GH (Fula)',
    Ga: 'GH (Ga)',
    Georgian: 'GE',
    'Georgian (ergonomic)': 'GE (Ergonomic)',
    'Georgian (France, AZERTY Tskapo)': 'FR (Geo)',
    'Georgian (Italy)': 'IT (Geo)',
    'Georgian (MESS)': 'GE (Mess)',
    German: 'DE',
    'German (Austria, Macintosh)': 'AT (Mac)',
    'German (Austria, no dead keys)': 'AT (Nodeadkeys)',
    'German (Austria)': 'AT',
    'German (dead acute)': 'DE (Deadacute)',
    'German (dead grave acute)': 'DE (Deadgraveacute)',
    'German (dead tilde)': 'DE (Deadtilde)',
    'German (Dvorak)': 'DE (Dvorak)',
    'German (E1)': 'DE (E1)',
    'German (E2)': 'DE (E2)',
    'German (Macintosh, no dead keys)': 'DE (Mac Nodeadkeys)',
    'German (Macintosh)': 'DE (Mac)',
    'German (Neo 2)': 'DE (Neo)',
    'German (no dead keys)': 'DE (Nodeadkeys)',
    'German (QWERTY)': 'DE (Qwerty)',
    'German (Switzerland, legacy)': 'CH (Legacy)',
    'German (Switzerland, Macintosh)': 'CH (De Mac)',
    'German (Switzerland, no dead keys)': 'CH (De Nodeadkeys)',
    'German (Switzerland)': 'CH',
    'German (T3)': 'DE (T3)',
    'German (US)': 'DE (Us)',
    Greek: 'GR',
    'Greek (extended)': 'GR (Extended)',
    'Greek (no dead keys)': 'GR (Nodeadkeys)',
    'Greek (polytonic)': 'GR (Polytonic)',
    'Greek (simple)': 'GR (Simple)',
    Gujarati: 'IN (Guj)',
    'Hanyu Pinyin Letters (with AltGr dead keys)': 'CN (Altgr-Pinyin)',
    'Hausa (Ghana)': 'GH (Hausa)',
    'Hausa (Nigeria)': 'NG (Hausa)',
    Hawaiian: 'US (Haw)',
    Hebrew: 'IL',
    'Hebrew (Biblical, Tiro)': 'IL (Biblical)',
    'Hebrew (lyx)': 'IL (Lyx)',
    'Hebrew (phonetic)': 'IL (Phonetic)',
    'Hindi (Bolnagri)': 'IN (Bolnagri)',
    'Hindi (KaGaPa, phonetic)': 'IN (Hin-Kagapa)',
    'Hindi (Wx)': 'IN (Hin-Wx)',
    Hungarian: 'HU',
    'Hungarian (no dead keys)': 'HU (Nodeadkeys)',
    'Hungarian (QWERTY, 101-key, comma, dead keys)': 'HU (101 Qwerty Comma Dead)',
    'Hungarian (QWERTY, 101-key, comma, no dead keys)': 'HU (101 Qwerty Comma Nodead)',
    'Hungarian (QWERTY, 101-key, dot, dead keys)': 'HU (101 Qwerty Dot Dead)',
    'Hungarian (QWERTY, 101-key, dot, no dead keys)': 'HU (101 Qwerty Dot Nodead)',
    'Hungarian (QWERTY, 102-key, comma, dead keys)': 'HU (102 Qwerty Comma Dead)',
    'Hungarian (QWERTY, 102-key, comma, no dead keys)': 'HU (102 Qwerty Comma Nodead)',
    'Hungarian (QWERTY, 102-key, dot, dead keys)': 'HU (102 Qwerty Dot Dead)',
    'Hungarian (QWERTY, 102-key, dot, no dead keys)': 'HU (102 Qwerty Dot Nodead)',
    'Hungarian (QWERTY)': 'HU (Qwerty)',
    'Hungarian (QWERTZ, 101-key, comma, dead keys)': 'HU (101 Qwertz Comma Dead)',
    'Hungarian (QWERTZ, 101-key, comma, no dead keys)': 'HU (101 Qwertz Comma Nodead)',
    'Hungarian (QWERTZ, 101-key, dot, dead keys)': 'HU (101 Qwertz Dot Dead)',
    'Hungarian (QWERTZ, 101-key, dot, no dead keys)': 'HU (101 Qwertz Dot Nodead)',
    'Hungarian (QWERTZ, 102-key, comma, dead keys)': 'HU (102 Qwertz Comma Dead)',
    'Hungarian (QWERTZ, 102-key, comma, no dead keys)': 'HU (102 Qwertz Comma Nodead)',
    'Hungarian (QWERTZ, 102-key, dot, dead keys)': 'HU (102 Qwertz Dot Dead)',
    'Hungarian (QWERTZ, 102-key, dot, no dead keys)': 'HU (102 Qwertz Dot Nodead)',
    'Hungarian (standard)': 'HU (Standard)',
    Icelandic: 'IS',
    'Icelandic (Dvorak)': 'IS (Dvorak)',
    'Icelandic (Macintosh, legacy)': 'IS (Mac Legacy)',
    'Icelandic (Macintosh)': 'IS (Mac)',
    Igbo: 'NG (Igbo)',
    Indian: 'IN',
    'Indic IPA': 'IN (Iipa)',
    'Indonesian (Arab Melayu, extended phonetic)': 'ID (Melayu-Phoneticx)',
    'Indonesian (Arab Melayu, phonetic)': 'ID (Melayu-Phonetic)',
    'Indonesian (Arab Pegon, phonetic)': 'ID (Pegon-Phonetic)',
    'Indonesian (Latin)': 'ID',
    Inuktitut: 'CA (Ike)',
    Iraqi: 'IQ',
    Irish: 'IE',
    'Irish (UnicodeExpert)': 'IE (UnicodeExpert)',
    Italian: 'IT',
    'Italian (IBM 142)': 'IT (Ibm)',
    'Italian (intl., with dead keys)': 'IT (Intl)',
    'Italian (Macintosh)': 'IT (Mac)',
    'Italian (no dead keys)': 'IT (Nodeadkeys)',
    'Italian (US)': 'IT (Us)',
    'Italian (Windows)': 'IT (Winkeys)',
    Japanese: 'JP',
    'Japanese (Dvorak)': 'JP (Dvorak)',
    'Japanese (Kana 86)': 'JP (Kana86)',
    'Japanese (Kana)': 'JP (Kana)',
    'Japanese (Macintosh)': 'JP (Mac)',
    'Japanese (OADG 109A)': 'JP (OADG109A)',
    Javanese: 'ID (Javanese)',
    'Kabyle (AZERTY, with dead keys)': 'DZ (Azerty-Deadkeys)',
    'Kabyle (QWERTY, UK, with dead keys)': 'DZ (Qwerty-Gb-Deadkeys)',
    'Kabyle (QWERTY, US, with dead keys)': 'DZ (Qwerty-Us-Deadkeys)',
    Kalmyk: 'RU (Xal)',
    Kannada: 'IN (Kan)',
    'Kannada (KaGaPa, phonetic)': 'IN (Kan-Kagapa)',
    Kashubian: 'PL (Csb)',
    Kazakh: 'KZ',
    'Kazakh (extended)': 'KZ (Ext)',
    'Kazakh (Latin)': 'KZ (Latin)',
    'Kazakh (with Russian)': 'KZ (Kazrus)',
    'Khmer (Cambodia)': 'KH',
    Kikuyu: 'KE (Kik)',
    Komi: 'RU (Kom)',
    Korean: 'KR',
    'Korean (101/104-key compatible)': 'KR (Kr104)',
    'Kurdish (Iran, Arabic-Latin)': 'IR (Ku Ara)',
    'Kurdish (Iran, F)': 'IR (Ku F)',
    'Kurdish (Iran, Latin Alt-Q)': 'IR (Ku Alt)',
    'Kurdish (Iran, Latin Q)': 'IR (Ku)',
    'Kurdish (Iraq, Arabic-Latin)': 'IQ (Ku Ara)',
    'Kurdish (Iraq, F)': 'IQ (Ku F)',
    'Kurdish (Iraq, Latin Alt-Q)': 'IQ (Ku Alt)',
    'Kurdish (Iraq, Latin Q)': 'IQ (Ku)',
    'Kurdish (Syria, F)': 'SY (Ku F)',
    'Kurdish (Syria, Latin Alt-Q)': 'SY (Ku Alt)',
    'Kurdish (Syria, Latin Q)': 'SY (Ku)',
    'Kurdish (Turkey, F)': 'TR (Ku F)',
    'Kurdish (Turkey, Latin Alt-Q)': 'TR (Ku Alt)',
    'Kurdish (Turkey, Latin Q)': 'TR (Ku)',
    Kyrgyz: 'KG',
    'Kyrgyz (phonetic)': 'KG (Phonetic)',
    Lao: 'LA',
    'Lao (STEA)': 'LA (Stea)',
    Latvian: 'LV',
    'Latvian (adapted)': 'LV (Adapted)',
    'Latvian (apostrophe)': 'LV (Apostrophe)',
    'Latvian (ergonomic, ŪGJRMV)': 'LV (Ergonomic)',
    'Latvian (F)': 'LV (Fkey)',
    'Latvian (modern)': 'LV (Modern)',
    'Latvian (tilde)': 'LV (Tilde)',
    Lithuanian: 'LT',
    'Lithuanian (IBM LST 1205-92)': 'LT (Ibm)',
    'Lithuanian (LEKP)': 'LT (Lekp)',
    'Lithuanian (LEKPa)': 'LT (Lekpa)',
    'Lithuanian (Ratise)': 'LT (Ratise)',
    'Lithuanian (standard)': 'LT (Std)',
    'Lithuanian (US)': 'LT (Us)',
    'Lower Sorbian': 'DE (Dsb)',
    'Lower Sorbian (QWERTZ)': 'DE (Dsb Qwertz)',
    Macedonian: 'MK',
    'Macedonian (no dead keys)': 'MK (Nodeadkeys)',
    'Malay (Jawi, Arabic Keyboard)': 'MY',
    'Malay (Jawi, phonetic)': 'MY (Phonetic)',
    Malayalam: 'IN (Mal)',
    'Malayalam (enhanced InScript, with rupee)': 'IN (Mal Enhanced)',
    'Malayalam (Lalitha)': 'IN (Mal Lalitha)',
    Maltese: 'MT',
    'Maltese (UK, with AltGr overrides)': 'MT (Alt-Gb)',
    'Maltese (US, with AltGr overrides)': 'MT (Alt-Us)',
    'Maltese (US)': 'MT (Us)',
    'Manipuri (Eeyek)': 'IN (Eeyek)',
    Maori: 'MAO',
    'Marathi (enhanced InScript)': 'IN (Marathi)',
    'Marathi (KaGaPa, phonetic)': 'IN (Mar-Kagapa)',
    Mari: 'RU (Chm)',
    Mmuock: 'CM (Mmuock)',
    Moldavian: 'MD',
    'Moldavian (Gagauz)': 'MD (Gag)',
    Mon: 'MM (Mnw)',
    'Mon (A1)': 'MM (Mnw-A1)',
    Mongolian: 'MN',
    'Mongolian (Bichig)': 'CN (Mon Trad)',
    'Mongolian (Galik)': 'CN (Mon Trad Galik)',
    'Mongolian (Manchu Galik)': 'CN (Mon Manchu Galik)',
    'Mongolian (Manchu)': 'CN (Mon Trad Manchu)',
    'Mongolian (Todo Galik)': 'CN (Mon Todo Galik)',
    'Mongolian (Todo)': 'CN (Mon Trad Todo)',
    'Mongolian (Xibe)': 'CN (Mon Trad Xibe)',
    Montenegrin: 'ME',
    'Montenegrin (Cyrillic, with guillemets)': 'ME (Cyrillicalternatequotes)',
    'Montenegrin (Cyrillic, ZE and ZHE swapped)': 'ME (Cyrillicyz)',
    'Montenegrin (Cyrillic)': 'ME (Cyrillic)',
    'Montenegrin (Latin, QWERTY)': 'ME (Latinyz)',
    'Montenegrin (Latin, Unicode, QWERTY)': 'ME (Latinunicodeyz)',
    'Montenegrin (Latin, Unicode)': 'ME (Latinunicode)',
    'Montenegrin (Latin, with guillemets)': 'ME (Latinalternatequotes)',
    "N'Ko (AZERTY)": 'GN',
    Nepali: 'NP',
    'Northern Saami (Finland)': 'FI (Smi)',
    'Northern Saami (Norway, no dead keys)': 'NO (Smi Nodeadkeys)',
    'Northern Saami (Norway)': 'NO (Smi)',
    'Northern Saami (Sweden)': 'SE (Smi)',
    Norwegian: 'NO',
    'Norwegian (Colemak)': 'NO (Colemak)',
    'Norwegian (Dvorak)': 'NO (Dvorak)',
    'Norwegian (Macintosh, no dead keys)': 'NO (Mac Nodeadkeys)',
    'Norwegian (Macintosh)': 'NO (Mac)',
    'Norwegian (no dead keys)': 'NO (Nodeadkeys)',
    'Norwegian (Windows)': 'NO (Winkeys)',
    Occitan: 'FR (Oci)',
    Ogham: 'IE (Ogam)',
    'Ogham (IS434)': 'IE (Ogam Is434)',
    'Ol Chiki': 'IN (Olck)',
    'Old Turkic': 'TR (Otk)',
    'Old Turkic (F)': 'TR (Otkf)',
    Oriya: 'IN (Ori)',
    'Oriya (Bolnagri)': 'IN (Ori-Bolnagri)',
    'Oriya (Wx)': 'IN (Ori-Wx)',
    'Ossetian (Georgia)': 'GE (Os)',
    'Ossetian (legacy)': 'RU (Os Legacy)',
    'Ossetian (Windows)': 'RU (Os Winkeys)',
    'Ottoman (F)': 'TR (Otf)',
    'Ottoman (Q)': 'TR (Ot)',
    'Pannonian Rusyn': 'RS (Rue)',
    Pashto: 'AF (Ps)',
    'Pashto (Afghanistan, OLPC)': 'AF (Ps-Olpc)',
    Persian: 'IR',
    'Persian (with Persian keypad)': 'IR (Pes Keypad)',
    Polish: 'PL',
    'Polish (British keyboard)': 'GB (Pl)',
    'Polish (Dvorak, with Polish quotes on key 1)': 'PL (Dvorak Altquotes)',
    'Polish (Dvorak, with Polish quotes on quotemark key)': 'PL (Dvorak Quotes)',
    'Polish (Dvorak)': 'PL (Dvorak)',
    'Polish (legacy)': 'PL (Legacy)',
    'Polish (programmer Dvorak)': 'PL (Dvp)',
    'Polish (QWERTZ)': 'PL (Qwertz)',
    Portuguese: 'PT',
    'Portuguese (Brazil, Dvorak)': 'BR (Dvorak)',
    'Portuguese (Brazil, IBM/Lenovo ThinkPad)': 'BR (Thinkpad)',
    'Portuguese (Brazil, Nativo for US keyboards)': 'BR (Nativo-Us)',
    'Portuguese (Brazil, Nativo)': 'BR (Nativo)',
    'Portuguese (Brazil, no dead keys)': 'BR (Nodeadkeys)',
    'Portuguese (Brazil)': 'BR',
    'Portuguese (Macintosh, no dead keys)': 'PT (Mac Nodeadkeys)',
    'Portuguese (Macintosh)': 'PT (Mac)',
    'Portuguese (Nativo for US keyboards)': 'PT (Nativo-Us)',
    'Portuguese (Nativo)': 'PT (Nativo)',
    'Portuguese (no dead keys)': 'PT (Nodeadkeys)',
    'Punjabi (Gurmukhi Jhelum)': 'IN (Jhelum)',
    'Punjabi (Gurmukhi)': 'IN (Guru)',
    Romanian: 'RO',
    'Romanian (Germany, no dead keys)': 'DE (Ro Nodeadkeys)',
    'Romanian (Germany)': 'DE (Ro)',
    'Romanian (standard)': 'RO (Std)',
    'Romanian (Windows)': 'RO (Winkeys)',
    Russian: 'RU',
    'Russian (Belarus)': 'BY (Ru)',
    'Russian (Czech, phonetic)': 'CZ (Rus)',
    'Russian (DOS)': 'RU (Dos)',
    'Russian (engineering, EN)': 'RU (Ruchey En)',
    'Russian (engineering, RU)': 'RU (Ruchey Ru)',
    'Russian (Georgia)': 'GE (Ru)',
    'Russian (Germany, phonetic)': 'DE (Ru)',
    'Russian (Kazakhstan, with Kazakh)': 'KZ (Ruskaz)',
    'Russian (legacy)': 'RU (Legacy)',
    'Russian (Macintosh)': 'RU (Mac)',
    'Russian (phonetic, AZERTY)': 'RU (Phonetic Azerty)',
    'Russian (phonetic, Dvorak)': 'RU (Phonetic Dvorak)',
    'Russian (phonetic, French)': 'RU (Phonetic Fr)',
    'Russian (phonetic, Windows)': 'RU (Phonetic Winkeys)',
    'Russian (phonetic, YAZHERTY)': 'RU (Phonetic YAZHERTY)',
    'Russian (phonetic)': 'RU (Phonetic)',
    'Russian (Poland, phonetic Dvorak)': 'PL (Ru Phonetic Dvorak)',
    'Russian (Sweden, phonetic, no dead keys)': 'SE (Rus Nodeadkeys)',
    'Russian (Sweden, phonetic)': 'SE (Rus)',
    'Russian (typewriter, legacy)': 'RU (Typewriter-Legacy)',
    'Russian (typewriter)': 'RU (Typewriter)',
    'Russian (Ukraine, standard RSTU)': 'UA (Rstu Ru)',
    'Russian (US, phonetic)': 'US (Rus)',
    'Saisiyat (Taiwan)': 'TW (Saisiyat)',
    Samogitian: 'LT (Sgs)',
    'Sanskrit (KaGaPa, phonetic)': 'IN (San-Kagapa)',
    'Scottish Gaelic': 'GB (Gla)',
    Serbian: 'RS',
    'Serbian (Cyrillic, with guillemets)': 'RS (Alternatequotes)',
    'Serbian (Cyrillic, ZE and ZHE swapped)': 'RS (Yz)',
    'Serbian (Latin, QWERTY)': 'RS (Latinyz)',
    'Serbian (Latin, Unicode, QWERTY)': 'RS (Latinunicodeyz)',
    'Serbian (Latin, Unicode)': 'RS (Latinunicode)',
    'Serbian (Latin, with guillemets)': 'RS (Latinalternatequotes)',
    'Serbian (Latin)': 'RS (Latin)',
    'Serbian (Russia)': 'RU (Srp)',
    'Serbo-Croatian (US)': 'US (Hbs)',
    Shan: 'MM (Shn)',
    'Shan (Zawgyi Tai)': 'MM (Zgt)',
    Sicilian: 'IT (Scn)',
    Silesian: 'PL (Szl)',
    Sindhi: 'PK (Snd)',
    'Sinhala (phonetic)': 'LK',
    'Sinhala (US)': 'LK (Us)',
    Slovak: 'SK',
    'Slovak (extended backslash)': 'SK (Bksl)',
    'Slovak (QWERTY, extended backslash)': 'SK (Qwerty Bksl)',
    'Slovak (QWERTY)': 'SK (Qwerty)',
    Slovenian: 'SI',
    'Slovenian (US)': 'SI (Us)',
    'Slovenian (with guillemets)': 'SI (Alternatequotes)',
    Spanish: 'ES',
    'Spanish (dead tilde)': 'ES (Deadtilde)',
    'Spanish (Dvorak)': 'ES (Dvorak)',
    'Spanish (Latin American, Colemak)': 'LATAM (Colemak)',
    'Spanish (Latin American, dead tilde)': 'LATAM (Deadtilde)',
    'Spanish (Latin American, Dvorak)': 'LATAM (Dvorak)',
    'Spanish (Latin American, no dead keys)': 'LATAM (Nodeadkeys)',
    'Spanish (Latin American)': 'LATAM',
    'Spanish (Macintosh)': 'ES (Mac)',
    'Spanish (no dead keys)': 'ES (Nodeadkeys)',
    'Spanish (Windows)': 'ES (Winkeys)',
    'Swahili (Kenya)': 'KE',
    'Swahili (Tanzania)': 'TZ',
    Swedish: 'SE',
    'Swedish (Dvorak, intl.)': 'SE (Us Dvorak)',
    'Swedish (Dvorak)': 'SE (Dvorak)',
    'Swedish (Macintosh)': 'SE (Mac)',
    'Swedish (no dead keys)': 'SE (Nodeadkeys)',
    'Swedish (Svdvorak)': 'SE (Svdvorak)',
    'Swedish (US)': 'SE (Us)',
    'Swedish Sign Language': 'SE (Swl)',
    Syriac: 'SY (Syc)',
    'Syriac (phonetic)': 'SY (Syc Phonetic)',
    Taiwanese: 'TW',
    'Taiwanese (indigenous)': 'TW (Indigenous)',
    Tajik: 'TJ',
    'Tajik (legacy)': 'TJ (Legacy)',
    'Tamil (InScript, with Arabic numerals)': 'IN (Tam)',
    'Tamil (InScript, with Tamil numerals)': 'IN (Tam Tamilnumbers)',
    "Tamil (Sri Lanka, TamilNet '99, TAB encoding)": 'LK (Tam TAB)',
    "Tamil (Sri Lanka, TamilNet '99)": 'LK (Tam Unicode)',
    "Tamil (TamilNet '99 with Tamil numerals)": 'IN (Tamilnet Tamilnumbers)',
    "Tamil (TamilNet '99, TAB encoding)": 'IN (Tamilnet TAB)',
    "Tamil (TamilNet '99, TSCII encoding)": 'IN (Tamilnet TSCII)',
    "Tamil (TamilNet '99)": 'IN (Tamilnet)',
    Tarifit: 'MA (Rif)',
    Tatar: 'RU (Tt)',
    Telugu: 'IN (Tel)',
    'Telugu (KaGaPa, phonetic)': 'IN (Tel-Kagapa)',
    'Telugu (Sarala)': 'IN (Tel-Sarala)',
    Thai: 'TH',
    'Thai (Pattachote)': 'TH (Pat)',
    'Thai (TIS-820.2538)': 'TH (Tis)',
    Tibetan: 'CN (Tib)',
    'Tibetan (with ASCII numerals)': 'CN (Tib Asciinum)',
    Tswana: 'BW',
    Turkish: 'TR',
    'Turkish (Alt-Q)': 'TR (Alt)',
    'Turkish (E)': 'TR (E)',
    'Turkish (F)': 'TR (F)',
    'Turkish (Germany)': 'DE (Tr)',
    'Turkish (intl., with dead keys)': 'TR (Intl)',
    Turkmen: 'TM',
    'Turkmen (Alt-Q)': 'TM (Alt)',
    Udmurt: 'RU (Udm)',
    Ukrainian: 'UA',
    'Ukrainian (homophonic)': 'UA (Homophonic)',
    'Ukrainian (legacy)': 'UA (Legacy)',
    'Ukrainian (macOS)': 'UA (MacOS)',
    'Ukrainian (phonetic)': 'UA (Phonetic)',
    'Ukrainian (standard RSTU)': 'UA (Rstu)',
    'Ukrainian (typewriter)': 'UA (Typewriter)',
    'Ukrainian (Windows)': 'UA (Winkeys)',
    'Urdu (alt. phonetic)': 'IN (Urd-Phonetic3)',
    'Urdu (Pakistan, CRULP)': 'PK (Urd-Crulp)',
    'Urdu (Pakistan, NLA)': 'PK (Urd-Nla)',
    'Urdu (Pakistan)': 'PK',
    'Urdu (phonetic)': 'IN (Urd-Phonetic)',
    'Urdu (Windows)': 'IN (Urd-Winkeys)',
    Uyghur: 'CN (Ug)',
    Uzbek: 'UZ',
    'Uzbek (Afghanistan, OLPC)': 'AF (Uz-Olpc)',
    'Uzbek (Afghanistan)': 'AF (Uz)',
    'Uzbek (Latin)': 'UZ (Latin)',
    Vietnamese: 'VN',
    'Vietnamese (France)': 'VN (Fr)',
    'Vietnamese (US)': 'VN (Us)',
    Wolof: 'SN',
    Yakut: 'RU (Sah)',
    Yoruba: 'NG (Yoruba)',
    'Unknown Layout': 'Unknown',
} as const;


================================================
FILE: .config/ags/customModules/module.ts
================================================
import { BarBoxChild, Module } from 'lib/types/bar';
import { BarButtonStyles } from 'lib/types/options';
import { Bind } from 'lib/types/variable';
import { GtkWidget } from 'lib/types/widget';
import options from 'options';
import Gtk from 'types/@girs/gtk-3.0/gtk-3.0';

const { style } = options.theme.bar.buttons;

const undefinedVar = Variable(undefined);

export const module = ({
    icon,
    textIcon,
    label,
    tooltipText,
    boxClass,
    props = {},
    showLabelBinding = undefinedVar.bind('value'),
    showLabel,
    labelHook,
    hook,
}: Module): BarBoxChild => {
    const getIconWidget = (): GtkWidget | undefined => {
        let iconWidget: Gtk.Widget | undefined;

        if (icon !== undefined) {
            iconWidget = Widget.Icon({
                class_name: `txt-icon bar-button-icon module-icon ${boxClass}`,
                icon: icon,
            }) as unknown as Gtk.Widget;
        } else if (textIcon !== undefined) {
            iconWidget = Widget.Label({
                class_name: `txt-icon bar-button-icon module-icon ${boxClass}`,
                label: textIcon,
            }) as unknown as Gtk.Widget;
        }

        return iconWidget;
    };

    return {
        component: Widget.Box({
            className: Utils.merge(
                [style.bind('value'), showLabelBinding],
                (style: BarButtonStyles, shwLabel: boolean) => {
                    const shouldShowLabel = shwLabel || showLabel;
                    const styleMap = {
                        default: 'style1',
                        split: 'style2',
                        wave: 'style3',
                        wave2: 'style3',
                    };
                    return `${boxClass} ${styleMap[style]} ${!shouldShowLabel ? 'no-label' : ''}`;
                },
            ),
            tooltip_text: tooltipText,
            children: Utils.merge([showLabelBinding], (showLabelBinding): Gtk.Widget[] => {
                const childrenArray: Gtk.Widget[] = [];
                const iconWidget = getIconWidget();

                if (iconWidget !== undefined) {
                    childrenArray.push(iconWidget);
                }

                if (showLabelBinding) {
                    childrenArray.push(
                        Widget.Label({
                            class_name: `bar-button-label module-label ${boxClass}`,
                            label: label,
                            setup: labelHook,
                        }) as unknown as Gtk.Widget,
                    );
                }
                return childrenArray;
            }) as Bind,
            setup: hook,
        }),
        tooltip_text: tooltipText,
        isVisible: true,
        boxClass,
        props,
    };
};


================================================
FILE: .config/ags/customModules/netstat/computeNetwork.ts
================================================
import GLib from 'gi://GLib';
import { Variable as VariableType } from 'types/variable';
import { NetworkResourceData } from 'lib/types/customModules/network';
import { GET_DEFAULT_NETSTAT_DATA } from 'lib/types/defaults/netstat';
import { RateUnit } from 'lib/types/bar';

let previousNetUsage = { rx: 0, tx: 0, time: 0 };

const formatRate = (rate: number, type: string, round: boolean): string => {
    const fixed = round ? 0 : 2;

    switch (true) {
        case type === 'KiB':
            return `${(rate / 1e3).toFixed(fixed)} KiB/s`;
        case type === 'MiB':
            return `${(rate / 1e6).toFixed(fixed)} MiB/s`;
        case type === 'GiB':
            return `${(rate / 1e9).toFixed(fixed)} GiB/s`;
        case rate >= 1e9:
            return `${(rate / 1e9).toFixed(fixed)} GiB/s`;
        case rate >= 1e6:
            return `${(rate / 1e6).toFixed(fixed)} MiB/s`;
        case rate >= 1e3:
            return `${(rate / 1e3).toFixed(fixed)} KiB/s`;
        default:
            return `${rate.toFixed(fixed)} bytes/s`;
    }
};

interface NetworkUsage {
    name: string;
    rx: number;
    tx: number;
}

const parseInterfaceData = (line: string): NetworkUsage | null => {
    const trimmedLine = line.trim();
    if (!trimmedLine || trimmedLine.startsWith('Inter-') || trimmedLine.startsWith('face')) {
        return null;
    }

    const [iface, rx, , , , , , , , tx] = trimmedLine.split(/\s+/);
    const rxValue = parseInt(rx, 10);
    const txValue = parseInt(tx, 10);
    const cleanedIface = iface.replace(':', '');

    return { name: cleanedIface, rx: rxValue, tx: txValue };
};

const isValidInterface = (iface: NetworkUsage | null, interfaceName: string): boolean => {
    if (!iface) return false;
    if (interfaceName) return iface.name === interfaceName;
    return iface.name !== 'lo' && iface.rx > 0 && iface.tx > 0;
};

const getNetworkUsage = (interfaceName: string = ''): NetworkUsage => {
    const [success, data] = GLib.file_get_contents('/proc/net/dev');
    if (!success) {
        console.error('Failed to read /proc/net/dev');
        return { name: '', rx: 0, tx: 0 };
    }

    const lines = new TextDecoder('utf-8').decode(data).split('\n');
    for (const line of lines) {
        const iface = parseInterfaceData(line);
        if (isValidInterface(iface, interfaceName)) {
            return iface!;
        }
    }

    return { name: '', rx: 0, tx: 0 };
};

export const computeNetwork = (
    round: VariableType<boolean>,
    interfaceNameVar: VariableType<string>,
    dataType: VariableType<RateUnit>,
): NetworkResourceData => {
    const rateUnit = dataType.value;
    const interfaceName = interfaceNameVar ? interfaceNameVar.value : '';

    const DEFAULT_NETSTAT_DATA = GET_DEFAULT_NETSTAT_DATA(rateUnit);
    try {
        const { rx, tx, name } = getNetworkUsage(interfaceName);
        const currentTime = Date.now();

        if (!name) {
            return DEFAULT_NETSTAT_DATA;
        }

        if (previousNetUsage.time === 0) {
            previousNetUsage = { rx, tx, time: currentTime };
            return DEFAULT_NETSTAT_DATA;
        }

        const timeDiff = Math.max((currentTime - previousNetUsage.time) / 1000, 1);
        const rxRate = (rx - previousNetUsage.rx) / timeDiff;
        const txRate = (tx - previousNetUsage.tx) / timeDiff;

        previousNetUsage = { rx, tx, time: currentTime };

        return {
            in: formatRate(rxRate, rateUnit, round.value),
            out: formatRate(txRate, rateUnit, round.value),
        };
    } catch (error) {
        console.error('Error calculating network usage:', error);
        return DEFAULT_NETSTAT_DATA;
    }
};


================================================
FILE: .config/ags/customModules/netstat/index.ts
================================================
import options from 'options';
import { module } from '../module';
import { inputHandler } from 'customModules/utils';
import { computeNetwork } from './computeNetwork';
import { BarBoxChild, NetstatLabelType } from 'lib/types/bar';
import Button from 'types/widgets/button';
import { NetworkResourceData } from 'lib/types/customModules/network';
import { NETWORK_LABEL_TYPES } from 'lib/types/defaults/bar';
import { GET_DEFAULT_NETSTAT_DATA } from 'lib/types/defaults/netstat';
import { pollVariable } from 'customModules/PollVar';
import { Attribute, Child } from 'lib/types/widget';

const {
    label,
    labelType,
    networkInterface,
    rateUnit,
    icon,
    round,
    leftClick,
    rightClick,
    middleClick,
    pollingInterval,
} = options.bar.customModules.netstat;

export const networkUsage = Variable<NetworkResourceData>(GET_DEFAULT_NETSTAT_DATA(rateUnit.value));

pollVariable(
    // Variable to poll and update with the result of the function passed in
    networkUsage,
    // Variables that should trigger the polling function to update when they change
    [rateUnit.bind('value'), networkInterface.bind('value'), round.bind('value')],
    // Interval at which to poll
    pollingInterval.bind('value'),
    // Function to execute to get the network data
    computeNetwork,
    // Optional parameters to pass to the function
    // round is a boolean that determines whether to round the values
    round,
    // Optional parameters to pass to the function
    // networkInterface is the interface name to filter the data
    networkInterface,
    // Optional parameters to pass to the function
    // rateUnit is the unit to display the data in
    // e.g. KiB, MiB, GiB, etc.
    rateUnit,
);

export const Netstat = (): BarBoxChild => {
    const renderNetworkLabel = (lblType: NetstatLabelType, network: NetworkResourceData): string => {
        switch (lblType) {
            case 'in':
                return `↓ ${network.in}`;
            case 'out':
                return `↑ ${network.out}`;
            default:
                return `↓ ${network.in} ↑ ${network.out}`;
        }
    };

    const netstatModule = module({
        textIcon: icon.bind('value'),
        label: Utils.merge(
            [networkUsage.bind('value'), labelType.bind('value')],
            (network: NetworkResourceData, lblTyp: NetstatLabelType) => renderNetworkLabel(lblTyp, network),
        ),
        tooltipText: labelType.bind('value').as((lblTyp) => {
            return lblTyp === 'full' ? 'Ingress / Egress' : lblTyp === 'in' ? 'Ingress' : 'Egress';
        }),
        boxClass: 'netstat',
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        fn: () => {
                            labelType.value = NETWORK_LABEL_TYPES[
                                (NETWORK_LABEL_TYPES.indexOf(labelType.value) + 1) % NETWORK_LABEL_TYPES.length
                            ] as NetstatLabelType;
                        },
                    },
                    onScrollDown: {
                        fn: () => {
                            labelType.value = NETWORK_LABEL_TYPES[
                                (NETWORK_LABEL_TYPES.indexOf(labelType.value) - 1 + NETWORK_LABEL_TYPES.length) %
                                    NETWORK_LABEL_TYPES.length
                            ] as NetstatLabelType;
                        },
                    },
                });
            },
        },
    });

    return netstatModule;
};


================================================
FILE: .config/ags/customModules/power/index.ts
================================================
import options from 'options';
import { module } from '../module';

import { inputHandler } from 'customModules/utils';
import Button from 'types/widgets/button';
import { Attribute, Child } from 'lib/types/widget';
import { BarBoxChild } from 'lib/types/bar';

const { icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } = options.bar.customModules.power;

export const Power = (): BarBoxChild => {
    const powerModule = module({
        tooltipText: 'Power Menu',
        textIcon: icon.bind('value'),
        boxClass: 'powermodule',
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return powerModule;
};


================================================
FILE: .config/ags/customModules/ram/computeRam.ts
================================================
const GLib = imports.gi.GLib;

import { divide } from 'customModules/utils';
import { GenericResourceData } from 'lib/types/customModules/generic';
import { Variable as VariableType } from 'types/variable';

// FIX: Consolidate with Ram service class
export const calculateRamUsage = (round: VariableType<boolean>): GenericResourceData => {
    try {
        const [success, meminfoBytes] = GLib.file_get_contents('/proc/meminfo');

        if (!success || !meminfoBytes) {
            throw new Error('Failed to read /proc/meminfo or file content is null.');
        }

        const meminfo = new TextDecoder('utf-8').decode(meminfoBytes);

        const totalMatch = meminfo.match(/MemTotal:\s+(\d+)/);
        const availableMatch = meminfo.match(/MemAvailable:\s+(\d+)/);

        if (!totalMatch || !availableMatch) {
            throw new Error('Failed to parse /proc/meminfo for memory values.');
        }

        const totalRamInBytes = parseInt(totalMatch[1], 10) * 1024;
        const availableRamInBytes = parseInt(availableMatch[1], 10) * 1024;

        let usedRam = totalRamInBytes - availableRamInBytes;
        usedRam = isNaN(usedRam) || usedRam < 0 ? 0 : usedRam;

        return {
            percentage: divide([totalRamInBytes, usedRam], round.value),
            total: totalRamInBytes,
            used: usedRam,
            free: availableRamInBytes,
        };
    } catch (error) {
        console.error('Error calculating RAM usage:', error);
        return { total: 0, used: 0, percentage: 0, free: 0 };
    }
};


================================================
FILE: .config/ags/customModules/ram/index.ts
================================================
import options from 'options';

// Module initializer
import { module } from '../module';

// Types
import { GenericResourceData } from 'lib/types/customModules/generic';
import Button from 'types/widgets/button';

// Helper Methods
import { calculateRamUsage } from './computeRam';

// Utility Methods
import { formatTooltip, inputHandler, renderResourceLabel } from 'customModules/utils';
import { BarBoxChild, ResourceLabelType } from 'lib/types/bar';

// Global Constants
import { LABEL_TYPES } from 'lib/types/defaults/bar';
import { pollVariable } from 'customModules/PollVar';
import { Attribute, Child } from 'lib/types/widget';

// All the user configurable options for the ram module that are needed
const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval, icon } =
    options.bar.customModules.ram;

const defaultRamData: GenericResourceData = { total: 0, used: 0, percentage: 0, free: 0 };
const ramUsage = Variable<GenericResourceData>(defaultRamData);

pollVariable(ramUsage, [round.bind('value')], pollingInterval.bind('value'), calculateRamUsage, round);

export const Ram = (): BarBoxChild => {
    const ramModule = module({
        textIcon: icon.bind('value'),
        label: Utils.merge(
            [ramUsage.bind('value'), labelType.bind('value'), round.bind('value')],
            (rmUsg: GenericResourceData, lblTyp: ResourceLabelType, round: boolean) => {
                const returnValue = renderResourceLabel(lblTyp, rmUsg, round);

                return returnValue;
            },
        ),
        tooltipText: labelType.bind('value').as((lblTyp) => {
            return formatTooltip('RAM', lblTyp);
        }),
        boxClass: 'ram',
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        fn: () => {
                            labelType.value = LABEL_TYPES[
                                (LABEL_TYPES.indexOf(labelType.value) + 1) % LABEL_TYPES.length
                            ] as ResourceLabelType;
                        },
                    },
                    onScrollDown: {
                        fn: () => {
                            labelType.value = LABEL_TYPES[
                                (LABEL_TYPES.indexOf(labelType.value) - 1 + LABEL_TYPES.length) % LABEL_TYPES.length
                            ] as ResourceLabelType;
                        },
                    },
                });
            },
        },
    });

    return ramModule;
};


================================================
FILE: .config/ags/customModules/storage/computeStorage.ts
================================================
// @ts-expect-error is a special directive that tells the compiler to use the GTop library
import GTop from 'gi://GTop';

import { divide } from 'customModules/utils';
import { Variable as VariableType } from 'types/variable';
import { GenericResourceData } from 'lib/types/customModules/generic';

// FIX: Consolidate with Storage service class
export const computeStorage = (round: VariableType<boolean>): GenericResourceData => {
    try {
        const currentFsUsage = new GTop.glibtop_fsusage();

        GTop.glibtop_get_fsusage(currentFsUsage, '/');

        const total = currentFsUsage.blocks * currentFsUsage.block_size;
        const available = currentFsUsage.bavail * currentFsUsage.block_size;
        const used = total - available;

        return {
            total,
            used,
            free: available,
            percentage: divide([total, used], round.value),
        };
    } catch (error) {
        console.error('Error calculating RAM usage:', error);
        return { total: 0, used: 0, percentage: 0, free: 0 };
    }
};


================================================
FILE: .config/ags/customModules/storage/index.ts
================================================
import options from 'options';
import { module } from '../module';

import { formatTooltip, inputHandler, renderResourceLabel } from 'customModules/utils';
import { computeStorage } from './computeStorage';
import { BarBoxChild, ResourceLabelType } from 'lib/types/bar';
import { GenericResourceData } from 'lib/types/customModules/generic';
import Button from 'types/widgets/button';
import { LABEL_TYPES } from 'lib/types/defaults/bar';
import { pollVariable } from 'customModules/PollVar';
import { Attribute, Child } from 'lib/types/widget';

const { label, labelType, icon, round, leftClick, rightClick, middleClick, pollingInterval } =
    options.bar.customModules.storage;

const defaultStorageData = { total: 0, used: 0, percentage: 0, free: 0 };

const storageUsage = Variable<GenericResourceData>(defaultStorageData);

pollVariable(storageUsage, [round.bind('value')], pollingInterval.bind('value'), computeStorage, round);

export const Storage = (): BarBoxChild => {
    const storageModule = module({
        textIcon: icon.bind('value'),
        label: Utils.merge(
            [storageUsage.bind('value'), labelType.bind('value'), round.bind('value')],
            (storage: GenericResourceData, lblTyp: ResourceLabelType, round: boolean) => {
                return renderResourceLabel(lblTyp, storage, round);
            },
        ),
        tooltipText: labelType.bind('value').as((lblTyp) => {
            return formatTooltip('Storage', lblTyp);
        }),
        boxClass: 'storage',
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        fn: () => {
                            labelType.value = LABEL_TYPES[
                                (LABEL_TYPES.indexOf(labelType.value) + 1) % LABEL_TYPES.length
                            ] as ResourceLabelType;
                        },
                    },
                    onScrollDown: {
                        fn: () => {
                            labelType.value = LABEL_TYPES[
                                (LABEL_TYPES.indexOf(labelType.value) - 1 + LABEL_TYPES.length) % LABEL_TYPES.length
                            ] as ResourceLabelType;
                        },
                    },
                });
            },
        },
    });

    return storageModule;
};


================================================
FILE: .config/ags/customModules/submap/helpers.ts
================================================
import { Variable } from 'types/variable';

const hyprland = await Service.import('hyprland');

export const isSubmapEnabled = (submap: string, enabled: string, disabled: string): string => {
    return submap !== 'default' ? enabled : disabled;
};

export const getInitialSubmap = (submapStatus: Variable<string>): void => {
    let submap = hyprland.message('submap');

    const newLineCarriage = /\n/g;
    submap = submap.replace(newLineCarriage, '');

    if (submap === 'unknown request') {
        submap = 'default';
    }

    submapStatus.value = submap;
};


================================================
FILE: .config/ags/customModules/submap/index.ts
================================================
const hyprland = await Service.import('hyprland');
import options from 'options';
import { module } from '../module';

import { inputHandler } from 'customModules/utils';
import Button from 'types/widgets/button';
import { Variable as VariableType } from 'types/variable';
import { Attribute, Child } from 'lib/types/widget';
import { BarBoxChild } from 'lib/types/bar';
import { capitalizeFirstLetter } from 'lib/utils';
import { getInitialSubmap, isSubmapEnabled } from './helpers';

const {
    label,
    showSubmapName,
    enabledIcon,
    disabledIcon,
    enabledText,
    disabledText,
    leftClick,
    rightClick,
    middleClick,
    scrollUp,
    scrollDown,
} = options.bar.customModules.submap;

const submapStatus: VariableType<string> = Variable('default');

hyprland.connect('submap', (_, currentSubmap) => {
    if (currentSubmap.length === 0) {
        submapStatus.value = 'default';
    } else {
        submapStatus.value = currentSubmap;
    }
});

getInitialSubmap(submapStatus);

export const Submap = (): BarBoxChild => {
    const submapModule = module({
        textIcon: Utils.merge(
            [submapStatus.bind('value'), enabledIcon.bind('value'), disabledIcon.bind('value')],
            (status, enabled, disabled) => {
                return isSubmapEnabled(status, enabled, disabled);
            },
        ),
        tooltipText: Utils.merge(
            [
                submapStatus.bind('value'),
                enabledText.bind('value'),
                disabledText.bind('value'),
                showSubmapName.bind('value'),
            ],
            (status, enabled, disabled, showSmName) => {
                if (showSmName) {
                    return capitalizeFirstLetter(status);
                }
                return isSubmapEnabled(status, enabled, disabled);
            },
        ),
        boxClass: 'submap',
        label: Utils.merge(
            [
                submapStatus.bind('value'),
                enabledText.bind('value'),
                disabledText.bind('value'),
                showSubmapName.bind('value'),
            ],
            (status, enabled, disabled, showSmName) => {
                if (showSmName) {
                    return capitalizeFirstLetter(status);
                }
                return isSubmapEnabled(status, enabled, disabled);
            },
        ),
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return submapModule;
};


================================================
FILE: .config/ags/customModules/theme.ts
================================================
import { Option } from 'widget/settings/shared/Option';
import { Header } from 'widget/settings/shared/Header';

import options from 'options';
import Scrollable from 'types/widgets/scrollable';
import { Attribute, GtkWidget } from 'lib/types/widget';

export const CustomModuleTheme = (): Scrollable<GtkWidget, Attribute> => {
    return Widget.Scrollable({
        vscroll: 'automatic',
        hscroll: 'automatic',
        class_name: 'menu-theme-page customModules paged-container',
        child: Widget.Box({
            class_name: 'bar-theme-page paged-container',
            vertical: true,
            children: [
                Header('RAM'),
                Option({ opt: options.theme.bar.buttons.modules.ram.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.ram.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.ram.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.ram.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.ram.border, title: 'Border', type: 'color' }),

                Header('CPU'),
                Option({ opt: options.theme.bar.buttons.modules.cpu.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.cpu.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.cpu.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.cpu.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.cpu.border, title: 'Border', type: 'color' }),

                Header('Storage'),
                Option({ opt: options.theme.bar.buttons.modules.storage.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.storage.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.storage.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.storage.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.storage.border, title: 'Border', type: 'color' }),

                Header('Netstat'),
                Option({ opt: options.theme.bar.buttons.modules.netstat.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.netstat.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.netstat.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.netstat.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.netstat.border, title: 'Border', type: 'color' }),

                Header('Keyboard Layout'),
                Option({ opt: options.theme.bar.buttons.modules.kbLayout.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.kbLayout.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.kbLayout.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.kbLayout.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.kbLayout.border, title: 'Border', type: 'color' }),

                Header('Updates'),
                Option({ opt: options.theme.bar.buttons.modules.updates.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.updates.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.updates.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.updates.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.updates.border, title: 'Border', type: 'color' }),

                Header('Submap'),
                Option({ opt: options.theme.bar.buttons.modules.submap.text, title: 'Text', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.submap.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.submap.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.submap.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.submap.border, title: 'Border', type: 'color' }),

                Header('Weather'),
                Option({ opt: options.theme.bar.buttons.modules.weather.icon, title: 'Icon', type: 'color' }),
                Option({ opt: options.theme.bar.buttons.modules.weather.text, title: 'Text', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.weather.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.weather.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.weather.border, title: 'Border', type: 'color' }),

                Header('Power'),
                Option({ opt: options.theme.bar.buttons.modules.power.icon, title: 'Icon', type: 'color' }),
                Option({
                    opt: options.theme.bar.buttons.modules.power.background,
                    title: 'Label Background',
                    type: 'color',
                }),
                Option({
                    opt: options.theme.bar.buttons.modules.power.icon_background,
                    title: 'Icon Background',
                    subtitle:
                        "Applies a background color to the icon section of the button.\nRequires 'split' button styling.",
                    type: 'color',
                }),
                Option({ opt: options.theme.bar.buttons.modules.power.border, title: 'Border', type: 'color' }),
            ],
        }),
    });
};


================================================
FILE: .config/ags/customModules/updates/index.ts
================================================
import options from 'options';
import { module } from '../module';

import { inputHandler } from 'customModules/utils';
import Button from 'types/widgets/button';
import { Variable as VariableType } from 'types/variable';
import { pollVariableBash } from 'customModules/PollVar';
import { Attribute, Child } from 'lib/types/widget';
import { BarBoxChild } from 'lib/types/bar';

const {
    updateCommand,
    label,
    padZero,
    pollingInterval,
    icon,
    leftClick,
    rightClick,
    middleClick,
    scrollUp,
    scrollDown,
} = options.bar.customModules.updates;

const pendingUpdates: VariableType<string> = Variable(' 0');

const processUpdateCount = (updateCount: string): string => {
    if (!padZero.value) return updateCount;
    return `${updateCount.padStart(2, '0')}`;
};

pollVariableBash(
    pendingUpdates,
    [padZero.bind('value')],
    pollingInterval.bind('value'),
    updateCommand.value,
    processUpdateCount,
);

export const Updates = (): BarBoxChild => {
    const updatesModule = module({
        textIcon: icon.bind('value'),
        tooltipText: pendingUpdates.bind('value').as((v) => `${v} updates available`),
        boxClass: 'updates',
        label: pendingUpdates.bind('value'),
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return updatesModule;
};


================================================
FILE: .config/ags/customModules/utils.ts
================================================
import { ResourceLabelType } from 'lib/types/bar';
import { GenericResourceData, Postfix } from 'lib/types/customModules/generic';
import { InputHandlerEvents, RunAsyncCommand } from 'lib/types/customModules/utils';
import { ThrottleFn, ThrottleFnCallback } from 'lib/types/utils';
import { Attribute, Child, EventArgs } from 'lib/types/widget';
import { Binding } from 'lib/utils';
import { openMenu } from 'modules/bar/utils';
import options from 'options';
import Gdk from 'types/@girs/gdk-3.0/gdk-3.0';
import { Variable as VariableType } from 'types/variable';
import Button from 'types/widgets/button';

const { scrollSpeed } = options.bar.customModules;

export const runAsyncCommand: RunAsyncCommand = (cmd, events, fn): void => {
    if (cmd.startsWith('menu:')) {
        const menuName = cmd.split(':')[1].trim().toLowerCase();
        openMenu(events.clicked, events.event, `${menuName}menu`);

        return;
    }

    Utils.execAsync(`bash -c "${cmd}"`)
        .then((output) => {
            if (fn !== undefined) {
                fn(output);
            }
        })
        .catch((err) => console.error(`Error running command "${cmd}": ${err})`));
};

export function throttle<T extends ThrottleFn>(func: T, limit: number): T {
    let inThrottle: boolean;
    return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => {
                inThrottle = false;
            }, limit);
        }
    } as T;
}

export const throttledScrollHandler = (interval: number): ThrottleFn =>
    throttle((cmd: string, events: EventArgs, fn: ThrottleFnCallback) => {
        runAsyncCommand(cmd, events, fn);
    }, 200 / interval);

const dummyVar = Variable('');

export const inputHandler = (
    self: Button<Child, Attribute>,
    { onPrimaryClick, onSecondaryClick, onMiddleClick, onScrollUp, onScrollDown }: InputHandlerEvents,
): void => {
    const sanitizeInput = (input: VariableType<string>): string => {
        if (input === undefined) {
            return '';
        }
        return input.value;
    };

    const updateHandlers = (): void => {
        const interval = scrollSpeed.value;
        const throttledHandler = throttledScrollHandler(interval);

        self.on_primary_click = (clicked: Button<Child, Attribute>, event: Gdk.Event): void =>
            runAsyncCommand(sanitizeInput(onPrimaryClick?.cmd || dummyVar), { clicked, event }, onPrimaryClick.fn);

        self.on_secondary_click = (clicked: Button<Child, Attribute>, event: Gdk.Event): void =>
            runAsyncCommand(sanitizeInput(onSecondaryClick?.cmd || dummyVar), { clicked, event }, onSecondaryClick.fn);

        self.on_middle_click = (clicked: Button<Child, Attribute>, event: Gdk.Event): void =>
            runAsyncCommand(sanitizeInput(onMiddleClick?.cmd || dummyVar), { clicked, event }, onMiddleClick.fn);

        self.on_scroll_up = (clicked: Button<Child, Attribute>, event: Gdk.Event): void =>
            throttledHandler(sanitizeInput(onScrollUp?.cmd || dummyVar), { clicked, event }, onScrollUp.fn);

        self.on_scroll_down = (clicked: Button<Child, Attribute>, event: Gdk.Event): void =>
            throttledHandler(sanitizeInput(onScrollDown?.cmd || dummyVar), { clicked, event }, onScrollDown.fn);
    };

    // Initial setup of event handlers
    updateHandlers();

    const sanitizeVariable = (someVar: VariableType<string> | undefined): Binding<string> => {
        if (someVar === undefined || typeof someVar.bind !== 'function') {
            return dummyVar.bind('value');
        }
        return someVar.bind('value');
    };

    // Re-run the update whenever scrollSpeed changes
    Utils.merge(
        [
            scrollSpeed.bind('value'),
            sanitizeVariable(onPrimaryClick),
            sanitizeVariable(onSecondaryClick),
            sanitizeVariable(onMiddleClick),
            sanitizeVariable(onScrollUp),
            sanitizeVariable(onScrollDown),
        ],
        updateHandlers,
    );
};

export const divide = ([total, used]: number[], round: boolean): number => {
    const percentageTotal = (used / total) * 100;
    if (round) {
        return total > 0 ? Math.round(percentageTotal) : 0;
    }
    return total > 0 ? parseFloat(percentageTotal.toFixed(2)) : 0;
};

export const formatSizeInKiB = (sizeInBytes: number, round: boolean): number => {
    const sizeInGiB = sizeInBytes / 1024 ** 1;
    return round ? Math.round(sizeInGiB) : parseFloat(sizeInGiB.toFixed(2));
};
export const formatSizeInMiB = (sizeInBytes: number, round: boolean): number => {
    const sizeInGiB = sizeInBytes / 1024 ** 2;
    return round ? Math.round(sizeInGiB) : parseFloat(sizeInGiB.toFixed(2));
};
export const formatSizeInGiB = (sizeInBytes: number, round: boolean): number => {
    const sizeInGiB = sizeInBytes / 1024 ** 3;
    return round ? Math.round(sizeInGiB) : parseFloat(sizeInGiB.toFixed(2));
};
export const formatSizeInTiB = (sizeInBytes: number, round: boolean): number => {
    const sizeInGiB = sizeInBytes / 1024 ** 4;
    return round ? Math.round(sizeInGiB) : parseFloat(sizeInGiB.toFixed(2));
};

export const autoFormatSize = (sizeInBytes: number, round: boolean): number => {
    // auto convert to GiB, MiB, KiB, TiB, or bytes
    if (sizeInBytes >= 1024 ** 4) return formatSizeInTiB(sizeInBytes, round);
    if (sizeInBytes >= 1024 ** 3) return formatSizeInGiB(sizeInBytes, round);
    if (sizeInBytes >= 1024 ** 2) return formatSizeInMiB(sizeInBytes, round);
    if (sizeInBytes >= 1024 ** 1) return formatSizeInKiB(sizeInBytes, round);

    return sizeInBytes;
};

export const getPostfix = (sizeInBytes: number): Postfix => {
    if (sizeInBytes >= 1024 ** 4) return 'TiB';
    if (sizeInBytes >= 1024 ** 3) return 'GiB';
    if (sizeInBytes >= 1024 ** 2) return 'MiB';
    if (sizeInBytes >= 1024 ** 1) return 'KiB';

    return 'B';
};

export const renderResourceLabel = (lblType: ResourceLabelType, rmUsg: GenericResourceData, round: boolean): string => {
    const { used, total, percentage, free } = rmUsg;

    const formatFunctions = {
        TiB: formatSizeInTiB,
        GiB: formatSizeInGiB,
        MiB: formatSizeInMiB,
        KiB: formatSizeInKiB,
        B: (size: number): number => size,
    };

    // Get the data in proper GiB, MiB, KiB, TiB, or bytes
    const totalSizeFormatted = autoFormatSize(total, round);
    // get the postfix: one of [TiB, GiB, MiB, KiB, B]
    const postfix = getPostfix(total);

    // Determine which format function to use
    const formatUsed = formatFunctions[postfix] || formatFunctions['B'];
    const usedSizeFormatted = formatUsed(used, round);

    if (lblType === 'used/total') {
        return `${usedSizeFormatted}/${totalSizeFormatted} ${postfix}`;
    }
    if (lblType === 'used') {
        return `${autoFormatSize(used, round)} ${getPostfix(used)}`;
    }
    if (lblType === 'free') {
        return `${autoFormatSize(free, round)} ${getPostfix(free)}`;
    }

    return `${percentage}%`;
};

export const formatTooltip = (dataType: string, lblTyp: ResourceLabelType): string => {
    switch (lblTyp) {
        case 'used':
            return `Used ${dataType}`;
        case 'free':
            return `Free ${dataType}`;
        case 'used/total':
            return `Used/Total ${dataType}`;
        case 'percentage':
            return `Percentage ${dataType} Usage`;
        default:
            return '';
    }
};


================================================
FILE: .config/ags/customModules/weather/index.ts
================================================
import options from 'options';
import { module } from '../module';

import { inputHandler } from 'customModules/utils';
import Button from 'types/widgets/button';
import { getWeatherStatusTextIcon, globalWeatherVar } from 'globals/weather';
import { Attribute, Child } from 'lib/types/widget';
import { BarBoxChild } from 'lib/types/bar';

const { label, unit, leftClick, rightClick, middleClick, scrollUp, scrollDown } = options.bar.customModules.weather;

export const Weather = (): BarBoxChild => {
    const weatherModule = module({
        textIcon: Utils.merge([globalWeatherVar.bind('value')], (wthr) => {
            const weatherStatusIcon = getWeatherStatusTextIcon(wthr);
            return weatherStatusIcon;
        }),
        tooltipText: globalWeatherVar.bind('value').as((v) => `Weather Status: ${v.current.condition.text}`),
        boxClass: 'weather-custom',
        label: Utils.merge([globalWeatherVar.bind('value'), unit.bind('value')], (wthr, unt) => {
            if (unt === 'imperial') {
                return `${Math.ceil(wthr.current.temp_f)}° F`;
            } else {
                return `${Math.ceil(wthr.current.temp_c)}° C`;
            }
        }),
        showLabelBinding: label.bind('value'),
        props: {
            setup: (self: Button<Child, Attribute>) => {
                inputHandler(self, {
                    onPrimaryClick: {
                        cmd: leftClick,
                    },
                    onSecondaryClick: {
                        cmd: rightClick,
                    },
                    onMiddleClick: {
                        cmd: middleClick,
                    },
                    onScrollUp: {
                        cmd: scrollUp,
                    },
                    onScrollDown: {
                        cmd: scrollDown,
                    },
                });
            },
        },
    });

    return weatherModule;
};


================================================
FILE: .config/ags/directoryMonitorService.ts
================================================
import Service from 'resource:///com/github/Aylur/ags/service.js';
import App from 'resource:///com/github/Aylur/ags/app.js';
import { monitorFile } from 'resource:///com/github/Aylur/ags/utils.js';
import Gio from 'gi://Gio';
import { FileInfo } from 'types/@girs/gio-2.0/gio-2.0.cjs';

class DirectoryMonitorService extends Service {
    static {
        Service.register(this, {}, {});
    }

    constructor() {
        super();
        this.recursiveDirectoryMonitor(`${App.configDir}/scss`);
    }

    recursiveDirectoryMonitor(directoryPath: string): void {
        monitorFile(directoryPath, (_, eventType) => {
            if (eventType === Gio.FileMonitorEvent.CHANGES_DONE_HINT) {
                this.emit('changed');
            }
        });

        const directory = Gio.File.new_for_path(directoryPath);
        const enumerator = directory.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);

        let fileInfo: FileInfo;
        while ((fileInfo = enumerator.next_file(null) as FileInfo) !== null) {
            const childPath = directoryPath + '/' + fileInfo.get_name();
            if (fileInfo.get_file_type() === Gio.FileType.DIRECTORY) {
                this.recursiveDirectoryMonitor(childPath);
            }
        }
    }
}

const service = new DirectoryMonitorService();
export default service;


================================================
FILE: .config/ags/flake.nix
================================================
{
  description = "A Bar/Panel for Hyprland with extensive customizability.";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    ags.url = "github:Aylur/ags";
  };

  outputs = inputs: let
    systems = [
      "x86_64-linux"
      "x86_64-darwin"
      "aarch64-darwin"
      "aarch64-linux"
    ];
    forEachSystem = inputs.nixpkgs.lib.genAttrs systems;
    pkgsFor = forEachSystem (
      system:
        import inputs.nixpkgs {
          inherit system;
          config.allowUnfree = true;
        }
    );

    devShellFor = system:
      inputs.nixpkgs.lib.genAttrs ["default"] (
        _:
          inputs.nixpkgs.legacyPackages.${system}.mkShell {
            buildInputs = [
              pkgsFor.${system}.esbuild
              pkgsFor.${system}.fish
              pkgsFor.${system}.typescript
              pkgsFor.${system}.bun
              pkgsFor.${system}.libnotify
              pkgsFor.${system}.dart-sass
              pkgsFor.${system}.fd
              pkgsFor.${system}.btop
              pkgsFor.${system}.bluez
              pkgsFor.${system}.libgtop
              pkgsFor.${system}.gobject-introspection
              pkgsFor.${system}.glib
              pkgsFor.${system}.bluez-tools
              pkgsFor.${system}.grimblast
              pkgsFor.${system}.gpu-screen-recorder
              pkgsFor.${system}.brightnessctl
              pkgsFor.${system}.gnome-bluetooth
              pkgsFor.${system}.python3
              pkgsFor.${system}.matugen
              inputs.ags.packages.${system}.agsWithTypes
            ];
            nativeBuildInputs = with pkgsFor.${system}; [
              nixfmt-rfc-style
              nil
            ];
            shellHook = ''
              export GDK_BACKEND=wayland
              export GI_TYPELIB_PATH=${pkgsFor.${system}.libgtop}/lib/girepository-1.0:${pkgsFor.${system}.glib}/lib/girepository-1.0:$GI_TYPELIB_PATH
            '';
          }
      );
  in {
    devShells = forEachSystem devShellFor;

    overlay = final: prev: {
      hyprpanel =
        if final ? callPackage
        then (final.callPackage ./nix {inherit inputs;}).desktop.script
        else inputs.self.packages.${prev.stdenv.system}.default;
    };
    packages = forEachSystem (
      system: let
        pkgs = pkgsFor.${system};
      in {
        default = (pkgs.callPackage ./nix {inherit inputs;}).desktop.script;
      }
    );
  };
}


================================================
FILE: .config/ags/globals/dropdown.ts
================================================
import { Variable as VariableType } from 'types/variable';

type GlobalEventBoxes = {
    [key: string]: unknown;
};
export const globalEventBoxes: VariableType<GlobalEventBoxes> = Variable({});


================================================
FILE: .config/ags/globals/mousePos.ts
================================================
import { Variable as VariableType } from 'types/variable';

const globalMousePosVar: VariableType<number[]> = Variable([0, 0]);

globalThis['globalMousePos'] = globalMousePosVar;


================================================
FILE: .config/ags/globals/network.ts
================================================
export const WIFI_STATUS_MAP = {
    unknown: 'Status Unknown',
    unmanaged: 'Unmanaged',
    unavailable: 'Unavailable',
    disconnected: 'Disconnected',
    prepare: 'Preparing Connecting',
    config: 'Connecting',
    need_auth: 'Needs Authentication',
    ip_config: 'Requesting IP',
    ip_check: 'Checking Access',
    secondaries: 'Waiting on Secondaries',
    activated: 'Connected',
    deactivating: 'Disconnecting',
    failed: 'Connection Failed',
} as const;


================================================
FILE: .config/ags/globals/notification.ts
================================================
import icons from 'modules/icons/index';
import { Notification } from 'types/service/notifications';

export const removingNotifications = Variable<boolean>(false);

export const getNotificationIcon = (app_name: string, app_icon: string, app_entry: string): string => {
    let icon: string = icons.fallback.notification;

    if (Utils.lookUpIcon(app_name) || Utils.lookUpIcon(app_name.toLowerCase() || '')) {
        icon = Utils.lookUpIcon(app_name)
            ? app_name
            : Utils.lookUpIcon(app_name.toLowerCase())
              ? app_name.toLowerCase()
              : '';
    }

    if (Utils.lookUpIcon(app_icon) && icon === '') {
        icon = app_icon;
    }

    if (Utils.lookUpIcon(app_entry || '') && icon === '') {
        icon = app_entry || '';
    }

    return icon;
};

export const closeNotifications = async (notifications: Notification[], delay: number): Promise<void> => {
    removingNotifications.value = true;
    for (const notif of notifications) {
        notif.close();
        await new Promise((resolve) => setTimeout(resolve, delay));
    }
    removingNotifications.value = false;
};

globalThis['removingNotifications'] = removingNotifications;


================================================
FILE: .config/ags/globals/useTheme.ts
================================================
import Gio from 'gi://Gio';
import { bash, Notify } from 'lib/utils';
import icons from 'lib/icons';
import { filterConfigForThemeOnly, loadJsonFile, saveConfigToFile } from 'widget/settings/shared/FileChooser';

export const hexColorPattern = /^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;

globalThis.useTheme = (filePath: string): void => {
    const importedConfig = loadJsonFile(filePath);

    if (!importedConfig) {
        return;
    }

    Notify({
        summary: `Importing Theme`,
        body: `Importing: ${filePath}`,
        iconName: icons.ui.info,
        timeout: 7000,
    });

    const tmpConfigFile = Gio.File.new_for_path(`${TMP}/config.json`);
    const optionsConfigFile = Gio.File.new_for_path(OPTIONS);

    const [tmpSuccess, tmpContent] = tmpConfigFile.load_contents(null);
    const [optionsSuccess, optionsContent] = optionsConfigFile.load_contents(null);

    if (!tmpSuccess || !optionsSuccess) {
        console.error('Failed to read existing configuration files.');
        return;
    }

    let tmpConfig = JSON.parse(new TextDecoder('utf-8').decode(tmpContent));
    let optionsConfig = JSON.parse(new TextDecoder('utf-8').decode(optionsContent));

    const filteredConfig = filterConfigForThemeOnly(importedConfig);
    tmpConfig = { ...tmpConfig, ...filteredConfig };
    optionsConfig = { ...optionsConfig, ...filteredConfig };

    saveConfigToFile(tmpConfig, `${TMP}/config.json`);
    saveConfigToFile(optionsConfig, OPTIONS);
    bash('pkill ags && ags');
};


================================================
FILE: .config/ags/globals/utilities.ts
================================================
globalThis.isWindowVisible = (windowName: string): boolean => {
    const appWindow = App.getWindow(windowName);

    if (appWindow === undefined) {
        return false;
    }
    return appWindow.visible;
};


================================================
FILE: .config/ags/globals/variables.ts
================================================
import { Opt } from 'lib/option';
import { HexColor, MatugenTheme, RecursiveOptionsObject } from 'lib/types/options';

export const isOpt = <T>(value: unknown): value is Opt<T> =>
    typeof value === 'object' && value !== null && 'value' in value && value instanceof Opt;

export const isOptString = (value: unknown): value is Opt<string> => {
    return value instanceof Opt && typeof value.value === 'string';
};

export const isOptNumber = (value: unknown): value is Opt<number> => {
    return value instanceof Opt && typeof value.value === 'number';
};

export const isOptBoolean = (value: unknown): value is Opt<boolean> => {
    return value instanceof Opt && typeof value.value === 'boolean';
};

export const isOptMatugenTheme = (value: unknown): value is Opt<MatugenTheme> => {
    return value instanceof Opt && typeof value.value === 'object' && 'specificProperty' in value.value; // Replace 'specificProperty' with an actual property of MatugenTheme
};

export const isRecursiveOptionsObject = (value: unknown): value is RecursiveOptionsObject => {
    return typeof value === 'object' && value !== null && !(value instanceof Opt);
};

export const isHexColor = (val: unknown): val is HexColor => {
    return typeof val === 'string' && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(val);
};


================================================
FILE: .config/ags/globals/weather.ts
================================================
import options from 'options';
import { UnitType, Weather, WeatherIconTitle, WeatherIcon } from 'lib/types/weather.js';
import { DEFAULT_WEATHER } from 'lib/types/defaults/weather.js';
import GLib from 'gi://GLib?version=2.0';
import { weatherIcons } from 'modules/icons/weather.js';

const { key, interval, location } = options.menus.clock.weather;

export const globalWeatherVar = Variable<Weather>(DEFAULT_WEATHER);

let weatherIntervalInstance: null | number = null;

const weatherIntervalFn = (weatherInterval: number, loc: string, weatherKey: string): void => {
    if (weatherIntervalInstance !== null) {
        GLib.source_remove(weatherIntervalInstance);
    }

    const formattedLocation = loc.replace(' ', '%20');

    weatherIntervalInstance = Utils.interval(weatherInterval, () => {
        Utils.execAsync(
            `curl "https://api.weatherapi.com/v1/forecast.json?key=${weatherKey}&q=${formattedLocation}&days=1&aqi=no&alerts=no"`,
        )
            .then((res) => {
                try {
                    if (typeof res !== 'string') {
                        return (globalWeatherVar.value = DEFAULT_WEATHER);
                    }

                    const parsedWeather = JSON.parse(res);

                    if (Object.keys(parsedWeather).includes('error')) {
                        return (globalWeatherVar.value = DEFAULT_WEATHER);
                    }

                    return (globalWeatherVar.value = parsedWeather);
                } catch (error) {
                    globalWeatherVar.value = DEFAULT_WEATHER;
                    console.warn(`Failed to parse weather data: ${error}`);
                }
            })
            .catch((err) => {
                console.error(`Failed to fetch weather: ${err}`);
                globalWeatherVar.value = DEFAULT_WEATHER;
            });
    });
};

Utils.merge([key.bind('value'), interval.bind('value'), location.bind('value')], (weatherKey, weatherInterval, loc) => {
    if (!weatherKey) {
        return (globalWeatherVar.value = DEFAULT_WEATHER);
    }
    weatherIntervalFn(weatherInterval, loc, weatherKey);
});

export const getTemperature = (wthr: Weather, unt: UnitType): string => {
    if (unt === 'imperial') {
        return `${Math.ceil(wthr.current.temp_f)}° F`;
    } else {
        return `${Math.ceil(wthr.current.temp_c)}° C`;
    }
};

export const getWeatherIcon = (fahren: number): Record<string, string> => {
    const icons = {
        100: '',
        75: '',
        50: '',
        25: '',
        0: '',
    } as const;
    const colors = {
        100: 'weather-color red',
        75: 'weather-color orange',
        50: 'weather-color lavender',
        25: 'weather-color blue',
        0: 'weather-color sky',
    } as const;

    type IconKeys = keyof typeof icons;

    const threshold: IconKeys =
        fahren < 0 ? 0 : ([100, 75, 50, 25, 0] as IconKeys[]).find((threshold) => threshold <= fahren) || 0;

    const icon = icons[threshold || 50];
    const color = colors[threshold || 50];

    return {
        icon,
        color,
    };
};

export const getWindConditions = (wthr: Weather, unt: UnitType): string => {
    if (unt === 'imperial') {
        return `${Math.floor(wthr.current.wind_mph)} mph`;
    }
    return `${Math.floor(wthr.current.wind_kph)} kph`;
};

export const getRainChance = (wthr: Weather): string => `${wthr.forecast.forecastday[0].day.daily_chance_of_rain}%`;

export const isValidWeatherIconTitle = (title: string): title is WeatherIconTitle => {
    return title in weatherIcons;
};

export const getWeatherStatusTextIcon = (wthr: Weather): WeatherIcon => {
    let iconQuery = wthr.current.condition.text.trim().toLowerCase().replaceAll(' ', '_');

    if (!wthr.current.is_day && iconQuery === 'partly_cloudy') {
        iconQuery = 'partly_cloudy_night';
    }

    if (isValidWeatherIconTitle(iconQuery)) {
        return weatherIcons[iconQuery];
    } else {
        console.warn(`Unknown weather icon title: ${iconQuery}`);
        return weatherIcons['warning'];
    }
};

globalThis['globalWeatherVar'] = globalWeatherVar;


================================================
FILE: .config/ags/globals/window.ts
================================================
export const WINDOW_LAYOUTS: string[] = [
    'center',
    'top',
    'top-right',
    'top-center',
    'top-left',
    'bottom-left',
    'bottom-center',
    'bottom-right',
];


================================================
FILE: .config/ags/globals.d.ts
================================================
// globals.d.ts
/* eslint-disable no-var */

import { Options, Variable as VariableType } from 'types/variable';

declare global {
    var useTheme: (filePath: string) => void;
    var isWindowVisible: (windowName: string) => boolean;
    var globalWeatherVar: VariableType<Weather>;
    var options: Options;
    var removingNotifications: VariableType<boolean>;
}

export {};


================================================
FILE: .config/ags/install_fonts.sh
================================================
#!/bin/bash

SOURCE_DIR="./assets/fonts"
DEST_DIR="$HOME/.local/share/fonts"
DEST_PATH="$DEST_DIR/NFP"

if [ ! -d "$SOURCE_DIR" ]; then
    echo "Source directory '$SOURCE_DIR' does not exist."
    exit 1
fi

if [ ! -d "$DEST_PATH" ]; then
    echo "Destination directory '$DEST_PATH' does not exist. Creating it..."
    mkdir -p "$DEST_PATH"
fi

if [ -z "$(ls -A "$SOURCE_DIR")" ]; then
    echo "Source directory '$SOURCE_DIR' is empty. No files to copy."
    exit 1
fi

echo "Copying fonts from '$SOURCE_DIR' to '$DEST_PATH'..."
cp -r "$SOURCE_DIR"/* "$DEST_PATH"

echo "Updating font cache..."
fc-cache -fv

echo "Fonts installed successfully."


================================================
FILE: .config/ags/lib/constants/colors.ts
================================================
export const namedColors = new Set([
    'alice blue',
    'antique white',
    'aqua',
    'aquamarine',
    'azure',
    'beige',
    'bisque',
    'black',
    'blanched almond',
    'blue',
    'blue violet',
    'brown',
    'burlywood',
    'cadet blue',
    'chartreuse',
    'chocolate',
    'coral',
    'cornflower blue',
    'cornsilk',
    'crimson',
    'cyan',
    'dark blue',
    'dark cyan',
    'dark goldenrod',
    'dark gray',
    'dark green',
    'dark khaki',
    'dark magenta',
    'dark olive green',
    'dark orange',
    'dark orchid',
    'dark red',
    'dark salmon',
    'dark sea green',
    'dark slate blue',
    'dark slate gray',
    'dark turquoise',
    'dark violet',
    'deep pink',
    'deep sky blue',
    'dim gray',
    'dodger blue',
    'firebrick',
    'floral white',
    'forest green',
    'fuchsia',
    'gainsboro',
    'ghost white',
    'gold',
    'goldenrod',
    'gray',
    'green',
    'green yellow',
    'honeydew',
    'hot pink',
    'indian red',
    'indigo',
    'ivory',
    'khaki',
    'lavender',
    'lavender blush',
    'lawn green',
    'lemon chiffon',
    'light blue',
    'light coral',
    'light cyan',
    'light goldenrod yellow',
    'light green',
    'light grey',
    'light pink',
    'light salmon',
    'light sea green',
    'light sky blue',
    'light slate gray',
    'light steel blue',
    'light yellow',
    'lime',
    'lime green',
    'linen',
    'magenta',
    'maroon',
    'medium aquamarine',
    'medium blue',
    'medium orchid',
    'medium purple',
    'medium sea green',
    'medium slate blue',
    'medium spring green',
    'medium turquoise',
    'medium violet red',
    'midnight blue',
    'mint cream',
    'misty rose',
    'moccasin',
    'navajo white',
    'navy',
    'old lace',
    'olive',
    'olive drab',
    'orange',
    'orange red',
    'orchid',
    'pale goldenrod',
    'pale green',
    'pale turquoise',
    'pale violet red',
    'papaya whip',
    'peach puff',
    'peru',
    'pink',
    'plum',
    'powder blue',
    'purple',
    'red',
    'rosy brown',
    'royal blue',
    'saddle brown',
    'salmon',
    'sandy brown',
    'sea green',
    'seashell',
    'sienna',
    'silver',
    'sky blue',
    'slate blue',
    'slate gray',
    'snow',
    'spring green',
    'steel blue',
    'tan',
    'teal',
    'thistle',
    'tomato',
    'turquoise',
    'violet',
    'wheat',
    'white',
    'white smoke',
    'yellow',
    'yellow green',
]);


================================================
FILE: .config/ags/lib/icons.ts
================================================
export const substitutes = {
    'transmission-gtk': 'transmission',
    'blueberry.py': 'blueberry',
    Caprine: 'facebook-messenger',
    'com.raggesilver.BlackBox-symbolic': 'terminal-symbolic',
    'org.wezfurlong.wezterm-symbolic': 'terminal-symbolic',
    'audio-headset-bluetooth': 'audio-headphones-symbolic',
    'audio-card-analog-usb': 'audio-speakers-symbolic',
    'audio-card-analog-pci': 'audio-card-symbolic',
    'preferences-system': 'emblem-system-symbolic',
    'com.github.Aylur.ags-symbolic': 'controls-symbolic',
    'com.github.Aylur.ags': 'controls-symbolic',
} as const;

export default {
    missing: 'image-missing-symbolic',
    nix: {
        nix: 'nix-snowflake-symbolic',
    },
    app: {
        terminal: 'terminal-symbolic',
    },
    fallback: {
        executable: 'application-x-executable',
        notification: 'dialog-information-symbolic',
        video: 'video-x-generic-symbolic',
        audio: 'audio-x-generic-symbolic',
    },
    ui: {
        close: 'window-close-symbolic',
        colorpicker: 'color-select-symbolic',
        info: 'info-symbolic',
        link: 'external-link-symbolic',
        lock: 'system-lock-screen-symbolic',
        menu: 'open-menu-symbolic',
        refresh: 'view-refresh-symbolic',
        search: 'system-search-symbolic',
        settings: 'emblem-system-symbolic',
        themes: 'preferences-desktop-theme-symbolic',
        tick: 'object-select-symbolic',
        time: 'hourglass-symbolic',
        toolbars: 'toolbars-symbolic',
        warning: 'dialog-warning-symbolic',
        arrow: {
            right: 'pan-end-symbolic',
            left: 'pan-start-symbolic',
            down: 'pan-down-symbolic',
            up: 'pan-up-symbolic',
        },
    },
    audio: {
        mic: {
            muted: 'microphone-disabled-symbolic',
            low: 'microphone-sensitivity-low-symbolic',
            medium: 'microphone-sensitivity-medium-symbolic',
            high: 'microphone-sensitivity-high-symbolic',
        },
        volume: {
            muted: 'audio-volume-muted-symbolic',
            low: 'audio-volume-low-symbolic',
            medium: 'audio-volume-medium-symbolic',
            high: 'audio-volume-high-symbolic',
            overamplified: 'audio-volume-overamplified-symbolic',
        },
        type: {
            headset: 'audio-headphones-symbolic',
            speaker: 'audio-speakers-symbolic',
            card: 'audio-card-symbolic',
        },
        mixer: 'mixer-symbolic',
    },
    powerprofile: {
        balanced: 'power-profile-balanced-symbolic',
        'power-saver': 'power-profile-power-saver-symbolic',
        performance: 'power-profile-performance-symbolic',
    },
    asusctl: {
        profile: {
            Balanced: 'power-profile-balanced-symbolic',
            Quiet: 'power-profile-power-saver-symbolic',
            Performance: 'power-profile-performance-symbolic',
        },
        mode: {
            Integrated: 'processor-symbolic',
            Hybrid: 'controller-symbolic',
        },
    },
    battery: {
        charging: 'battery-flash-symbolic',
        warning: 'battery-empty-symbolic',
    },
    bluetooth: {
        enabled: 'bluetooth-active-symbolic',
        disabled: 'bluetooth-disabled-symbolic',
    },
    brightness: {
        indicator: 'display-brightness-symbolic',
        keyboard: 'keyboard-brightness-symbolic',
        screen: 'display-brightness-symbolic',
    },
    powermenu: {
        sleep: 'weather-clear-night-symbolic',
        reboot: 'system-reboot-symbolic',
        logout: 'system-log-out-symbolic',
        shutdown: 'system-shutdown-symbolic',
    },
    recorder: {
        recording: 'media-record-symbolic',
    },
    notifications: {
        noisy: 'org.gnome.Settings-notifications-symbolic',
        silent: 'notifications-disabled-symbolic',
        message: 'chat-bubbles-symbolic',
    },
    trash: {
        full: 'user-trash-full-symbolic',
        empty: 'user-trash-symbolic',
    },
    mpris: {
        shuffle: {
            enabled: 'media-playlist-shuffle-symbolic',
            disabled: 'media-playlist-consecutive-symbolic',
        },
        loop: {
            none: 'media-playlist-repeat-symbolic',
            track: 'media-playlist-repeat-song-symbolic',
            playlist: 'media-playlist-repeat-symbolic',
        },
        playing: 'media-playback-pause-symbolic',
        paused: 'media-playback-start-symbolic',
        stopped: 'media-playback-start-symbolic',
        prev: 'media-skip-backward-symbolic',
        next: 'media-skip-forward-symbolic',
    },
    system: {
        cpu: 'org.gnome.SystemMonitor-symbolic',
        ram: 'drive-harddisk-solidstate-symbolic',
        temp: 'temperature-symbolic',
    },
    color: {
        dark: 'dark-mode-symbolic',
        light: 'light-mode-symbolic',
    },
};


================================================
FILE: .config/ags/lib/option.ts
================================================
import { isHexColor } from 'globals/variables';
import { Variable } from 'resource:///com/github/Aylur/ags/variable.js';
import { MkOptionsResult } from './types/options';

type OptProps = {
    persistent?: boolean;
};

export class Opt<T = unknown> extends Variable<T> {
    static {
        Service.register(this);
    }

    constructor(initial: T, { persistent = false }: OptProps = {}) {
        super(initial);
        this.initial = initial;
        this.persistent = persistent;
    }

    initial: T;
    id = '';
    persistent: boolean;
    toString(): string {
        return `${this.value}`;
    }
    toJSON(): string {
        return `opt:${this.value}`;
    }

    getValue = (): T => {
        return super.getValue();
    };
    init(cacheFile: string): void {
        const cacheV = JSON.parse(Utils.readFile(cacheFile) || '{}')[this.id];
        if (cacheV !== undefined) this.value = cacheV;

        this.connect('changed', () => {
            const cache = JSON.parse(Utils.readFile(cacheFile) || '{}');
            cache[this.id] = this.value;
            Utils.writeFileSync(JSON.stringify(cache, null, 2), cacheFile);
        });
    }

    reset(): string | undefined {
        if (this.persistent) return;

        if (JSON.stringify(this.value) !== JSON.stringify(this.initial)) {
            this.value = this.initial;
            return this.id;
        }
    }

    doResetColor(): string | undefined {
        if (this.persistent) return;

        const isColor = isHexColor(this.value as string);
        if (JSON.stringify(this.value) !== JSON.stringify(this.initial) && isColor) {
            this.value = this.initial;
            return this.id;
        }
        return;
    }
}

export const opt = <T>(initial: T, opts?: OptProps): Opt<T> => new Opt(initial, opts);

const getOptions = (object: Record<string, unknown>, path = ''): Opt[] => {
    return Object.keys(object).flatMap((key) => {
        const obj = object[key];
        const id = path ? path + '.' + key : key;

        if (obj instanceof Variable) {
            const optValue = obj as Opt;
            optValue.id = id;
            return optValue;
        }

        if (typeof obj === 'object' && obj !== null) {
            return getOptions(obj as Record<string, unknown>, id); // Recursively process nested objects
        }

        return [];
    });
};

export function mkOptions<T extends object>(
    cacheFile: string,
    object: T,
    confFile: string = 'config.json',
): T & MkOptionsResult {
    for (const opt of getOptions(object as Record<string, unknown>)) opt.init(cacheFile);

    Utils.ensureDirectory(cacheFile.split('/').slice(0, -1).join('/'));

    const configFile = `${TMP}/${confFile}`;
    const values = getOptions(object as Record<string, unknown>).reduce(
        (obj, { id, value }) => ({ [id]: value, ...obj }),
        {},
    );
    Utils.writeFileSync(JSON.stringify(values, null, 2), configFile);
    Utils.monitorFile(configFile, () => {
        const cache = JSON.parse(Utils.readFile(configFile) || '{}');
        for (const opt of getOptions(object as Record<string, unknown>)) {
            if (JSON.stringify(cache[opt.id]) !== JSON.stringify(opt.value)) opt.value = cache[opt.id];
        }
    });

    function sleep(ms = 0): Promise<T> {
        return new Promise((r) => setTimeout(r, ms));
    }

    const reset = async (
        [opt, ...list] = getOptions(object as Record<string, unknown>),
        id = opt?.reset(),
    ): Promise<Array<string>> => {
        if (!opt) return sleep().then(() => []);

        return id ? [id, ...(await sleep(50).then(() => reset(list)))] : await sleep().then(() => reset(list));
    };

    const resetTheme = async (
        [opt, ...list] = getOptions(object as Record<string, unknown>),
        id = opt?.doResetColor(),
    ): Promise<Array<string>> => {
        if (!opt) return sleep().then(() => []);

        return id
            ? [id, ...(await sleep(50).then(() => resetTheme(list)))]
            : await sleep().then(() => resetTheme(list));
    };

    return Object.assign(object, {
        configFile,
        array: () => getOptions(object as Record<string, unknown>),
        async reset() {
            return (await reset()).join('\n');
        },
        async resetTheme() {
            return (await resetTheme()).join('\n');
        },
        handler(deps: string[], callback: () => void) {
            for (const opt of getOptions(object as Record<string, unknown>)) {
                if (deps.some((i) => opt.id.startsWith(i))) opt.connect('changed', callback);
            }
        },
    });
}


================================================
FILE: .config/ags/lib/session.ts
================================================
import GLib from 'gi://GLib?version=2.0';

declare global {
    const OPTIONS: string;
    const TMP: string;
    const USER: string;
}

Object.assign(globalThis, {
    OPTIONS: `${GLib.get_user_cache_dir()}/ags/hyprpanel/options.json`,
    TMP: `${GLib.get_tmp_dir()}/ags/hyprpanel`,
    USER: GLib.get_user_name(),
});

Utils.ensureDirectory(TMP);
App.addIcons(`${App.configDir}/assets`);


================================================
FILE: .config/ags/lib/shared/media.ts
================================================
import { MprisPlayer } from 'types/service/mpris';
const mpris = await Service.import('mpris');

export const getCurrentPlayer = (activePlayer: MprisPlayer = mpris.players[0]): MprisPlayer => {
    const statusOrder = {
        Playing: 1,
        Paused: 2,
        Stopped: 3,
    };

    if (mpris.players.length === 0) {
        return mpris.players[0];
    }

    const isPlaying = mpris.players.some((p: MprisPlayer) => p.play_back_status === 'Playing');

    const playerStillExists = mpris.players.some((p) => activePlayer.bus_name === p.bus_name);

    const nextPlayerUp = mpris.players.sort(
        (a: MprisPlayer, b: MprisPlayer) => statusOrder[a.play_back_status] - statusOrder[b.play_back_status],
    )[0];

    if (isPlaying || !playerStillExists) {
        return nextPlayerUp;
    }

    return activePlayer;
};


================================================
FILE: .config/ags/lib/shared/notifications.ts
================================================
import { Notification } from 'types/service/notifications';

export const filterNotifications = (notifications: Notification[], filter: string[]): Notification[] => {
    const notifFilter = new Set(filter.map((name: string) => name.toLowerCase().replace(/\s+/g, '_')));

    const filteredNotifications = notifications.filter((notif: Notification) => {
        const normalizedAppName = notif.app_name.toLowerCase().replace(/\s+/g, '_');
        return !notifFilter.has(normalizedAppName);
    });

    return filteredNotifications;
};


================================================
FILE: .config/ags/lib/types/audio.d.ts
================================================
export type InputDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribute>, Attribute>[];

type DummyDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribute>, Attribute>[];
type RealPlaybackDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribute>, Attribute>[];
export type PlaybackDevices = DummyDevices | RealPlaybackDevices;


================================================
FILE: .config/ags/lib/types/bar.d.ts
================================================
import { Binding, Connectable } from 'types/service';
import { Variable } from 'types/variable';
import Box from 'types/widgets/box';
import Button, { ButtonProps } from 'types/widgets/button';
import Label from 'types/widgets/label';
import { Attribute, Child } from './widget';

export type BarBoxChild = {
    component: Box<Gtk.Widget, unknown>;
    isVisible?: boolean;
    isVis?: Variable<boolean>;
    boxClass: string;
    tooltip_text?: string | Binding<string>;
    props: ButtonProps;
};

export type SelfButton = Button<Child, Attribute>;

export type BoxHook = (self: Box<Gtk.Widget, Gtk.Widget>) => void;
export type LabelHook = (self: Label<Gtk.Widget>) => void;

export type Module = {
    icon?: string | Binding<string>;
    textIcon?: string | Binding<string>;
    label?: string | Binding<string>;
    labelHook?: LabelHook;
    boundLabel?: string;
    tooltipText?: string | Binding<string>;
    boxClass: string;
    props?: ButtonProps;
    showLabel?: boolean;
    showLabelBinding?: Binding;
    hook?: BoxHook;
    connection?: Binding<Connectable>;
};

export type ResourceLabelType = 'used/total' | 'used' | 'percentage' | 'free';

export type NetstatLabelType = 'full' | 'in' | 'out';
export type RateUnit = 'GiB' | 'MiB' | 'KiB' | 'auto';




================================================
FILE: .config/ags/lib/types/customModules/generic.d.ts
================================================
export type GenericFunction<T, P extends unknown[] = unknown[]> = (...args: P) => T;

export type GenericResourceMetrics = {
    total: number;
    used: number;
    percentage: number;
};

export type GenericResourceData = GenericResourceMetrics & {
    free: number;
};

export type Postfix = 'TiB' | 'GiB' | 'MiB' | 'KiB' | 'B';


================================================
FILE: .config/ags/lib/types/customModules/kbLayout.d.ts
================================================
import { layoutMap } from 'customModules/kblayout/layouts';

export type KbLabelType = 'layout' | 'code';

export type HyprctlKeyboard = {
    address: string;
    name: string;
    rules: string;
    model: string;
    layout: string;
    variant: string;
    options: string;
    active_keymap: string;
    main: boolean;
};

export type HyprctlMouse = {
    address: string;
    name: string;
    defaultSpeed: number;
};

export type HyprctlDeviceLayout = {
    mice: HyprctlMouse[];
    keyboards: HyprctlKeyboard[];
    tablets: unknown[];
    touch: unknown[];
    switches: unknown[];
};

export type LayoutKeys = keyof typeof layoutMap;
export type LayoutValues = (typeof layoutMap)[LayoutKeys];


================================================
FILE: .config/ags/lib/types/customModules/network.d.ts
================================================
export type NetworkResourceData = {
    in: string;
    out: string;
};


================================================
FILE: .config/ags/lib/types/customModules/utils.d.ts
================================================
import { Binding } from 'lib/utils';

export type InputHandlerEvents = {
    onPrimaryClick?: Binding;
    onSecondaryClick?: Binding;
    onMiddleClick?: Binding;
    onScrollUp?: Binding;
    onScrollDown?: Binding;
};

export type RunAsyncCommand = (cmd: string, args: EventArgs, fn?: (output: string) => void) => void;


================================================
FILE: .config/ags/lib/types/defaults/bar.ts
================================================
import { NetstatLabelType, ResourceLabelType } from '../bar';

export const LABEL_TYPES: ResourceLabelType[] = ['used/total', 'used', 'free', 'percentage'];

export const NETWORK_LABEL_TYPES: NetstatLabelType[] = ['full', 'in', 'out'];


================================================
FILE: .config/ags/lib/types/defaults/netstat.ts
================================================
import { RateUnit } from '../bar';
import { NetworkResourceData } from '../customModules/network';

export const GET_DEFAULT_NETSTAT_DATA = (dataType: RateUnit): NetworkResourceData => {
    if (dataType === 'auto') {
        return { in: `0 Kib/s`, out: `0 Kib/s` };
    }

    return { in: `0 ${dataType}/s`, out: `0 ${dataType}/s` };
};


================================================
FILE: .config/ags/lib/types/defaults/options.ts
================================================
export const defaultColorMap = {
    rosewater: '#f5e0dc',
    flamingo: '#f2cdcd',
    pink: '#f5c2e7',
    mauve: '#cba6f7',
    red: '#f38ba8',
    maroon: '#eba0ac',
    peach: '#fab387',
    yellow: '#f9e2af',
    green: '#a6e3a1',
    teal: '#94e2d5',
    sky: '#89dceb',
    sapphire: '#74c7ec',
    blue: '#89b4fa',
    lavender: '#b4befe',
    text: '#cdd6f4',
    subtext1: '#bac2de',
    subtext2: '#a6adc8',
    overlay2: '#9399b2',
    overlay1: '#7f849c',
    overlay0: '#6c7086',
    surface2: '#585b70',
    surface1: '#45475a',
    surface0: '#313244',
    base2: '#242438',
    base: '#1e1e2e',
    mantle: '#181825',
    crust: '#11111b',
    surface1_2: '#454759',
    text2: '#cdd6f3',
    pink2: '#f5c2e6',
    red2: '#f38ba7',
    peach2: '#fab386',
    mantle2: '#181824',
    surface0_2: '#313243',
    surface2_2: '#585b69',
    overlay1_2: '#7f849b',
    lavender2: '#b4befd',
    mauve2: '#cba6f6',
    green2: '#a6e3a0',
    sky2: '#89dcea',
    teal2: '#94e2d4',
    yellow2: '#f9e2ad',
    maroon2: '#eba0ab',
    crust2: '#11111a',
    pink3: '#f5c2e8',
    red3: '#f38ba9',
    mantle3: '#181826',
    surface0_3: '#313245',
    surface2_3: '#585b71',
    overlay1_3: '#7f849d',
    lavender3: '#b4beff',
    mauve3: '#cba6f8',
    green3: '#a6e3a2',
    sky3: '#89dcec',
    teal3: '#94e2d6',
    yellow3: '#f9e2ae',
    maroon3: '#eba0ad',
    crust3: '#11111c',
} as const;


================================================
FILE: .config/ags/lib/types/defaults/weather.ts
================================================
export const DEFAULT_WEATHER = {
    location: {
        name: 'Tahiti',
        region: 'Somewhere',
        country: 'United States of America',
        lat: 0,
        lon: 0,
        tz_id: 'Tahiti',
        localtime_epoch: 1721981457,
        localtime: '2024-07-26 1:10',
    },
    current: {
        last_updated_epoch: 1721980800,
        last_updated: '2024-07-26 01:00',
        temp_c: 0,
        temp_f: 0,
        is_day: 0,
        condition: {
            text: 'Clear',
            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
            code: 1000,
        },
        wind_mph: 0,
        wind_kph: 0,
        wind_degree: 0,
        wind_dir: 'NW',
        pressure_mb: 0,
        pressure_in: 0,
        precip_mm: 0.0,
        precip_in: 0.0,
        humidity: 0,
        cloud: 0,
        feelslike_c: 0,
        feelslike_f: 0,
        windchill_c: 0,
        windchill_f: 0,
        heatindex_c: 0,
        heatindex_f: 0,
        dewpoint_c: 0,
        dewpoint_f: 0,
        vis_km: 0,
        vis_miles: 0,
        uv: 0,
        gust_mph: 0,
        gust_kph: 0,
    },
    forecast: {
        forecastday: [
            {
                date: '2024-07-26',
                date_epoch: 1721952000,
                day: {
                    maxtemp_c: 0,
                    maxtemp_f: 0,
                    mintemp_c: 0,
                    mintemp_f: 0,
                    avgtemp_c: 0,
                    avgtemp_f: 0,
                    maxwind_mph: 0,
                    maxwind_kph: 0,
                    totalprecip_mm: 0,
                    totalprecip_in: 0,
                    totalsnow_cm: 0,
                    avgvis_km: 0,
                    avgvis_miles: 0,
                    avghumidity: 0,
                    daily_will_it_rain: 0,
                    daily_chance_of_rain: 0,
                    daily_will_it_snow: 0,
                    daily_chance_of_snow: 0,
                    condition: {
                        text: 'Sunny',
                        icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                        code: 1000,
                    },
                    uv: 0,
                },
                astro: {
                    sunrise: '06:01 AM',
                    sunset: '08:10 PM',
                    moonrise: '11:32 PM',
                    moonset: '12:01 PM',
                    moon_phase: 'Waning Gibbous',
                    moon_illumination: 0,
                    is_moon_up: 0,
                    is_sun_up: 0,
                },
                hour: [
                    {
                        time_epoch: 1721977200,
                        time: '2024-07-26 00:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721980800,
                        time: '2024-07-26 01:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721984400,
                        time: '2024-07-26 02:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721988000,
                        time: '2024-07-26 03:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721991600,
                        time: '2024-07-26 04:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721995200,
                        time: '2024-07-26 05:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1721998800,
                        time: '2024-07-26 06:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1722002400,
                        time: '2024-07-26 07:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 7.0,
                    },
                    {
                        time_epoch: 1722006000,
                        time: '2024-07-26 08:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 7.0,
                    },
                    {
                        time_epoch: 1722009600,
                        time: '2024-07-26 09:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 8.0,
                    },
                    {
                        time_epoch: 1722013200,
                        time: '2024-07-26 10:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 8.0,
                    },
                    {
                        time_epoch: 1722016800,
                        time: '2024-07-26 11:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 9.0,
                    },
                    {
                        time_epoch: 1722020400,
                        time: '2024-07-26 12:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 9.0,
                    },
                    {
                        time_epoch: 1722024000,
                        time: '2024-07-26 13:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 9.0,
                    },
                    {
                        time_epoch: 1722027600,
                        time: '2024-07-26 14:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 10.0,
                    },
                    {
                        time_epoch: 1722031200,
                        time: '2024-07-26 15:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 10.0,
                    },
                    {
                        time_epoch: 1722034800,
                        time: '2024-07-26 16:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 10.0,
                    },
                    {
                        time_epoch: 1722038400,
                        time: '2024-07-26 17:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 10.0,
                    },
                    {
                        time_epoch: 1722042000,
                        time: '2024-07-26 18:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 9.0,
                    },
                    {
                        time_epoch: 1722045600,
                        time: '2024-07-26 19:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 9.0,
                    },
                    {
                        time_epoch: 1722049200,
                        time: '2024-07-26 20:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 1,
                        condition: {
                            text: 'Sunny',
                            icon: '//cdn.weatherapi.com/weather/64x64/day/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 8.0,
                    },
                    {
                        time_epoch: 1722052800,
                        time: '2024-07-26 21:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1722056400,
                        time: '2024-07-26 22:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                    {
                        time_epoch: 1722060000,
                        time: '2024-07-26 23:00',
                        temp_c: 0,
                        temp_f: 0,
                        is_day: 0,
                        condition: {
                            text: 'Clear ',
                            icon: '//cdn.weatherapi.com/weather/64x64/night/113.png',
                            code: 1000,
                        },
                        wind_mph: 0,
                        wind_kph: 0,
                        wind_degree: 0,
                        wind_dir: 'N',
                        pressure_mb: 0,
                        pressure_in: 0,
                        precip_mm: 0,
                        precip_in: 0,
                        snow_cm: 0,
                        humidity: 0,
                        cloud: 0,
                        feelslike_c: 0,
                        feelslike_f: 0,
                        windchill_c: 0,
                        windchill_f: 0,
                        heatindex_c: 0,
                        heatindex_f: 0,
                        dewpoint_c: 0,
                        dewpoint_f: 0,
                        will_it_rain: 0,
                        chance_of_rain: 0,
                        will_it_snow: 0,
                        chance_of_snow: 0,
                        vis_km: 0,
                        vis_miles: 0,
                        gust_mph: 0,
                        gust_kph: 0,
                        uv: 0,
                    },
                ],
            },
        ],
    },
};


================================================
FILE: .config/ags/lib/types/dropdownmenu.d.ts
================================================
import { WindowProps } from 'types/widgets/window';
import { GtkWidget, Transition } from './widget';
import { Binding } from 'types/service';

export type DropdownMenuProps = {
    name: string;
    child: GtkWidget;
    layout?: string;
    transition?: Transition | Binding<Transition>;
    exclusivity?: Exclusivity;
    fixed?: boolean;
} & WindowProps;


================================================
FILE: .config/ags/lib/types/filechooser.d.ts
================================================
export type Config = {
    [key: string]: string | number | boolean | object;
};


================================================
FILE: .config/ags/lib/types/globals.d.ts
================================================
export type MousePos = {
    source: string;
    pos: number[];
};


================================================
FILE: .config/ags/lib/types/gpustat.d.ts
================================================
export type GPU_Stat_Process = {
    username: string;
    command: string;
    full_command: string[];
    gpu_memory_usage: number;
    cpu_percent: number;
    cpu_memory_usage: number;
    pid: number;
};

export type GPU_Stat = {
    index: number;
    uuid: string;
    name: string;
    'temperature.gpu': number;
    'fan.speed': number;
    'utilization.gpu': number;
    'utilization.enc': number;
    'utilization.dec': number;
    'power.draw': number;
    'enforced.power.limit': number;
    'memory.used': number;
    'memory.total': number;
    processes: Process[];
};


================================================
FILE: .config/ags/lib/types/mpris.d.ts
================================================
export type LoopStatus = 'none' | 'track' | 'playlist';
export type PlaybackStatus = 'playing' | 'paused' | 'stopped';


================================================
FILE: .config/ags/lib/types/network.d.ts
================================================
import { WIFI_STATUS_MAP } from 'globals/network';

export type AccessPoint = {
    bssid: string | null;
    address: string | null;
    lastSeen: number;
    ssid: string | null;
    active: boolean;
    strength: number;
    frequency: number;
    iconName: string | undefined;
};

export type WifiStatus = keyof typeof WIFI_STATUS_MAP;

export type WifiIcon = '󰤩' | '󰤨' | '󰤪' | '󰤨' | '󰤩' | '󰤮' | '󰤨' | '󰤥' | '󰤢' | '󰤟' | '󰤯';


================================================
FILE: .config/ags/lib/types/notification.d.ts
================================================
import icons from 'modules/icons/index';

export interface NotificationArgs {
    appName?: string;
    body?: string;
    iconName?: string;
    id?: number;
    summary?: string;
    urgency?: Urgency;
    category?: string;
    timeout?: number;
    transient?: boolean;
}

export type NotificationIcon = keyof typeof icons.notifications;


===============================================
Download .txt
gitextract_9l3ptfwt/

├── .config/
│   ├── ags/
│   │   ├── .eslintignore
│   │   ├── .eslintrc.js
│   │   ├── .github/
│   │   │   ├── ISSUE_TEMPLATE/
│   │   │   │   ├── bug_report.md
│   │   │   │   └── feature_request.md
│   │   │   └── workflows/
│   │   │       └── ci.yml
│   │   ├── .gitignore
│   │   ├── .gitmodules
│   │   ├── .prettierignore
│   │   ├── .prettierrc
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── config.js
│   │   ├── customModules/
│   │   │   ├── PollVar.ts
│   │   │   ├── config.ts
│   │   │   ├── cpu/
│   │   │   │   ├── computeCPU.ts
│   │   │   │   └── index.ts
│   │   │   ├── kblayout/
│   │   │   │   ├── getLayout.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── layouts.ts
│   │   │   ├── module.ts
│   │   │   ├── netstat/
│   │   │   │   ├── computeNetwork.ts
│   │   │   │   └── index.ts
│   │   │   ├── power/
│   │   │   │   └── index.ts
│   │   │   ├── ram/
│   │   │   │   ├── computeRam.ts
│   │   │   │   └── index.ts
│   │   │   ├── storage/
│   │   │   │   ├── computeStorage.ts
│   │   │   │   └── index.ts
│   │   │   ├── submap/
│   │   │   │   ├── helpers.ts
│   │   │   │   └── index.ts
│   │   │   ├── theme.ts
│   │   │   ├── updates/
│   │   │   │   └── index.ts
│   │   │   ├── utils.ts
│   │   │   └── weather/
│   │   │       └── index.ts
│   │   ├── directoryMonitorService.ts
│   │   ├── flake.nix
│   │   ├── globals/
│   │   │   ├── dropdown.ts
│   │   │   ├── mousePos.ts
│   │   │   ├── network.ts
│   │   │   ├── notification.ts
│   │   │   ├── useTheme.ts
│   │   │   ├── utilities.ts
│   │   │   ├── variables.ts
│   │   │   ├── weather.ts
│   │   │   └── window.ts
│   │   ├── globals.d.ts
│   │   ├── install_fonts.sh
│   │   ├── lib/
│   │   │   ├── constants/
│   │   │   │   └── colors.ts
│   │   │   ├── icons.ts
│   │   │   ├── option.ts
│   │   │   ├── session.ts
│   │   │   ├── shared/
│   │   │   │   ├── media.ts
│   │   │   │   └── notifications.ts
│   │   │   ├── types/
│   │   │   │   ├── audio.d.ts
│   │   │   │   ├── bar.d.ts
│   │   │   │   ├── customModules/
│   │   │   │   │   ├── generic.d.ts
│   │   │   │   │   ├── kbLayout.d.ts
│   │   │   │   │   ├── network.d.ts
│   │   │   │   │   └── utils.d.ts
│   │   │   │   ├── defaults/
│   │   │   │   │   ├── bar.ts
│   │   │   │   │   ├── netstat.ts
│   │   │   │   │   ├── options.ts
│   │   │   │   │   └── weather.ts
│   │   │   │   ├── dropdownmenu.d.ts
│   │   │   │   ├── filechooser.d.ts
│   │   │   │   ├── globals.d.ts
│   │   │   │   ├── gpustat.d.ts
│   │   │   │   ├── mpris.d.ts
│   │   │   │   ├── network.d.ts
│   │   │   │   ├── notification.d.ts
│   │   │   │   ├── options.d.ts
│   │   │   │   ├── popupwindow.d.ts
│   │   │   │   ├── power.d.ts
│   │   │   │   ├── powerprofiles.d.ts
│   │   │   │   ├── systray.d.ts
│   │   │   │   ├── utils.d.ts
│   │   │   │   ├── variable.d.ts
│   │   │   │   ├── volume.d.ts
│   │   │   │   ├── weather.d.ts
│   │   │   │   ├── widget.d.ts
│   │   │   │   └── workspace.d.ts
│   │   │   ├── utils.ts
│   │   │   └── variables.ts
│   │   ├── main.ts
│   │   ├── modules/
│   │   │   ├── bar/
│   │   │   │   ├── Bar.ts
│   │   │   │   ├── Exports.ts
│   │   │   │   ├── SideEffects.ts
│   │   │   │   ├── battery/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── bluetooth/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── clock/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── media/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── menu/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── network/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── notifications/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── systray/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── utils.ts
│   │   │   │   ├── volume/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── window_title/
│   │   │   │   │   └── index.ts
│   │   │   │   └── workspaces/
│   │   │   │       ├── helpers.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── utils.ts
│   │   │   │       └── variants/
│   │   │   │           ├── default.ts
│   │   │   │           └── occupied.ts
│   │   │   ├── icons/
│   │   │   │   ├── index.ts
│   │   │   │   └── weather.ts
│   │   │   ├── menus/
│   │   │   │   ├── audio/
│   │   │   │   │   ├── active/
│   │   │   │   │   │   ├── SelectedInput.ts
│   │   │   │   │   │   ├── SelectedPlayback.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── available/
│   │   │   │   │   │   ├── InputDevices.ts
│   │   │   │   │   │   ├── PlaybackDevices.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── bluetooth/
│   │   │   │   │   ├── devices/
│   │   │   │   │   │   ├── connectedControls.ts
│   │   │   │   │   │   ├── devicelist.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── label.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── calendar/
│   │   │   │   │   ├── calendar.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── time/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── weather/
│   │   │   │   │       ├── hourly/
│   │   │   │   │       │   ├── icon/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── temperature/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   ├── time/
│   │   │   │   │       │   │   └── index.ts
│   │   │   │   │       │   └── utils.ts
│   │   │   │   │       ├── icon/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── stats/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       └── temperature/
│   │   │   │   │           └── index.ts
│   │   │   │   ├── dashboard/
│   │   │   │   │   ├── controls/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── directories/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── profile/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── shortcuts/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── stats/
│   │   │   │   │       └── index.ts
│   │   │   │   ├── energy/
│   │   │   │   │   ├── brightness/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── profiles/
│   │   │   │   │       └── index.ts
│   │   │   │   ├── main.ts
│   │   │   │   ├── media/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── bar.ts
│   │   │   │   │   │   ├── controls.ts
│   │   │   │   │   │   └── mediainfo.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── media.ts
│   │   │   │   ├── network/
│   │   │   │   │   ├── ethernet/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── wifi/
│   │   │   │   │       ├── APStaging.ts
│   │   │   │   │       ├── WirelessAPs.ts
│   │   │   │   │       └── index.ts
│   │   │   │   ├── notifications/
│   │   │   │   │   ├── controls/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── notification/
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── body/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── close/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── header/
│   │   │   │   │   │   │   ├── icon.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── image/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── placeholder/
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── pager/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── power/
│   │   │   │   │   ├── helpers/
│   │   │   │   │   │   └── actions.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── verification.ts
│   │   │   │   ├── powerDropdown/
│   │   │   │   │   ├── button.ts
│   │   │   │   │   └── index.ts
│   │   │   │   └── shared/
│   │   │   │       ├── dropdown/
│   │   │   │       │   ├── eventBoxes/
│   │   │   │       │   │   └── index.ts
│   │   │   │       │   ├── index.ts
│   │   │   │       │   └── locationHandler/
│   │   │   │       │       └── index.ts
│   │   │   │       └── popup/
│   │   │   │           └── index.ts
│   │   │   ├── notifications/
│   │   │   │   ├── actions/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── body/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── close/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── header/
│   │   │   │   │   ├── icon.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── image/
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   ├── osd/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── icon/
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── label/
│   │   │   │       └── index.ts
│   │   │   └── shared/
│   │   │       └── barItemBox.ts
│   │   ├── nix/
│   │   │   └── default.nix
│   │   ├── options.ts
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   ├── README.md
│   │   │   ├── checkUpdates.sh
│   │   │   ├── color_generation/
│   │   │   │   ├── applycolor.sh
│   │   │   │   ├── colorgen.sh
│   │   │   │   ├── generate_colors_material.py
│   │   │   │   ├── pywal_to_material.scss
│   │   │   │   ├── randomwall.sh
│   │   │   │   ├── schemes/
│   │   │   │   │   └── scheme_morevibrant.py
│   │   │   │   ├── specials/
│   │   │   │   │   ├── _material_badapple-l.scss
│   │   │   │   │   └── _material_badapple.scss
│   │   │   │   ├── switchcolor.sh
│   │   │   │   └── switchwall.sh
│   │   │   ├── fillThemes.js
│   │   │   ├── fillThemes.sh
│   │   │   ├── grimblast.sh
│   │   │   ├── hyprland/
│   │   │   │   ├── get_keybinds.py
│   │   │   │   └── workspace_action.sh
│   │   │   ├── quickscripts/
│   │   │   │   └── nixos-trim-generations.sh
│   │   │   ├── record-script.sh
│   │   │   ├── sway/
│   │   │   │   └── swayToRelativeWs.sh
│   │   │   ├── templates/
│   │   │   │   ├── fuzzel/
│   │   │   │   │   └── fuzzel.ini
│   │   │   │   ├── gradience/
│   │   │   │   │   └── preset.json
│   │   │   │   ├── hypr/
│   │   │   │   │   ├── hyprland/
│   │   │   │   │   │   └── colors.conf
│   │   │   │   │   └── hyprlock.conf
│   │   │   │   └── terminal/
│   │   │   │       ├── scheme-base.json
│   │   │   │       ├── scheme-monochrome.json
│   │   │   │       └── sequences.txt
│   │   │   └── wayland-idle-inhibitor.py
│   │   ├── scss/
│   │   │   ├── main.scss
│   │   │   ├── optionsTrackers.ts
│   │   │   ├── style/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── audio.scss
│   │   │   │   │   ├── bar.scss
│   │   │   │   │   ├── battery.scss
│   │   │   │   │   ├── bluetooth.scss
│   │   │   │   │   ├── clock.scss
│   │   │   │   │   ├── media.scss
│   │   │   │   │   ├── menu.scss
│   │   │   │   │   ├── network.scss
│   │   │   │   │   ├── notifications.scss
│   │   │   │   │   ├── power.scss
│   │   │   │   │   ├── systray.scss
│   │   │   │   │   ├── window_title.scss
│   │   │   │   │   └── workspace.scss
│   │   │   │   ├── colors.scss
│   │   │   │   ├── common/
│   │   │   │   │   ├── common.scss
│   │   │   │   │   ├── floating-widget.scss
│   │   │   │   │   ├── general.scss
│   │   │   │   │   └── widget-button.scss
│   │   │   │   ├── customModules/
│   │   │   │   │   └── style.scss
│   │   │   │   ├── highlights.scss
│   │   │   │   ├── menus/
│   │   │   │   │   ├── audiomenu.scss
│   │   │   │   │   ├── bluetooth.scss
│   │   │   │   │   ├── calendar.scss
│   │   │   │   │   ├── dashboard.scss
│   │   │   │   │   ├── energy.scss
│   │   │   │   │   ├── media.scss
│   │   │   │   │   ├── menu.scss
│   │   │   │   │   ├── network.scss
│   │   │   │   │   ├── notifications.scss
│   │   │   │   │   ├── power.scss
│   │   │   │   │   └── powerdropdown.scss
│   │   │   │   ├── notifications/
│   │   │   │   │   └── popups.scss
│   │   │   │   ├── osd/
│   │   │   │   │   └── index.scss
│   │   │   │   └── settings/
│   │   │   │       └── dialog.scss
│   │   │   └── style.ts
│   │   ├── services/
│   │   │   ├── Brightness.ts
│   │   │   ├── Cpu.ts
│   │   │   ├── Ram.ts
│   │   │   ├── Storage.ts
│   │   │   ├── Wallpaper.ts
│   │   │   ├── bluetooth.py
│   │   │   ├── matugen/
│   │   │   │   ├── index.ts
│   │   │   │   └── variations.ts
│   │   │   ├── screen_record.sh
│   │   │   └── snapshot.sh
│   │   ├── themes/
│   │   │   ├── catppuccin_frappe.json
│   │   │   ├── catppuccin_frappe_split.json
│   │   │   ├── catppuccin_latte.json
│   │   │   ├── catppuccin_latte_split.json
│   │   │   ├── catppuccin_macchiato.json
│   │   │   ├── catppuccin_macchiato_split.json
│   │   │   ├── catppuccin_mocha.json
│   │   │   ├── catppuccin_mocha_split.json
│   │   │   ├── cyberpunk.json
│   │   │   ├── cyberpunk_split.json
│   │   │   ├── dracula.json
│   │   │   ├── dracula_split.json
│   │   │   ├── everforest.json
│   │   │   ├── everforest_split.json
│   │   │   ├── gruvbox.json
│   │   │   ├── gruvbox_split.json
│   │   │   ├── monochrome.json
│   │   │   ├── monochrome_split.json
│   │   │   ├── nord.json
│   │   │   ├── nord_split.json
│   │   │   ├── one_dark.json
│   │   │   ├── one_dark_split.json
│   │   │   ├── rose_pine.json
│   │   │   ├── rose_pine_moon.json
│   │   │   ├── rose_pine_moon_split.json
│   │   │   ├── rose_pine_split.json
│   │   │   ├── tokyo_night.json
│   │   │   └── tokyo_night_split.json
│   │   ├── tsconfig.json
│   │   └── widget/
│   │       ├── RegularWindow.ts
│   │       └── settings/
│   │           ├── SettingsDialog.ts
│   │           ├── pages/
│   │           │   ├── config/
│   │           │   │   ├── bar/
│   │           │   │   │   └── index.ts
│   │           │   │   ├── general/
│   │           │   │   │   └── index.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── menus/
│   │           │   │   │   ├── clock.ts
│   │           │   │   │   ├── dashboard.ts
│   │           │   │   │   └── power.ts
│   │           │   │   ├── notifications/
│   │           │   │   │   └── index.ts
│   │           │   │   └── osd/
│   │           │   │       └── index.ts
│   │           │   └── theme/
│   │           │       ├── bar/
│   │           │       │   └── index.ts
│   │           │       ├── index.ts
│   │           │       ├── menus/
│   │           │       │   ├── battery.ts
│   │           │       │   ├── bluetooth.ts
│   │           │       │   ├── clock.ts
│   │           │       │   ├── dashboard.ts
│   │           │       │   ├── index.ts
│   │           │       │   ├── matugen.ts
│   │           │       │   ├── media.ts
│   │           │       │   ├── network.ts
│   │           │       │   ├── notifications.ts
│   │           │       │   ├── power.ts
│   │           │       │   ├── systray.ts
│   │           │       │   └── volume.ts
│   │           │       ├── notifications/
│   │           │       │   └── index.ts
│   │           │       └── osd/
│   │           │           └── index.ts
│   │           ├── shared/
│   │           │   ├── FileChooser.ts
│   │           │   ├── Header.ts
│   │           │   ├── Inputter.ts
│   │           │   ├── Label.ts
│   │           │   ├── Option.ts
│   │           │   └── components/
│   │           │       ├── boolean.ts
│   │           │       ├── color.ts
│   │           │       ├── enum.ts
│   │           │       ├── font.ts
│   │           │       ├── image.ts
│   │           │       ├── import.ts
│   │           │       ├── number.ts
│   │           │       ├── object.ts
│   │           │       ├── string.ts
│   │           │       └── wallpaper.ts
│   │           └── side_effects/
│   │               └── index.ts
│   ├── fuzzel/
│   │   └── fuzzel.ini
│   ├── hypr/
│   │   ├── hypridle.conf
│   │   ├── hyprland/
│   │   │   ├── colors.conf
│   │   │   ├── env.conf
│   │   │   ├── execs.conf
│   │   │   ├── general.conf
│   │   │   ├── keybinds.conf
│   │   │   └── rules.conf
│   │   ├── hyprland.conf
│   │   ├── hyprlock/
│   │   │   └── status.sh
│   │   ├── hyprlock.conf
│   │   ├── monitors.conf
│   │   ├── shaders/
│   │   │   ├── chromatic_abberation.frag
│   │   │   ├── crt.frag
│   │   │   ├── drugs.frag
│   │   │   ├── extradark.frag
│   │   │   ├── invert.frag
│   │   │   └── solarized.frag
│   │   └── workspaces.conf
│   ├── kitty/
│   │   ├── current-theme.conf
│   │   ├── kitty-hyprland.conf
│   │   ├── kitty-themes/
│   │   │   ├── .all-contributorsrc
│   │   │   ├── .tools/
│   │   │   │   ├── README.md
│   │   │   │   ├── color_table.sh
│   │   │   │   ├── convert.py
│   │   │   │   ├── convert_conf.swift
│   │   │   │   ├── extract-vscode.sh
│   │   │   │   ├── generate_conf.sh
│   │   │   │   ├── generate_theme_preview.sh
│   │   │   │   ├── generate_themes_previews.sh
│   │   │   │   ├── libcapture.sh
│   │   │   │   ├── markdown.sh
│   │   │   │   ├── palette.py
│   │   │   │   ├── preview.py
│   │   │   │   ├── previews.sh
│   │   │   │   ├── template.conf
│   │   │   │   ├── template.conf.j2
│   │   │   │   └── windowid.swift
│   │   │   ├── CONTRIBUTING.md
│   │   │   ├── LICENSE.md
│   │   │   ├── README.md
│   │   │   └── themes/
│   │   │       ├── 3024_Day.conf
│   │   │       ├── 3024_Night.conf
│   │   │       ├── AdventureTime.conf
│   │   │       ├── Afterglow.conf
│   │   │       ├── AlienBlood.conf
│   │   │       ├── Alucard.conf
│   │   │       ├── Apprentice.conf
│   │   │       ├── Argonaut.conf
│   │   │       ├── Arthur.conf
│   │   │       ├── AtelierSulphurpool.conf
│   │   │       ├── Atom.conf
│   │   │       ├── AtomOneLight.conf
│   │   │       ├── Batman.conf
│   │   │       ├── Belafonte_Day.conf
│   │   │       ├── Belafonte_Night.conf
│   │   │       ├── BirdsOfParadise.conf
│   │   │       ├── Blazer.conf
│   │   │       ├── Borland.conf
│   │   │       ├── Bright_Lights.conf
│   │   │       ├── Broadcast.conf
│   │   │       ├── Brogrammer.conf
│   │   │       ├── C64.conf
│   │   │       ├── CLRS.conf
│   │   │       ├── Chalk.conf
│   │   │       ├── Chalkboard.conf
│   │   │       ├── Ciapre.conf
│   │   │       ├── Cobalt2.conf
│   │   │       ├── Cobalt_Neon.conf
│   │   │       ├── CrayonPonyFish.conf
│   │   │       ├── Dark_Pastel.conf
│   │   │       ├── Darkside.conf
│   │   │       ├── Desert.conf
│   │   │       ├── DimmedMonokai.conf
│   │   │       ├── DotGov.conf
│   │   │       ├── Dracula.conf
│   │   │       ├── Dumbledore.conf
│   │   │       ├── Duotone_Dark.conf
│   │   │       ├── ENCOM.conf
│   │   │       ├── Earthsong.conf
│   │   │       ├── Elemental.conf
│   │   │       ├── Espresso.conf
│   │   │       ├── Espresso_Libre.conf
│   │   │       ├── Fideloper.conf
│   │   │       ├── FishTank.conf
│   │   │       ├── Flat.conf
│   │   │       ├── Flatland.conf
│   │   │       ├── Floraverse.conf
│   │   │       ├── FrontEndDelight.conf
│   │   │       ├── FunForrest.conf
│   │   │       ├── Galaxy.conf
│   │   │       ├── Github.conf
│   │   │       ├── Glacier.conf
│   │   │       ├── GoaBase.conf
│   │   │       ├── Grape.conf
│   │   │       ├── Grass.conf
│   │   │       ├── Hardcore.conf
│   │   │       ├── Harper.conf
│   │   │       ├── Highway.conf
│   │   │       ├── Hipster_Green.conf
│   │   │       ├── Homebrew.conf
│   │   │       ├── Hurtado.conf
│   │   │       ├── Hybrid.conf
│   │   │       ├── IC_Green_PPL.conf
│   │   │       ├── IC_Orange_PPL.conf
│   │   │       ├── IR_Black.conf
│   │   │       ├── Jackie_Brown.conf
│   │   │       ├── Japanesque.conf
│   │   │       ├── Jellybeans.conf
│   │   │       ├── JetBrains_Darcula.conf
│   │   │       ├── Kibble.conf
│   │   │       ├── Later_This_Evening.conf
│   │   │       ├── Lavandula.conf
│   │   │       ├── LiquidCarbon.conf
│   │   │       ├── LiquidCarbonTransparent.conf
│   │   │       ├── LiquidCarbonTransparentInverse.conf
│   │   │       ├── Man_Page.conf
│   │   │       ├── Material.conf
│   │   │       ├── MaterialDark.conf
│   │   │       ├── Mathias.conf
│   │   │       ├── Medallion.conf
│   │   │       ├── Misterioso.conf
│   │   │       ├── Molokai.conf
│   │   │       ├── MonaLisa.conf
│   │   │       ├── Monokai.conf
│   │   │       ├── Monokai_Classic.conf
│   │   │       ├── Monokai_Pro.conf
│   │   │       ├── Monokai_Pro_(Filter_Machine).conf
│   │   │       ├── Monokai_Pro_(Filter_Octagon).conf
│   │   │       ├── Monokai_Pro_(Filter_Ristretto).conf
│   │   │       ├── Monokai_Pro_(Filter_Spectrum).conf
│   │   │       ├── Monokai_Soda.conf
│   │   │       ├── N0tch2k.conf
│   │   │       ├── Neopolitan.conf
│   │   │       ├── Neutron.conf
│   │   │       ├── NightLion_v1.conf
│   │   │       ├── NightLion_v2.conf
│   │   │       ├── Nova.conf
│   │   │       ├── Novel.conf
│   │   │       ├── Obsidian.conf
│   │   │       ├── Ocean.conf
│   │   │       ├── OceanicMaterial.conf
│   │   │       ├── Ollie.conf
│   │   │       ├── OneDark.conf
│   │   │       ├── Parasio_Dark.conf
│   │   │       ├── PaulMillr.conf
│   │   │       ├── PencilDark.conf
│   │   │       ├── PencilLight.conf
│   │   │       ├── Piatto_Light.conf
│   │   │       ├── Pnevma.conf
│   │   │       ├── Pro.conf
│   │   │       ├── Red_Alert.conf
│   │   │       ├── Red_Sands.conf
│   │   │       ├── Relaxed_Afterglow.conf
│   │   │       ├── Renault_Style.conf
│   │   │       ├── Renault_Style_Light.conf
│   │   │       ├── Rippedcasts.conf
│   │   │       ├── Royal.conf
│   │   │       ├── SeaShells.conf
│   │   │       ├── Seafoam_Pastel.conf
│   │   │       ├── Seti.conf
│   │   │       ├── Shaman.conf
│   │   │       ├── Slate.conf
│   │   │       ├── Smyck.conf
│   │   │       ├── SoftServer.conf
│   │   │       ├── Solarized_Darcula.conf
│   │   │       ├── Solarized_Dark.conf
│   │   │       ├── Solarized_Dark_-_Patched.conf
│   │   │       ├── Solarized_Dark_Higher_Contrast.conf
│   │   │       ├── Solarized_Light.conf
│   │   │       ├── Source_Code_X.conf
│   │   │       ├── SpaceGray.conf
│   │   │       ├── SpaceGray_Eighties.conf
│   │   │       ├── SpaceGray_Eighties_Dull.conf
│   │   │       ├── Spacedust.conf
│   │   │       ├── Spiderman.conf
│   │   │       ├── Spring.conf
│   │   │       ├── Square.conf
│   │   │       ├── Sundried.conf
│   │   │       ├── Symfonic.conf
│   │   │       ├── Tango_Dark.conf
│   │   │       ├── Tango_Light.conf
│   │   │       ├── Teerb.conf
│   │   │       ├── Thayer_Bright.conf
│   │   │       ├── The_Hulk.conf
│   │   │       ├── Tomorrow.conf
│   │   │       ├── Tomorrow_Night.conf
│   │   │       ├── Tomorrow_Night_Blue.conf
│   │   │       ├── Tomorrow_Night_Bright.conf
│   │   │       ├── Tomorrow_Night_Eighties.conf
│   │   │       ├── ToyChest.conf
│   │   │       ├── Treehouse.conf
│   │   │       ├── Twilight.conf
│   │   │       ├── Ubuntu.conf
│   │   │       ├── Urple.conf
│   │   │       ├── Vaughn.conf
│   │   │       ├── VibrantInk.conf
│   │   │       ├── WarmNeon.conf
│   │   │       ├── Wez.conf
│   │   │       ├── WildCherry.conf
│   │   │       ├── Wombat.conf
│   │   │       ├── Wryan.conf
│   │   │       ├── Zenburn.conf
│   │   │       ├── ayu.conf
│   │   │       ├── ayu_light.conf
│   │   │       ├── ayu_mirage.conf
│   │   │       ├── gruvbox_dark.conf
│   │   │       ├── gruvbox_light.conf
│   │   │       ├── idleToes.conf
│   │   │       ├── rose-pine-moon.conf
│   │   │       └── snazzy.conf
│   │   └── kitty.conf
│   ├── qt5ct/
│   │   └── qt5ct.conf
│   ├── qt6ct/
│   │   ├── colors/
│   │   │   ├── Catppuccin-Latte.conf
│   │   │   └── Catppuccin-Mocha.conf
│   │   └── qt6ct.conf
│   ├── rofi/
│   │   ├── applets/
│   │   │   ├── bin/
│   │   │   │   ├── appasroot.sh
│   │   │   │   ├── apps.sh
│   │   │   │   ├── battery.sh
│   │   │   │   ├── brightness.sh
│   │   │   │   ├── mpd.sh
│   │   │   │   ├── powermenu.sh
│   │   │   │   ├── quicklinks.sh
│   │   │   │   ├── screenshot.sh
│   │   │   │   └── volume.sh
│   │   │   ├── shared/
│   │   │   │   ├── colors.rasi
│   │   │   │   ├── fonts.rasi
│   │   │   │   └── theme.bash
│   │   │   ├── type-1/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-2/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-3/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   ├── type-4/
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   └── style-3.rasi
│   │   │   └── type-5/
│   │   │       ├── style-1.rasi
│   │   │       ├── style-2.rasi
│   │   │       └── style-3.rasi
│   │   ├── colors/
│   │   │   ├── adapta.rasi
│   │   │   ├── arc.rasi
│   │   │   ├── black.rasi
│   │   │   ├── catppuccin.rasi
│   │   │   ├── cyberpunk.rasi
│   │   │   ├── dracula.rasi
│   │   │   ├── everforest.rasi
│   │   │   ├── gruvbox.rasi
│   │   │   ├── lovelace.rasi
│   │   │   ├── navy.rasi
│   │   │   ├── nord.rasi
│   │   │   ├── onedark.rasi
│   │   │   ├── paper.rasi
│   │   │   ├── solarized.rasi
│   │   │   ├── tokyonight.rasi
│   │   │   └── yousai.rasi
│   │   ├── config.rasi
│   │   ├── launchers/
│   │   │   ├── type-1/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-11.rasi
│   │   │   │   ├── style-12.rasi
│   │   │   │   ├── style-13.rasi
│   │   │   │   ├── style-14.rasi
│   │   │   │   ├── style-15.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-2/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-11.rasi
│   │   │   │   ├── style-12.rasi
│   │   │   │   ├── style-13.rasi
│   │   │   │   ├── style-14.rasi
│   │   │   │   ├── style-15.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-3/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-4/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── shared/
│   │   │   │   │   ├── colors.rasi
│   │   │   │   │   └── fonts.rasi
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   ├── type-5/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   └── style-5.rasi
│   │   │   ├── type-6/
│   │   │   │   ├── launcher.sh
│   │   │   │   ├── style-1.rasi
│   │   │   │   ├── style-10.rasi
│   │   │   │   ├── style-2.rasi
│   │   │   │   ├── style-3.rasi
│   │   │   │   ├── style-4.rasi
│   │   │   │   ├── style-5.rasi
│   │   │   │   ├── style-6.rasi
│   │   │   │   ├── style-7.rasi
│   │   │   │   ├── style-8.rasi
│   │   │   │   └── style-9.rasi
│   │   │   └── type-7/
│   │   │       ├── launcher.sh
│   │   │       ├── style-1.rasi
│   │   │       ├── style-10.rasi
│   │   │       ├── style-2.rasi
│   │   │       ├── style-3.rasi
│   │   │       ├── style-4.rasi
│   │   │       ├── style-5.rasi
│   │   │       ├── style-6.rasi
│   │   │       ├── style-7.rasi
│   │   │       ├── style-8.rasi
│   │   │       └── style-9.rasi
│   │   └── powermenu/
│   │       ├── type-1/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-2/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-10.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   ├── style-5.rasi
│   │       │   ├── style-6.rasi
│   │       │   ├── style-7.rasi
│   │       │   ├── style-8.rasi
│   │       │   └── style-9.rasi
│   │       ├── type-3/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   ├── confirm.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-4/
│   │       │   ├── powermenu.sh
│   │       │   ├── shared/
│   │       │   │   ├── colors.rasi
│   │       │   │   ├── confirm.rasi
│   │       │   │   └── fonts.rasi
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       ├── type-5/
│   │       │   ├── powermenu.sh
│   │       │   ├── style-1.rasi
│   │       │   ├── style-2.rasi
│   │       │   ├── style-3.rasi
│   │       │   ├── style-4.rasi
│   │       │   └── style-5.rasi
│   │       └── type-6/
│   │           ├── powermenu.sh
│   │           ├── style-1.rasi
│   │           ├── style-2.rasi
│   │           ├── style-3.rasi
│   │           ├── style-4.rasi
│   │           └── style-5.rasi
│   ├── wlogout/
│   │   ├── layout
│   │   └── style.css
│   └── zshrc.d/
│       ├── auto-Hypr.sh
│       ├── dots-hyprland.zsh
│       └── shortcuts.zsh
├── .fastfetch_conf.jsonc
├── .fonts/
│   ├── .uuid
│   └── CustomTkinter_shapes_font.otf
├── .gitattributes
├── .zprofile
├── .zshenv
├── .zshrc
├── README.md
├── backup.sh
└── hyprpanel_config.json
Download .txt
SYMBOL INDEX (240 symbols across 62 files)

FILE: .config/ags/customModules/netstat/computeNetwork.ts
  type NetworkUsage (line 30) | interface NetworkUsage {

FILE: .config/ags/customModules/utils.ts
  function throttle (line 32) | function throttle<T extends ThrottleFn>(func: T, limit: number): T {

FILE: .config/ags/directoryMonitorService.ts
  class DirectoryMonitorService (line 7) | class DirectoryMonitorService extends Service {
    method constructor (line 12) | constructor() {
    method recursiveDirectoryMonitor (line 17) | recursiveDirectoryMonitor(directoryPath: string): void {

FILE: .config/ags/globals/dropdown.ts
  type GlobalEventBoxes (line 3) | type GlobalEventBoxes = {

FILE: .config/ags/globals/network.ts
  constant WIFI_STATUS_MAP (line 1) | const WIFI_STATUS_MAP = {

FILE: .config/ags/globals/weather.ts
  type IconKeys (line 80) | type IconKeys = keyof typeof icons;

FILE: .config/ags/globals/window.ts
  constant WINDOW_LAYOUTS (line 1) | const WINDOW_LAYOUTS: string[] = [

FILE: .config/ags/lib/option.ts
  type OptProps (line 5) | type OptProps = {
  class Opt (line 9) | class Opt<T = unknown> extends Variable<T> {
    method constructor (line 14) | constructor(initial: T, { persistent = false }: OptProps = {}) {
    method toString (line 23) | toString(): string {
    method toJSON (line 26) | toJSON(): string {
    method init (line 33) | init(cacheFile: string): void {
    method reset (line 44) | reset(): string | undefined {
    method doResetColor (line 53) | doResetColor(): string | undefined {
  function mkOptions (line 86) | function mkOptions<T extends object>(

FILE: .config/ags/lib/types/audio.d.ts
  type InputDevices (line 1) | type InputDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribu...
  type DummyDevices (line 3) | type DummyDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribu...
  type RealPlaybackDevices (line 4) | type RealPlaybackDevices = Button<Box<Box<Label<Attribute>, Attribute>, ...
  type PlaybackDevices (line 5) | type PlaybackDevices = DummyDevices | RealPlaybackDevices;

FILE: .config/ags/lib/types/bar.d.ts
  type BarBoxChild (line 8) | type BarBoxChild = {
  type SelfButton (line 17) | type SelfButton = Button<Child, Attribute>;
  type BoxHook (line 19) | type BoxHook = (self: Box<Gtk.Widget, Gtk.Widget>) => void;
  type LabelHook (line 20) | type LabelHook = (self: Label<Gtk.Widget>) => void;
  type Module (line 22) | type Module = {
  type ResourceLabelType (line 37) | type ResourceLabelType = 'used/total' | 'used' | 'percentage' | 'free';
  type NetstatLabelType (line 39) | type NetstatLabelType = 'full' | 'in' | 'out';
  type RateUnit (line 40) | type RateUnit = 'GiB' | 'MiB' | 'KiB' | 'auto';

FILE: .config/ags/lib/types/customModules/generic.d.ts
  type GenericFunction (line 1) | type GenericFunction<T, P extends unknown[] = unknown[]> = (...args: P) ...
  type GenericResourceMetrics (line 3) | type GenericResourceMetrics = {
  type GenericResourceData (line 9) | type GenericResourceData = GenericResourceMetrics & {
  type Postfix (line 13) | type Postfix = 'TiB' | 'GiB' | 'MiB' | 'KiB' | 'B';

FILE: .config/ags/lib/types/customModules/kbLayout.d.ts
  type KbLabelType (line 3) | type KbLabelType = 'layout' | 'code';
  type HyprctlKeyboard (line 5) | type HyprctlKeyboard = {
  type HyprctlMouse (line 17) | type HyprctlMouse = {
  type HyprctlDeviceLayout (line 23) | type HyprctlDeviceLayout = {
  type LayoutKeys (line 31) | type LayoutKeys = keyof typeof layoutMap;
  type LayoutValues (line 32) | type LayoutValues = (typeof layoutMap)[LayoutKeys];

FILE: .config/ags/lib/types/customModules/network.d.ts
  type NetworkResourceData (line 1) | type NetworkResourceData = {

FILE: .config/ags/lib/types/customModules/utils.d.ts
  type InputHandlerEvents (line 3) | type InputHandlerEvents = {
  type RunAsyncCommand (line 11) | type RunAsyncCommand = (cmd: string, args: EventArgs, fn?: (output: stri...

FILE: .config/ags/lib/types/defaults/bar.ts
  constant LABEL_TYPES (line 3) | const LABEL_TYPES: ResourceLabelType[] = ['used/total', 'used', 'free', ...
  constant NETWORK_LABEL_TYPES (line 5) | const NETWORK_LABEL_TYPES: NetstatLabelType[] = ['full', 'in', 'out'];

FILE: .config/ags/lib/types/defaults/weather.ts
  constant DEFAULT_WEATHER (line 1) | const DEFAULT_WEATHER = {

FILE: .config/ags/lib/types/dropdownmenu.d.ts
  type DropdownMenuProps (line 5) | type DropdownMenuProps = {

FILE: .config/ags/lib/types/filechooser.d.ts
  type Config (line 1) | type Config = {

FILE: .config/ags/lib/types/globals.d.ts
  type MousePos (line 1) | type MousePos = {

FILE: .config/ags/lib/types/gpustat.d.ts
  type GPU_Stat_Process (line 1) | type GPU_Stat_Process = {
  type GPU_Stat (line 11) | type GPU_Stat = {

FILE: .config/ags/lib/types/mpris.d.ts
  type LoopStatus (line 1) | type LoopStatus = 'none' | 'track' | 'playlist';
  type PlaybackStatus (line 2) | type PlaybackStatus = 'playing' | 'paused' | 'stopped';

FILE: .config/ags/lib/types/network.d.ts
  type AccessPoint (line 3) | type AccessPoint = {
  type WifiStatus (line 14) | type WifiStatus = keyof typeof WIFI_STATUS_MAP;
  type WifiIcon (line 16) | type WifiIcon = '󰤩' | '󰤨' | '󰤪' | '󰤨' | '󰤩' | '󰤮' | '󰤨' | '󰤥' | '󰤢' | '󰤟...

FILE: .config/ags/lib/types/notification.d.ts
  type NotificationArgs (line 3) | interface NotificationArgs {
  type NotificationIcon (line 15) | type NotificationIcon = keyof typeof icons.notifications;

FILE: .config/ags/lib/types/options.d.ts
  type MkOptionsResult (line 5) | type MkOptionsResult = {
  type RecursiveOptionsObject (line 13) | type RecursiveOptionsObject = {
  type BarLocation (line 17) | type BarLocation = 'top' | 'bottom';
  type Unit (line 19) | type Unit = 'imperial' | 'metric';
  type PowerOptions (line 20) | type PowerOptions = 'sleep' | 'reboot' | 'logout' | 'shutdown';
  type NotificationAnchor (line 21) | type NotificationAnchor =
  type OSDAnchor (line 30) | type OSDAnchor = 'top left' | 'top' | 'top right' | 'right' | 'bottom ri...
  type BarButtonStyles (line 31) | type BarButtonStyles = 'default' | 'split' | 'wave' | 'wave2';
  type ThemeExportData (line 33) | type ThemeExportData = {
  type RowProps (line 37) | type RowProps<T> = {
  type OSDOrientation (line 66) | type OSDOrientation = 'horizontal' | 'vertical';
  type HexColor (line 68) | type HexColor = `#${string}`;
  type WindowLayer (line 70) | type WindowLayer = 'top' | 'bottom' | 'overlay' | 'background';
  type ActiveWsIndicator (line 72) | type ActiveWsIndicator = 'underline' | 'highlight' | 'color';
  type MatugenColors (line 74) | type MatugenColors = {
  type MatugenVariation (line 125) | type MatugenVariation = {
  type MatugenScheme (line 191) | type MatugenScheme =
  type MatugenVariations (line 201) | type MatugenVariations =
  type MatugenTheme (line 212) | type MatugenTheme = 'light' | 'dark';
  type ColorMapKey (line 214) | type ColorMapKey = keyof typeof defaultColorMap;
  type ColorMapValue (line 215) | type ColorMapValue = (typeof defaultColorMap)[ColorMapKey];
  type ScalingPriority (line 217) | type ScalingPriority = 'gdk' | 'hyprland' | 'both';

FILE: .config/ags/lib/types/popupwindow.d.ts
  type PopupWindowProps (line 5) | type PopupWindowProps = {
  type LayoutFunction (line 13) | type LayoutFunction = (
  type Layouts (line 27) | type Layouts =

FILE: .config/ags/lib/types/power.d.ts
  type Action (line 1) | type Action = 'sleep' | 'reboot' | 'logout' | 'shutdown';

FILE: .config/ags/lib/types/powerprofiles.d.ts
  type PowerProfiles (line 3) | type PowerProfiles = InstanceType<typeof PowerProfiles>;
  type PowerProfile (line 4) | type PowerProfile = 'power-saver' | 'balanced' | 'performance';
  type PowerProfileObject (line 5) | type PowerProfileObject = {

FILE: .config/ags/lib/types/utils.d.ts
  type SubstituteKeys (line 4) | type SubstituteKeys = keyof typeof substitutes;
  type ThrottleFn (line 6) | type ThrottleFn = (cmd: string, args: EventArgs, fn?: (output: string) =...
  type ThrottleFnCallback (line 7) | type ThrottleFnCallback = ((output: string) => void) | undefined;

FILE: .config/ags/lib/types/variable.d.ts
  type Bind (line 1) | type Bind = OriginalBinding<GObject.Object, keyof Props<GObject.Object>,...

FILE: .config/ags/lib/types/volume.d.ts
  type VolumeIcons (line 1) | type VolumeIcons = {

FILE: .config/ags/lib/types/weather.d.ts
  type UnitType (line 3) | type UnitType = 'imperial' | 'metric';
  type Weather (line 5) | type Weather = {
  type Current (line 11) | type Current = {
  type Condition (line 50) | type Condition = {
  type Forecast (line 56) | type Forecast = {
  type Forecastday (line 60) | type Forecastday = {
  type Astro (line 68) | type Astro = {
  type Day (line 79) | type Day = {
  type Location (line 102) | type Location = {
  type TemperatureIconColorMap (line 113) | type TemperatureIconColorMap = {
  type WeatherIconTitle (line 117) | type WeatherIconTitle = keyof typeof weatherIcons;
  type WeatherIcon (line 118) | type WeatherIcon = (typeof weatherIcons)[WeatherIconTitle];

FILE: .config/ags/lib/types/widget.d.ts
  type Exclusivity (line 4) | type Exclusivity = 'normal' | 'ignore' | 'exclusive';
  type Anchor (line 5) | type Anchor = 'left' | 'right' | 'top' | 'down';
  type Transition (line 6) | type Transition = 'none' | 'crossfade' | 'slide_right' | 'slide_left' | ...
  type Layouts (line 8) | type Layouts =
  type Attribute (line 18) | type Attribute = unknown;
  type Child (line 19) | type Child = Gtk.Widget;
  type GtkWidget (line 20) | type GtkWidget = Gtk.Widget;
  type BoxWidget (line 21) | type BoxWidget = Box<GtkWidget, Child>;
  type GButton (line 23) | type GButton = Gtk.Button;
  type GBox (line 24) | type GBox = Gtk.Box;
  type GLabel (line 25) | type GLabel = Gtk.Label;
  type GCenterBox (line 26) | type GCenterBox = Gtk.Box;
  type EventHandler (line 28) | type EventHandler<Self> = (self: Self, event: Gdk.Event) => boolean | un...
  type EventArgs (line 29) | type EventArgs = { clicked: Button<Child, Attribute>; event: Gdk.Event };

FILE: .config/ags/lib/types/workspace.d.ts
  type WorkspaceRule (line 1) | type WorkspaceRule = {
  type WorkspaceMap (line 6) | type WorkspaceMap = {
  type MonitorMap (line 10) | type MonitorMap = {
  type WorkspaceIcons (line 14) | type WorkspaceIcons = {
  type WorkspaceIconsColored (line 18) | type WorkspaceIconsColored = {
  type WorkspaceIconMap (line 25) | type WorkspaceIconMap = WorkspaceIcons | WorkspaceIconsColored;

FILE: .config/ags/lib/utils.ts
  type Binding (line 15) | type Binding<T> = import('types/service').Binding
  function icon (line 20) | function icon(name: string | null, fallback = icons.missing): string {
  function bash (line 42) | async function bash(strings: TemplateStringsArray | string, ...values: u...
  function sh (line 55) | async function sh(cmd: string | string[]): Promise<string> {
  function forMonitors (line 62) | function forMonitors(widget: (monitor: number) => Gtk.Window): Window[] {
  function range (line 70) | function range(length: number, start = 1): number[] {
  function dependencies (line 77) | function dependencies(...bins: string[]): boolean {
  function launchApp (line 102) | function launchApp(app: Application): void {
  function createSurfaceFromWidget (line 115) | function createSurfaceFromWidget(widget: Gtk.Widget): GdkPixbuf.Pixbuf {

FILE: .config/ags/modules/bar/Bar.ts
  type BarWidget (line 42) | type BarWidget = keyof typeof widget;
  type Section (line 44) | type Section =
  type Layout (line 66) | type Layout = {
  type BarLayout (line 72) | type BarLayout = {
  type GdkMonitors (line 118) | type GdkMonitors = {
  function getGdkMonitors (line 126) | function getGdkMonitors(): GdkMonitors {

FILE: .config/ags/modules/bar/workspaces/helpers.ts
  type ThrottledScrollHandlers (line 70) | type ThrottledScrollHandlers = {
  function throttle (line 127) | function throttle<T extends (...args: unknown[]) => void>(func: T, limit...

FILE: .config/ags/modules/menus/audio/utils.ts
  type IconVolumes (line 17) | type IconVolumes = keyof typeof speakerIcons;

FILE: .config/ags/modules/menus/dashboard/shortcuts/index.ts
  type ShortcutFixed (line 78) | type ShortcutFixed = {
  type ShortcutVariable (line 85) | type ShortcutVariable = {
  type Shortcut (line 92) | type Shortcut = ShortcutFixed | ShortcutVariable;

FILE: .config/ags/modules/menus/energy/profiles/index.ts
  function renderUptime (line 11) | function renderUptime(curUptime: number): string {

FILE: .config/ags/modules/menus/power/helpers/actions.ts
  class PowerMenu (line 5) | class PowerMenu extends Service {
    method title (line 20) | get title(): string {
    method action (line 24) | action(action: Action): void {
    method customAction (line 39) | customAction(action: Action, cmnd: string): void {

FILE: .config/ags/modules/menus/shared/dropdown/locationHandler/index.ts
  type NestedRevealer (line 12) | type NestedRevealer = Revealer<Box<TWidget, unknown>, unknown>;
  type NestedBox (line 13) | type NestedBox = Box<NestedRevealer, unknown>;
  type NestedEventBox (line 14) | type NestedEventBox = EventBox<NestedBox, unknown>;

FILE: .config/ags/modules/menus/shared/popup/index.ts
  type Opts (line 8) | type Opts = {

FILE: .config/ags/scripts/color_generation/generate_colors_material.py
  function calculate_optimal_size (line 35) | def calculate_optimal_size (width: int, height: int, bitmap_size: int) -...
  function harmonize (line 47) | def harmonize (design_color: int, source_color: int, threshold: float = ...
  function boost_chroma_tone (line 57) | def boost_chroma_tone (argb: int, chroma: float = 1, tone: float = 1) ->...

FILE: .config/ags/scripts/color_generation/schemes/scheme_morevibrant.py
  class SchemeMoreVibrant (line 6) | class SchemeMoreVibrant(DynamicScheme):
    method __init__ (line 11) | def __init__(self, source_color_hct, is_dark, contrast_level):

FILE: .config/ags/scripts/fillThemes.js
  constant COLORS (line 23) | const COLORS = {

FILE: .config/ags/scripts/hyprland/get_keybinds.py
  class KeyBinding (line 23) | class KeyBinding(dict):
    method __init__ (line 24) | def __init__(self, mods, key, dispatcher, params, comment) -> None:
  class Section (line 31) | class Section(dict):
    method __init__ (line 32) | def __init__(self, children, keybinds, name) -> None:
  function read_content (line 38) | def read_content(path: str) -> str:
  function autogenerate_comment (line 45) | def autogenerate_comment(dispatcher: str, params: str = "") -> str:
  function get_keybind_at_line (line 139) | def get_keybind_at_line(line_number, line_start = 0):
  function get_binds_recursive (line 172) | def get_binds_recursive(current_content, scope):
  function parse_keys (line 210) | def parse_keys(path: str) -> Dict[str, List[KeyBinding]]:

FILE: .config/ags/scripts/wayland-idle-inhibitor.py
  class GlobalRegistry (line 19) | class GlobalRegistry:
  function handle_registry_global (line 24) | def handle_registry_global(
  function main (line 38) | def main() -> None:

FILE: .config/ags/scss/style.ts
  function extractVariables (line 10) | function extractVariables(theme: RecursiveOptionsObject, prefix = '', ma...

FILE: .config/ags/services/Brightness.ts
  class Brightness (line 10) | class Brightness extends Service {
    method kbd (line 27) | get kbd(): number {
    method screen (line 30) | get screen(): number {
    method kbd (line 34) | set kbd(value) {
    method screen (line 43) | set screen(percent) {
    method constructor (line 54) | constructor() {

FILE: .config/ags/services/Cpu.ts
  class Cpu (line 8) | class Cpu {
    method constructor (line 14) | constructor() {
    method calculateUsage (line 21) | public calculateUsage(): number {
    method updateTimer (line 36) | public updateTimer(timerInMs: number): void {

FILE: .config/ags/services/Ram.ts
  class Ram (line 8) | class Ram {
    method constructor (line 14) | constructor() {
    method calculateUsage (line 19) | public calculateUsage(): GenericResourceData {
    method setShouldRound (line 54) | public setShouldRound(round: boolean): void {
    method divide (line 58) | private divide([total, used]: number[]): number {
    method updateTimer (line 68) | updateTimer(timerInMs: number): void {

FILE: .config/ags/services/Storage.ts
  class Storage (line 9) | class Storage {
    method constructor (line 15) | constructor() {
    method calculateUsage (line 20) | public calculateUsage(): GenericResourceData {
    method setShouldRound (line 42) | public setShouldRound(round: boolean): void {
    method divide (line 46) | private divide([total, used]: number[]): number {
    method updateTimer (line 56) | public updateTimer(timerInMs: number): void {

FILE: .config/ags/services/Wallpaper.ts
  class Wallpaper (line 7) | class Wallpaper extends Service {
    method #wallpaper (line 21) | #wallpaper(): void {
    method #setWallpaper (line 45) | async #setWallpaper(path: string): Promise<void> {
    method wallpaper (line 61) | get wallpaper(): string {
    method constructor (line 65) | constructor() {

FILE: .config/ags/services/bluetooth.py
  function send_notification_with_actions (line 15) | def send_notification_with_actions(title, message, actions, action_handl...
  class Agent (line 24) | class Agent(dbus.service.Object):
    method __init__ (line 25) | def __init__(self, bus):
    method Release (line 29) | def Release(self):
    method get_device_name (line 32) | def get_device_name(self, device):
    method RequestPinCode (line 39) | def RequestPinCode(self, device):
    method RequestPasskey (line 45) | def RequestPasskey(self, device):
    method DisplayPasskey (line 51) | def DisplayPasskey(self, device, passkey):
    method RequestConfirmation (line 57) | def RequestConfirmation(self, device, passkey):
    method RequestAuthorization (line 76) | def RequestAuthorization(self, device):
    method AuthorizeService (line 95) | def AuthorizeService(self, device, uuid):
    method Cancel (line 114) | def Cancel(self):
    method request_input (line 117) | def request_input(self, title, message, device, input_type):
    method handle_pin_input (line 132) | def handle_pin_input(self, device, pin_code):
    method handle_passkey_input (line 136) | def handle_passkey_input(self, device, passkey):
    method send_reply (line 140) | def send_reply(self, device):
    method send_error (line 147) | def send_error(self, device, error):
    method success_callback (line 154) | def success_callback(self):
    method error_callback (line 157) | def error_callback(self, error):
  function register_agent (line 160) | def register_agent():

FILE: .config/ags/services/matugen/index.ts
  function generateMatugenColors (line 15) | async function generateMatugenColors(): Promise<MatugenColors | undefine...

FILE: .config/ags/widget/settings/SettingsDialog.ts
  type Page (line 10) | type Page = 'Configuration' | 'Theming';
  method setup (line 77) | setup(win) {

FILE: .config/ags/widget/settings/pages/config/index.ts
  type Page (line 11) | type Page =

FILE: .config/ags/widget/settings/pages/theme/index.ts
  type Page (line 19) | type Page =

FILE: .config/ags/widget/settings/shared/components/number.ts
  method setup (line 29) | setup(self) {

FILE: .config/kitty/kitty-themes/.tools/convert.py
  function removeAlpha (line 7) | def removeAlpha(value):

FILE: .config/kitty/kitty-themes/.tools/palette.py
  function is_valid (line 12) | def is_valid(line):
  function extract_configuration_pair (line 27) | def extract_configuration_pair(line):
  function read_configuration (line 40) | def read_configuration(filename):
  function draw_theme_palette (line 56) | def draw_theme_palette(theme_configuration, start_point, size, displacem...
  function draw_all_palettes (line 66) | def draw_all_palettes(themes):
  function main (line 79) | def main():

FILE: .config/kitty/kitty-themes/.tools/preview.py
  function is_valid (line 12) | def is_valid(line):
  function extract_configuration_pair (line 27) | def extract_configuration_pair(line):
  function read_configuration (line 40) | def read_configuration(filename):
  function fg (line 55) | def fg(color, text):
  function bg (line 60) | def bg(color, text):
  function print_preview (line 65) | def print_preview(filename, configuration):
  function main (line 124) | def main(directory):
Condensed preview — 749 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,823K chars).
[
  {
    "path": ".config/ags/.eslintignore",
    "chars": 19,
    "preview": "types\nnode_modules\n"
  },
  {
    "path": ".config/ags/.eslintrc.js",
    "chars": 914,
    "preview": "module.exports = {\n    parser: '@typescript-eslint/parser',\n    parserOptions: {\n        project: 'tsconfig.json',\n     "
  },
  {
    "path": ".config/ags/.github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 618,
    "preview": "---\nname: Bug report\nabout: Create a report to help HyprPanel improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describ"
  },
  {
    "path": ".config/ags/.github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".config/ags/.github/workflows/ci.yml",
    "chars": 1013,
    "preview": "name: CI\n\non:\n    pull_request:\n        branches:\n            - master\n\njobs:\n    code_quality:\n        runs-on: ubuntu-"
  },
  {
    "path": ".config/ags/.gitignore",
    "chars": 27,
    "preview": ".weather.json\nnode_modules\n"
  },
  {
    "path": ".config/ags/.gitmodules",
    "chars": 113,
    "preview": "[submodule \"external/ags-types\"]\n\tpath = external/ags-types\n\turl = https://github.com/Jas-SinghFSU/ags-types.git\n"
  },
  {
    "path": ".config/ags/.prettierignore",
    "chars": 27,
    "preview": ".eslintrc.js\ntypes/**/*.ts\n"
  },
  {
    "path": ".config/ags/.prettierrc",
    "chars": 138,
    "preview": "{\n    \"singleQuote\": true,\n    \"semi\": true,\n    \"trailingComma\": \"all\",\n    \"printWidth\": 120,\n    \"tabWidth\": 4,\n    \""
  },
  {
    "path": ".config/ags/LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2024 Jas Singh\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": ".config/ags/README.md",
    "chars": 7836,
    "preview": "<p align=\"center\">\n  <a href=\"https://hyprpanel.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n    <img width=\"180\" src"
  },
  {
    "path": ".config/ags/config.js",
    "chars": 1422,
    "preview": "import GLib from 'gi://GLib';\n\nconst main = '/tmp/ags/hyprpanel/main.js';\nconst entry = `${App.configDir}/main.ts`;\ncons"
  },
  {
    "path": ".config/ags/customModules/PollVar.ts",
    "chars": 3029,
    "preview": "import GLib from 'gi://GLib?version=2.0';\nimport { GenericFunction } from 'lib/types/customModules/generic';\nimport { Bi"
  },
  {
    "path": ".config/ags/customModules/config.ts",
    "chars": 22921,
    "preview": "import { Option } from 'widget/settings/shared/Option';\nimport { Header } from 'widget/settings/shared/Header';\n\nimport "
  },
  {
    "path": ".config/ags/customModules/cpu/computeCPU.ts",
    "chars": 770,
    "preview": "// @ts-expect-error: This import is a special directive that tells the compiler to use the GTop library\nimport GTop from"
  },
  {
    "path": ".config/ags/customModules/cpu/index.ts",
    "chars": 2212,
    "preview": "import options from 'options';\n\n// Module initializer\nimport { module } from '../module';\n\nimport Button from 'types/wid"
  },
  {
    "path": ".config/ags/customModules/kblayout/getLayout.ts",
    "chars": 850,
    "preview": "import {\n    HyprctlDeviceLayout,\n    HyprctlKeyboard,\n    KbLabelType,\n    LayoutKeys,\n    LayoutValues,\n} from 'lib/ty"
  },
  {
    "path": ".config/ags/customModules/kblayout/index.ts",
    "chars": 2396,
    "preview": "const hyprland = await Service.import('hyprland');\n\nimport options from 'options';\nimport { module } from '../module';\n\n"
  },
  {
    "path": ".config/ags/customModules/kblayout/layouts.ts",
    "chars": 25123,
    "preview": "export const layoutMap = {\n    'Abkhazian (Russia)': 'RU (Ab)',\n    Akan: 'GH (Akan)',\n    Albanian: 'AL',\n    'Albanian"
  },
  {
    "path": ".config/ags/customModules/module.ts",
    "chars": 2780,
    "preview": "import { BarBoxChild, Module } from 'lib/types/bar';\nimport { BarButtonStyles } from 'lib/types/options';\nimport { Bind "
  },
  {
    "path": ".config/ags/customModules/netstat/computeNetwork.ts",
    "chars": 3676,
    "preview": "import GLib from 'gi://GLib';\nimport { Variable as VariableType } from 'types/variable';\nimport { NetworkResourceData } "
  },
  {
    "path": ".config/ags/customModules/netstat/index.ts",
    "chars": 3938,
    "preview": "import options from 'options';\nimport { module } from '../module';\nimport { inputHandler } from 'customModules/utils';\ni"
  },
  {
    "path": ".config/ags/customModules/power/index.ts",
    "chars": 1248,
    "preview": "import options from 'options';\nimport { module } from '../module';\n\nimport { inputHandler } from 'customModules/utils';\n"
  },
  {
    "path": ".config/ags/customModules/ram/computeRam.ts",
    "chars": 1544,
    "preview": "const GLib = imports.gi.GLib;\n\nimport { divide } from 'customModules/utils';\nimport { GenericResourceData } from 'lib/ty"
  },
  {
    "path": ".config/ags/customModules/ram/index.ts",
    "chars": 2924,
    "preview": "import options from 'options';\n\n// Module initializer\nimport { module } from '../module';\n\n// Types\nimport { GenericReso"
  },
  {
    "path": ".config/ags/customModules/storage/computeStorage.ts",
    "chars": 1059,
    "preview": "// @ts-expect-error is a special directive that tells the compiler to use the GTop library\nimport GTop from 'gi://GTop';"
  },
  {
    "path": ".config/ags/customModules/storage/index.ts",
    "chars": 2736,
    "preview": "import options from 'options';\nimport { module } from '../module';\n\nimport { formatTooltip, inputHandler, renderResource"
  },
  {
    "path": ".config/ags/customModules/submap/helpers.ts",
    "chars": 569,
    "preview": "import { Variable } from 'types/variable';\n\nconst hyprland = await Service.import('hyprland');\n\nexport const isSubmapEna"
  },
  {
    "path": ".config/ags/customModules/submap/index.ts",
    "chars": 3116,
    "preview": "const hyprland = await Service.import('hyprland');\nimport options from 'options';\nimport { module } from '../module';\n\ni"
  },
  {
    "path": ".config/ags/customModules/theme.ts",
    "chars": 8979,
    "preview": "import { Option } from 'widget/settings/shared/Option';\nimport { Header } from 'widget/settings/shared/Header';\n\nimport "
  },
  {
    "path": ".config/ags/customModules/updates/index.ts",
    "chars": 1975,
    "preview": "import options from 'options';\nimport { module } from '../module';\n\nimport { inputHandler } from 'customModules/utils';\n"
  },
  {
    "path": ".config/ags/customModules/utils.ts",
    "chars": 7513,
    "preview": "import { ResourceLabelType } from 'lib/types/bar';\nimport { GenericResourceData, Postfix } from 'lib/types/customModules"
  },
  {
    "path": ".config/ags/customModules/weather/index.ts",
    "chars": 1933,
    "preview": "import options from 'options';\nimport { module } from '../module';\n\nimport { inputHandler } from 'customModules/utils';\n"
  },
  {
    "path": ".config/ags/directoryMonitorService.ts",
    "chars": 1348,
    "preview": "import Service from 'resource:///com/github/Aylur/ags/service.js';\nimport App from 'resource:///com/github/Aylur/ags/app"
  },
  {
    "path": ".config/ags/flake.nix",
    "chars": 2420,
    "preview": "{\n  description = \"A Bar/Panel for Hyprland with extensive customizability.\";\n\n  inputs = {\n    nixpkgs.url = \"github:ni"
  },
  {
    "path": ".config/ags/globals/dropdown.ts",
    "chars": 195,
    "preview": "import { Variable as VariableType } from 'types/variable';\n\ntype GlobalEventBoxes = {\n    [key: string]: unknown;\n};\nexp"
  },
  {
    "path": ".config/ags/globals/mousePos.ts",
    "chars": 179,
    "preview": "import { Variable as VariableType } from 'types/variable';\n\nconst globalMousePosVar: VariableType<number[]> = Variable(["
  },
  {
    "path": ".config/ags/globals/network.ts",
    "chars": 476,
    "preview": "export const WIFI_STATUS_MAP = {\n    unknown: 'Status Unknown',\n    unmanaged: 'Unmanaged',\n    unavailable: 'Unavailabl"
  },
  {
    "path": ".config/ags/globals/notification.ts",
    "chars": 1193,
    "preview": "import icons from 'modules/icons/index';\nimport { Notification } from 'types/service/notifications';\n\nexport const remov"
  },
  {
    "path": ".config/ags/globals/useTheme.ts",
    "chars": 1499,
    "preview": "import Gio from 'gi://Gio';\nimport { bash, Notify } from 'lib/utils';\nimport icons from 'lib/icons';\nimport { filterConf"
  },
  {
    "path": ".config/ags/globals/utilities.ts",
    "chars": 210,
    "preview": "globalThis.isWindowVisible = (windowName: string): boolean => {\n    const appWindow = App.getWindow(windowName);\n\n    if"
  },
  {
    "path": ".config/ags/globals/variables.ts",
    "chars": 1302,
    "preview": "import { Opt } from 'lib/option';\nimport { HexColor, MatugenTheme, RecursiveOptionsObject } from 'lib/types/options';\n\ne"
  },
  {
    "path": ".config/ags/globals/weather.ts",
    "chars": 4109,
    "preview": "import options from 'options';\nimport { UnitType, Weather, WeatherIconTitle, WeatherIcon } from 'lib/types/weather.js';\n"
  },
  {
    "path": ".config/ags/globals/window.ts",
    "chars": 181,
    "preview": "export const WINDOW_LAYOUTS: string[] = [\n    'center',\n    'top',\n    'top-right',\n    'top-center',\n    'top-left',\n  "
  },
  {
    "path": ".config/ags/globals.d.ts",
    "chars": 378,
    "preview": "// globals.d.ts\n/* eslint-disable no-var */\n\nimport { Options, Variable as VariableType } from 'types/variable';\n\ndeclar"
  },
  {
    "path": ".config/ags/install_fonts.sh",
    "chars": 649,
    "preview": "#!/bin/bash\n\nSOURCE_DIR=\"./assets/fonts\"\nDEST_DIR=\"$HOME/.local/share/fonts\"\nDEST_PATH=\"$DEST_DIR/NFP\"\n\nif [ ! -d \"$SOUR"
  },
  {
    "path": ".config/ags/lib/constants/colors.ts",
    "chars": 2506,
    "preview": "export const namedColors = new Set([\n    'alice blue',\n    'antique white',\n    'aqua',\n    'aquamarine',\n    'azure',\n "
  },
  {
    "path": ".config/ags/lib/icons.ts",
    "chars": 4870,
    "preview": "export const substitutes = {\n    'transmission-gtk': 'transmission',\n    'blueberry.py': 'blueberry',\n    Caprine: 'face"
  },
  {
    "path": ".config/ags/lib/option.ts",
    "chars": 4625,
    "preview": "import { isHexColor } from 'globals/variables';\nimport { Variable } from 'resource:///com/github/Aylur/ags/variable.js';"
  },
  {
    "path": ".config/ags/lib/session.ts",
    "chars": 391,
    "preview": "import GLib from 'gi://GLib?version=2.0';\n\ndeclare global {\n    const OPTIONS: string;\n    const TMP: string;\n    const "
  },
  {
    "path": ".config/ags/lib/shared/media.ts",
    "chars": 832,
    "preview": "import { MprisPlayer } from 'types/service/mpris';\nconst mpris = await Service.import('mpris');\n\nexport const getCurrent"
  },
  {
    "path": ".config/ags/lib/shared/notifications.ts",
    "chars": 537,
    "preview": "import { Notification } from 'types/service/notifications';\n\nexport const filterNotifications = (notifications: Notifica"
  },
  {
    "path": ".config/ags/lib/types/audio.d.ts",
    "chars": 354,
    "preview": "export type InputDevices = Button<Box<Box<Label<Attribute>, Attribute>, Attribute>, Attribute>[];\n\ntype DummyDevices = B"
  },
  {
    "path": ".config/ags/lib/types/bar.d.ts",
    "chars": 1273,
    "preview": "import { Binding, Connectable } from 'types/service';\nimport { Variable } from 'types/variable';\nimport Box from 'types/"
  },
  {
    "path": ".config/ags/lib/types/customModules/generic.d.ts",
    "chars": 332,
    "preview": "export type GenericFunction<T, P extends unknown[] = unknown[]> = (...args: P) => T;\n\nexport type GenericResourceMetrics"
  },
  {
    "path": ".config/ags/lib/types/customModules/kbLayout.d.ts",
    "chars": 705,
    "preview": "import { layoutMap } from 'customModules/kblayout/layouts';\n\nexport type KbLabelType = 'layout' | 'code';\n\nexport type H"
  },
  {
    "path": ".config/ags/lib/types/customModules/network.d.ts",
    "chars": 72,
    "preview": "export type NetworkResourceData = {\n    in: string;\n    out: string;\n};\n"
  },
  {
    "path": ".config/ags/lib/types/customModules/utils.d.ts",
    "chars": 323,
    "preview": "import { Binding } from 'lib/utils';\n\nexport type InputHandlerEvents = {\n    onPrimaryClick?: Binding;\n    onSecondaryCl"
  },
  {
    "path": ".config/ags/lib/types/defaults/bar.ts",
    "chars": 236,
    "preview": "import { NetstatLabelType, ResourceLabelType } from '../bar';\n\nexport const LABEL_TYPES: ResourceLabelType[] = ['used/to"
  },
  {
    "path": ".config/ags/lib/types/defaults/netstat.ts",
    "chars": 340,
    "preview": "import { RateUnit } from '../bar';\nimport { NetworkResourceData } from '../customModules/network';\n\nexport const GET_DEF"
  },
  {
    "path": ".config/ags/lib/types/defaults/options.ts",
    "chars": 1410,
    "preview": "export const defaultColorMap = {\n    rosewater: '#f5e0dc',\n    flamingo: '#f2cdcd',\n    pink: '#f5c2e7',\n    mauve: '#cb"
  },
  {
    "path": ".config/ags/lib/types/defaults/weather.ts",
    "chars": 40122,
    "preview": "export const DEFAULT_WEATHER = {\n    location: {\n        name: 'Tahiti',\n        region: 'Somewhere',\n        country: '"
  },
  {
    "path": ".config/ags/lib/types/dropdownmenu.d.ts",
    "chars": 359,
    "preview": "import { WindowProps } from 'types/widgets/window';\nimport { GtkWidget, Transition } from './widget';\nimport { Binding }"
  },
  {
    "path": ".config/ags/lib/types/filechooser.d.ts",
    "chars": 81,
    "preview": "export type Config = {\n    [key: string]: string | number | boolean | object;\n};\n"
  },
  {
    "path": ".config/ags/lib/types/globals.d.ts",
    "chars": 67,
    "preview": "export type MousePos = {\n    source: string;\n    pos: number[];\n};\n"
  },
  {
    "path": ".config/ags/lib/types/gpustat.d.ts",
    "chars": 585,
    "preview": "export type GPU_Stat_Process = {\n    username: string;\n    command: string;\n    full_command: string[];\n    gpu_memory_u"
  },
  {
    "path": ".config/ags/lib/types/mpris.d.ts",
    "chars": 119,
    "preview": "export type LoopStatus = 'none' | 'track' | 'playlist';\nexport type PlaybackStatus = 'playing' | 'paused' | 'stopped';\n"
  },
  {
    "path": ".config/ags/lib/types/network.d.ts",
    "chars": 429,
    "preview": "import { WIFI_STATUS_MAP } from 'globals/network';\n\nexport type AccessPoint = {\n    bssid: string | null;\n    address: s"
  },
  {
    "path": ".config/ags/lib/types/notification.d.ts",
    "chars": 342,
    "preview": "import icons from 'modules/icons/index';\n\nexport interface NotificationArgs {\n    appName?: string;\n    body?: string;\n "
  },
  {
    "path": ".config/ags/lib/types/options.d.ts",
    "chars": 5608,
    "preview": "import { Opt } from 'lib/option';\nimport { Variable } from 'types/variable';\nimport { defaultColorMap } from './defaults"
  },
  {
    "path": ".config/ags/lib/types/popupwindow.d.ts",
    "chars": 848,
    "preview": "import { Widget } from 'types/widgets/widget';\nimport { WindowProps } from 'types/widgets/window';\nimport { Transition }"
  },
  {
    "path": ".config/ags/lib/types/power.d.ts",
    "chars": 65,
    "preview": "export type Action = 'sleep' | 'reboot' | 'logout' | 'shutdown';\n"
  },
  {
    "path": ".config/ags/lib/types/powerprofiles.d.ts",
    "chars": 261,
    "preview": "import PowerProfiles from 'types/service/powerprofiles.js';\n\nexport type PowerProfiles = InstanceType<typeof PowerProfil"
  },
  {
    "path": ".config/ags/lib/types/systray.d.ts",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".config/ags/lib/types/utils.d.ts",
    "chars": 298,
    "preview": "import { substitutes } from 'lib/icons';\nimport { EventArgs } from './widget';\n\ntype SubstituteKeys = keyof typeof subst"
  },
  {
    "path": ".config/ags/lib/types/variable.d.ts",
    "chars": 90,
    "preview": "export type Bind = OriginalBinding<GObject.Object, keyof Props<GObject.Object>, unknown>;\n"
  },
  {
    "path": ".config/ags/lib/types/volume.d.ts",
    "chars": 60,
    "preview": "export type VolumeIcons = {\n    [index: number]: string;\n};\n"
  },
  {
    "path": ".config/ags/lib/types/weather.d.ts",
    "chars": 2496,
    "preview": "import { weatherIcons } from 'modules/icons/weather';\n\nexport type UnitType = 'imperial' | 'metric';\n\nexport type Weathe"
  },
  {
    "path": ".config/ags/lib/types/widget.d.ts",
    "chars": 922,
    "preview": "import Gtk from 'types/@girs/gtk-3.0/gtk-3.0';\nimport Box from 'types/widgets/box';\n\nexport type Exclusivity = 'normal' "
  },
  {
    "path": ".config/ags/lib/types/workspace.d.ts",
    "chars": 452,
    "preview": "export type WorkspaceRule = {\n    workspaceString: string;\n    monitor: string;\n};\n\nexport type WorkspaceMap = {\n    [ke"
  },
  {
    "path": ".config/ags/lib/utils.ts",
    "chars": 6075,
    "preview": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type Application } from 'types/service/applications';\ni"
  },
  {
    "path": ".config/ags/lib/variables.ts",
    "chars": 462,
    "preview": "import GLib from 'gi://GLib';\nimport { DateTime } from 'types/@girs/glib-2.0/glib-2.0.cjs';\n\nexport const clock = Variab"
  },
  {
    "path": ".config/ags/main.ts",
    "chars": 722,
    "preview": "import 'lib/session';\nimport 'scss/style';\nimport 'globals/useTheme';\nimport 'globals/dropdown.js';\nimport 'globals/util"
  },
  {
    "path": ".config/ags/modules/bar/Bar.ts",
    "chars": 12218,
    "preview": "const hyprland = await Service.import('hyprland');\n\nimport {\n    Menu,\n    Workspaces,\n    ClientTitle,\n    Media,\n    N"
  },
  {
    "path": ".config/ags/modules/bar/Exports.ts",
    "chars": 1295,
    "preview": "import { Menu } from './menu/index';\nimport { Workspaces } from './workspaces/index';\nimport { ClientTitle } from './win"
  },
  {
    "path": ".config/ags/modules/bar/SideEffects.ts",
    "chars": 600,
    "preview": "import options from 'options';\n\nconst { showIcon, showTime } = options.bar.clock;\n\nshowIcon.connect('changed', () => {\n "
  },
  {
    "path": ".config/ags/modules/bar/battery/index.ts",
    "chars": 5626,
    "preview": "const battery = await Service.import('battery');\nimport Gdk from 'gi://Gdk?version=3.0';\nimport { openMenu } from '../ut"
  },
  {
    "path": ".config/ags/modules/bar/bluetooth/index.ts",
    "chars": 3233,
    "preview": "const bluetooth = await Service.import('bluetooth');\nimport Gdk from 'gi://Gdk?version=3.0';\nimport options from 'option"
  },
  {
    "path": ".config/ags/modules/bar/clock/index.ts",
    "chars": 3426,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nimport GLib from 'gi://GLib';\nimport { openMenu } from '../utils.js';\nimport opt"
  },
  {
    "path": ".config/ags/modules/bar/media/index.ts",
    "chars": 4482,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nconst mpris = await Service.import('mpris');\nimport { openMenu } from '../utils."
  },
  {
    "path": ".config/ags/modules/bar/menu/index.ts",
    "chars": 2455,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nimport { openMenu } from '../utils.js';\nimport options from 'options';\nimport { "
  },
  {
    "path": ".config/ags/modules/bar/network/index.ts",
    "chars": 4429,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nconst network = await Service.import('network');\nimport options from 'options';\n"
  },
  {
    "path": ".config/ags/modules/bar/notifications/index.ts",
    "chars": 4283,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nimport { openMenu } from '../utils.js';\nimport options from 'options';\nimport { "
  },
  {
    "path": ".config/ags/modules/bar/systray/index.ts",
    "chars": 1425,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nimport { BarBoxChild, SelfButton } from 'lib/types/bar';\nimport { Notify } from "
  },
  {
    "path": ".config/ags/modules/bar/utils.ts",
    "chars": 2081,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nimport { Attribute, Child } from 'lib/types/widget';\nimport { calculateMenuPosit"
  },
  {
    "path": ".config/ags/modules/bar/volume/index.ts",
    "chars": 3940,
    "preview": "import Gdk from 'gi://Gdk?version=3.0';\nconst audio = await Service.import('audio');\nimport { openMenu } from '../utils."
  },
  {
    "path": ".config/ags/modules/bar/window_title/index.ts",
    "chars": 9008,
    "preview": "const hyprland = await Service.import('hyprland');\nimport { BarBoxChild } from 'lib/types/bar';\nimport options from 'opt"
  },
  {
    "path": ".config/ags/modules/bar/workspaces/helpers.ts",
    "chars": 5531,
    "preview": "const hyprland = await Service.import('hyprland');\n\nimport { MonitorMap, WorkspaceMap, WorkspaceRule } from 'lib/types/w"
  },
  {
    "path": ".config/ags/modules/bar/workspaces/index.ts",
    "chars": 1732,
    "preview": "import options from 'options';\nimport { createThrottledScrollHandlers, getCurrentMonitorWorkspaces } from './helpers';\ni"
  },
  {
    "path": ".config/ags/modules/bar/workspaces/utils.ts",
    "chars": 3852,
    "preview": "import { WorkspaceIconMap } from 'lib/types/workspace';\nimport { isValidGjsColor } from 'lib/utils';\nimport options from"
  },
  {
    "path": ".config/ags/modules/bar/workspaces/variants/default.ts",
    "chars": 8033,
    "preview": "const hyprland = await Service.import('hyprland');\nimport options from 'options';\nimport { getWorkspaceRules, getWorkspa"
  },
  {
    "path": ".config/ags/modules/bar/workspaces/variants/occupied.ts",
    "chars": 6710,
    "preview": "const hyprland = await Service.import('hyprland');\nimport options from 'options';\nimport { getWorkspaceRules, getWorkspa"
  },
  {
    "path": ".config/ags/modules/icons/index.ts",
    "chars": 7837,
    "preview": "export const substitutes = {\n    'transmission-gtk': 'transmission',\n    'blueberry.py': 'blueberry',\n    Caprine: 'face"
  },
  {
    "path": ".config/ags/modules/icons/weather.ts",
    "chars": 1562,
    "preview": "export const weatherIcons = {\n    warning: '󰼯',\n    sunny: '󰖙',\n    clear: '󰖔',\n    partly_cloudy: '󰖕',\n    partly_cloud"
  },
  {
    "path": ".config/ags/modules/menus/audio/active/SelectedInput.ts",
    "chars": 3376,
    "preview": "const audio = await Service.import('audio');\nimport { getIcon } from '../utils.js';\nimport Box from 'types/widgets/box.j"
  },
  {
    "path": ".config/ags/modules/menus/audio/active/SelectedPlayback.ts",
    "chars": 3025,
    "preview": "const audio = await Service.import('audio');\nimport { getIcon } from '../utils.js';\nimport Box from 'types/widgets/box.j"
  },
  {
    "path": ".config/ags/modules/menus/audio/active/index.ts",
    "chars": 1426,
    "preview": "import { renderActiveInput } from './SelectedInput.js';\nimport { renderActivePlayback } from './SelectedPlayback.js';\nim"
  },
  {
    "path": ".config/ags/modules/menus/audio/available/InputDevices.ts",
    "chars": 2658,
    "preview": "const audio = await Service.import('audio');\nimport { InputDevices } from 'lib/types/audio';\nimport { Stream } from 'typ"
  },
  {
    "path": ".config/ags/modules/menus/audio/available/PlaybackDevices.ts",
    "chars": 2512,
    "preview": "const audio = await Service.import('audio');\nimport { PlaybackDevices } from 'lib/types/audio';\nimport { Stream } from '"
  },
  {
    "path": ".config/ags/modules/menus/audio/available/index.ts",
    "chars": 2939,
    "preview": "const audio = await Service.import('audio');\nimport { BoxWidget } from 'lib/types/widget.js';\nimport { renderInputDevice"
  },
  {
    "path": ".config/ags/modules/menus/audio/index.ts",
    "chars": 877,
    "preview": "import Window from 'types/widgets/window.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nimport { activeDev"
  },
  {
    "path": ".config/ags/modules/menus/audio/utils.ts",
    "chars": 888,
    "preview": "const speakerIcons = {\n    101: 'audio-volume-overamplified-symbolic',\n    66: 'audio-volume-high-symbolic',\n    34: 'au"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/devices/connectedControls.ts",
    "chars": 3050,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { BluetoothDevice } from 'types/service/bluetooth';\n\nconst connecte"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/devices/devicelist.ts",
    "chars": 6302,
    "preview": "import { Bluetooth } from 'types/service/bluetooth.js';\nimport Box from 'types/widgets/box.js';\nimport { connectedContro"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/devices/index.ts",
    "chars": 747,
    "preview": "const bluetooth = await Service.import('bluetooth');\nimport { label } from './label.js';\nimport { devices } from './devi"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/devices/label.ts",
    "chars": 2516,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { Bluetooth } from 'types/service/bluetooth';\n\nconst label = (bluet"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/index.ts",
    "chars": 796,
    "preview": "import Window from 'types/widgets/window.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nimport { Devices }"
  },
  {
    "path": ".config/ags/modules/menus/bluetooth/utils.ts",
    "chars": 854,
    "preview": "const getBluetoothIcon = (iconName: string): string => {\n    const deviceIconMap = [\n        ['^audio-card*', '󰎄'],\n    "
  },
  {
    "path": ".config/ags/modules/menus/calendar/calendar.ts",
    "chars": 675,
    "preview": "import { BoxWidget } from 'lib/types/widget';\n\nconst CalendarWidget = (): BoxWidget => {\n    return Widget.Box({\n       "
  },
  {
    "path": ".config/ags/modules/menus/calendar/index.ts",
    "chars": 1399,
    "preview": "import DropdownMenu from 'modules/menus/shared/dropdown/index';\nimport { TimeWidget } from './time/index';\nimport { Cale"
  },
  {
    "path": ".config/ags/modules/menus/calendar/time/index.ts",
    "chars": 2635,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport options from 'options';\n\nconst { military, hideSeconds } = options."
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/hourly/icon/index.ts",
    "chars": 1534,
    "preview": "import { Weather, WeatherIconTitle } from 'lib/types/weather.js';\nimport { Variable } from 'types/variable.js';\nimport {"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/hourly/index.ts",
    "chars": 957,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Variable } from 'types/variable';\nimport { HourlyIcon } from './ic"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/hourly/temperature/index.ts",
    "chars": 1061,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Variable } from 'types/variable';\nimport options from 'options';\ni"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/hourly/time/index.ts",
    "chars": 839,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Child } from 'lib/types/widget';\nimport { Variable } from 'types/v"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/hourly/utils.ts",
    "chars": 795,
    "preview": "import { Weather } from 'lib/types/weather';\n\nexport const getNextEpoch = (wthr: Weather, hoursFromNow: number): number "
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/icon/index.ts",
    "chars": 656,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Variable } from 'types/variable';\nimport { getWeatherStatusTextIco"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/index.ts",
    "chars": 1423,
    "preview": "import { TodayIcon } from './icon/index.js';\nimport { TodayStats } from './stats/index.js';\nimport { TodayTemperature } "
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/stats/index.ts",
    "chars": 1819,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Variable } from 'types/variable';\nimport options from 'options';\ni"
  },
  {
    "path": ".config/ags/modules/menus/calendar/weather/temperature/index.ts",
    "chars": 2634,
    "preview": "import { Weather } from 'lib/types/weather';\nimport { Variable } from 'types/variable';\nimport options from 'options';\ni"
  },
  {
    "path": ".config/ags/modules/menus/dashboard/controls/index.ts",
    "chars": 4527,
    "preview": "import { BoxWidget } from 'lib/types/widget';\n\nconst network = await Service.import('network');\nconst bluetooth = await "
  },
  {
    "path": ".config/ags/modules/menus/dashboard/directories/index.ts",
    "chars": 5050,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport options from 'options';\n\nconst { left, right } = options.menus.dash"
  },
  {
    "path": ".config/ags/modules/menus/dashboard/index.ts",
    "chars": 2287,
    "preview": "import DropdownMenu from '../shared/dropdown/index.js';\nimport { Profile } from './profile/index.js';\nimport { Shortcuts"
  },
  {
    "path": ".config/ags/modules/menus/dashboard/profile/index.ts",
    "chars": 4153,
    "preview": "import powermenu from '../../power/helpers/actions.js';\nimport { PowerOptions } from 'lib/types/options.js';\nimport GdkP"
  },
  {
    "path": ".config/ags/modules/menus/dashboard/shortcuts/index.ts",
    "chars": 14598,
    "preview": "const hyprland = await Service.import('hyprland');\nimport { Attribute, BoxWidget, Child } from 'lib/types/widget';\nimpor"
  },
  {
    "path": ".config/ags/modules/menus/dashboard/stats/index.ts",
    "chars": 11191,
    "preview": "import options from 'options';\nimport Ram from 'services/Ram';\nimport { GPU_Stat } from 'lib/types/gpustat';\nimport { de"
  },
  {
    "path": ".config/ags/modules/menus/energy/brightness/index.ts",
    "chars": 2204,
    "preview": "import { BoxWidget } from 'lib/types/widget.js';\nimport brightness from '../../../../services/Brightness.js';\nimport ico"
  },
  {
    "path": ".config/ags/modules/menus/energy/index.ts",
    "chars": 873,
    "preview": "import DropdownMenu from '../shared/dropdown/index.js';\nimport { EnergyProfiles } from './profiles/index.js';\nimport { B"
  },
  {
    "path": ".config/ags/modules/menus/energy/profiles/index.ts",
    "chars": 3537,
    "preview": "const powerProfiles = await Service.import('powerprofiles');\nimport { PowerProfile, PowerProfileObject, PowerProfiles } "
  },
  {
    "path": ".config/ags/modules/menus/main.ts",
    "chars": 765,
    "preview": "import PowerMenu from './power/index.js';\nimport Verification from './power/verification.js';\nimport AudioMenu from './a"
  },
  {
    "path": ".config/ags/modules/menus/media/components/bar.ts",
    "chars": 3174,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { Mpris, MprisPlayer } from 'types/service/mpris';\n\nconst media = a"
  },
  {
    "path": ".config/ags/modules/menus/media/components/controls.ts",
    "chars": 10668,
    "preview": "import { MprisPlayer } from 'types/service/mpris.js';\nimport icons from '../../../icons/index.js';\nimport { LoopStatus, "
  },
  {
    "path": ".config/ags/modules/menus/media/components/mediainfo.ts",
    "chars": 3671,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { MprisPlayer } from 'types/service/mpris';\n\nconst media = await Se"
  },
  {
    "path": ".config/ags/modules/menus/media/index.ts",
    "chars": 740,
    "preview": "import Window from 'types/widgets/window.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nimport { Media } f"
  },
  {
    "path": ".config/ags/modules/menus/media/media.ts",
    "chars": 3493,
    "preview": "const media = await Service.import('mpris');\nimport { MediaInfo } from './components/mediainfo.js';\nimport { Controls } "
  },
  {
    "path": ".config/ags/modules/menus/network/ethernet/index.ts",
    "chars": 3307,
    "preview": "import { BoxWidget } from 'lib/types/widget';\n\nconst network = await Service.import('network');\n\nconst Ethernet = (): Bo"
  },
  {
    "path": ".config/ags/modules/menus/network/index.ts",
    "chars": 761,
    "preview": "import Window from 'types/widgets/window.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nimport { Ethernet "
  },
  {
    "path": ".config/ags/modules/menus/network/utils.ts",
    "chars": 835,
    "preview": "import { WifiIcon } from 'lib/types/network';\n\nconst getWifiIcon = (iconName: string): WifiIcon => {\n    const deviceIco"
  },
  {
    "path": ".config/ags/modules/menus/network/wifi/APStaging.ts",
    "chars": 4553,
    "preview": "import { Network } from 'types/service/network';\nimport { Variable } from 'types/variable';\nimport { AccessPoint } from "
  },
  {
    "path": ".config/ags/modules/menus/network/wifi/WirelessAPs.ts",
    "chars": 10660,
    "preview": "import { Network } from 'types/service/network.js';\nimport { AccessPoint, WifiStatus } from 'lib/types/network.js';\nimpo"
  },
  {
    "path": ".config/ags/modules/menus/network/wifi/index.ts",
    "chars": 2851,
    "preview": "const network = await Service.import('network');\nimport { renderWAPs } from './WirelessAPs.js';\nimport { renderWapStagin"
  },
  {
    "path": ".config/ags/modules/menus/notifications/controls/index.ts",
    "chars": 3117,
    "preview": "import { closeNotifications } from 'globals/notification';\nimport { BoxWidget } from 'lib/types/widget';\nimport { Notifi"
  },
  {
    "path": ".config/ags/modules/menus/notifications/index.ts",
    "chars": 1800,
    "preview": "import { Notification } from 'types/service/notifications.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nc"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/actions/index.ts",
    "chars": 1988,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { Notification, Notifications } from 'types/service/notifications';"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/body/index.ts",
    "chars": 806,
    "preview": "import { BoxWidget } from 'lib/types/widget.js';\nimport { notifHasImg } from '../../utils.js';\nimport { Notification } f"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/close/index.ts",
    "chars": 647,
    "preview": "import { Attribute } from 'lib/types/widget';\nimport { Notification, Notifications } from 'types/service/notifications';"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/header/icon.ts",
    "chars": 672,
    "preview": "import { Notification } from 'types/service/notifications.js';\nimport { NotificationIcon } from 'lib/types/notification."
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/header/index.ts",
    "chars": 1906,
    "preview": "import GLib from 'gi://GLib';\nimport { Notification } from 'types/service/notifications';\nimport { NotificationIcon } fr"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/image/index.ts",
    "chars": 721,
    "preview": "import { Notification } from 'types/service/notifications';\nimport { notifHasImg } from '../../utils.js';\nimport { BoxWi"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/index.ts",
    "chars": 3735,
    "preview": "import { Notifications, Notification } from 'types/service/notifications';\nimport { notifHasImg } from '../utils.js';\nim"
  },
  {
    "path": ".config/ags/modules/menus/notifications/notification/placeholder/index.ts",
    "chars": 953,
    "preview": "import { BoxWidget } from 'lib/types/widget';\nimport { Notifications } from 'types/service/notifications';\n\nconst Placeh"
  },
  {
    "path": ".config/ags/modules/menus/notifications/pager/index.ts",
    "chars": 3955,
    "preview": "const notifs = await Service.import('notifications');\n\nimport { BoxWidget } from 'lib/types/widget';\nimport options from"
  },
  {
    "path": ".config/ags/modules/menus/notifications/utils.ts",
    "chars": 220,
    "preview": "import { Notification } from 'types/service/notifications';\n\nconst notifHasImg = (notif: Notification): boolean => {\n   "
  },
  {
    "path": ".config/ags/modules/menus/power/helpers/actions.ts",
    "chars": 1487,
    "preview": "import { Action } from 'lib/types/power';\nimport options from 'options';\nconst { sleep, reboot, logout, shutdown } = opt"
  },
  {
    "path": ".config/ags/modules/menus/power/index.ts",
    "chars": 1482,
    "preview": "import { Action } from 'lib/types/power.js';\nimport PopupWindow from '../shared/popup/index.js';\nimport powermenu from '"
  },
  {
    "path": ".config/ags/modules/menus/power/verification.ts",
    "chars": 2264,
    "preview": "import Window from 'types/widgets/window.js';\nimport PopupWindow from '../shared/popup/index.js';\nimport powermenu from "
  },
  {
    "path": ".config/ags/modules/menus/powerDropdown/button.ts",
    "chars": 2287,
    "preview": "import { PowerOptions } from 'lib/types/options';\nimport options from 'options';\nimport powermenu from '../power/helpers"
  },
  {
    "path": ".config/ags/modules/menus/powerDropdown/index.ts",
    "chars": 809,
    "preview": "import Window from 'types/widgets/window.js';\nimport DropdownMenu from '../shared/dropdown/index.js';\nimport { PowerButt"
  },
  {
    "path": ".config/ags/modules/menus/shared/dropdown/eventBoxes/index.ts",
    "chars": 1104,
    "preview": "import { Attribute, BoxWidget } from 'lib/types/widget';\nimport EventBox from 'types/widgets/eventbox';\nimport { BarLoca"
  },
  {
    "path": ".config/ags/modules/menus/shared/dropdown/index.ts",
    "chars": 3964,
    "preview": "import options from 'options';\nimport { DropdownMenuProps } from 'lib/types/dropdownmenu';\nimport { Attribute, Child, Ex"
  },
  {
    "path": ".config/ags/modules/menus/shared/dropdown/locationHandler/index.ts",
    "chars": 3597,
    "preview": "const hyprland = await Service.import('hyprland');\n\nimport options from 'options';\nimport { bash } from 'lib/utils';\nimp"
  },
  {
    "path": ".config/ags/modules/menus/shared/popup/index.ts",
    "chars": 5596,
    "preview": "import { WINDOW_LAYOUTS } from 'globals/window';\nimport { LayoutFunction, Layouts, PopupWindowProps } from 'lib/types/po"
  },
  {
    "path": ".config/ags/modules/notifications/actions/index.ts",
    "chars": 1859,
    "preview": "import { Attribute, Child } from 'lib/types/widget';\nimport { Notification, Notifications } from 'types/service/notifica"
  },
  {
    "path": ".config/ags/modules/notifications/body/index.ts",
    "chars": 875,
    "preview": "import { Notification } from 'types/service/notifications';\nimport { notifHasImg } from '../../menus/notifications/utils"
  },
  {
    "path": ".config/ags/modules/notifications/close/index.ts",
    "chars": 646,
    "preview": "import { Attribute, Child } from 'lib/types/widget';\nimport { Notification, Notifications } from 'types/service/notifica"
  },
  {
    "path": ".config/ags/modules/notifications/header/icon.ts",
    "chars": 663,
    "preview": "import { Notification } from 'types/service/notifications.js';\nimport { getNotificationIcon } from 'globals/notification"
  },
  {
    "path": ".config/ags/modules/notifications/header/index.ts",
    "chars": 1999,
    "preview": "import GLib from 'gi://GLib';\nimport { notifHasImg } from '../../menus/notifications/utils.js';\nimport { NotificationIco"
  },
  {
    "path": ".config/ags/modules/notifications/image/index.ts",
    "chars": 790,
    "preview": "import { Notification } from 'types/service/notifications';\nimport { notifHasImg } from '../../menus/notifications/utils"
  },
  {
    "path": ".config/ags/modules/notifications/index.ts",
    "chars": 3449,
    "preview": "const notifs = await Service.import('notifications');\nimport options from 'options';\nimport { notifHasImg } from '../men"
  },
  {
    "path": ".config/ags/modules/osd/bar/index.ts",
    "chars": 4007,
    "preview": "import { OSDOrientation } from 'lib/types/options';\nimport brightness from 'services/Brightness';\nimport options from 'o"
  },
  {
    "path": ".config/ags/modules/osd/icon/index.ts",
    "chars": 1984,
    "preview": "import { Attribute, Child } from 'lib/types/widget';\nimport brightness from 'services/Brightness';\nimport Box from 'type"
  },
  {
    "path": ".config/ags/modules/osd/index.ts",
    "chars": 5798,
    "preview": "import options from 'options';\nimport brightness from 'services/Brightness';\nimport { OSDLabel } from './label/index';\ni"
  },
  {
    "path": ".config/ags/modules/osd/label/index.ts",
    "chars": 3513,
    "preview": "import brightness from 'services/Brightness';\nimport options from 'options';\nimport Box from 'types/widgets/box';\nimport"
  },
  {
    "path": ".config/ags/modules/shared/barItemBox.ts",
    "chars": 1074,
    "preview": "import { BarBoxChild } from 'lib/types/bar';\nimport { Bind } from 'lib/types/variable';\nimport { Attribute, GtkWidget } "
  },
  {
    "path": ".config/ags/nix/default.nix",
    "chars": 1341,
    "preview": "{\n  inputs,\n  pkgs,\n  system,\n  stdenv,\n  lib,\n  writeShellScriptBin,\n  bun,\n  dart-sass,\n  fd,\n  accountsservice,\n  bto"
  },
  {
    "path": ".config/ags/options.ts",
    "chars": 46670,
    "preview": "import { opt, mkOptions } from 'lib/option';\nimport { NetstatLabelType, RateUnit, ResourceLabelType } from 'lib/types/ba"
  },
  {
    "path": ".config/ags/package.json",
    "chars": 856,
    "preview": "{\n    \"name\": \"hyprpanel\",\n    \"version\": \"1.0.0\",\n    \"description\": \"A customizable panel built for Hyprland.\",\n    \"m"
  },
  {
    "path": ".config/ags/scripts/README.md",
    "chars": 219,
    "preview": "# scripts folder\n- For ARM devices, you have to compile C++ files yourself. If there are none, yippee\n- It is advised to"
  },
  {
    "path": ".config/ags/scripts/checkUpdates.sh",
    "chars": 884,
    "preview": "#!/bin/bash\n\ncheck_arch_updates() {\n    official_updates=0\n    aur_updates=0\n\n    if [ \"$1\" = \"-y\" ]; then\n        aur_u"
  },
  {
    "path": ".config/ags/scripts/color_generation/applycolor.sh",
    "chars": 6287,
    "preview": "#!/usr/bin/env bash\n\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nXDG_CACHE_HOME=\"${XDG_CACHE_HOME:-$HOME/.cache}"
  },
  {
    "path": ".config/ags/scripts/color_generation/colorgen.sh",
    "chars": 3861,
    "preview": "#!/usr/bin/env bash\n\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nXDG_CACHE_HOME=\"${XDG_CACHE_HOME:-$HOME/.cache}"
  },
  {
    "path": ".config/ags/scripts/color_generation/generate_colors_material.py",
    "chars": 8984,
    "preview": "#!/usr/bin/env python3\nimport argparse\nimport math\nimport json\nfrom PIL import Image\nfrom materialyoucolor.quantize impo"
  },
  {
    "path": ".config/ags/scripts/color_generation/pywal_to_material.scss",
    "chars": 2133,
    "preview": "$primary: lighten($color4, 20%);\n$onPrimary: darken($color2, 20%);\n$primaryContainer: darken($color2, 10%);\n$onPrimaryCo"
  },
  {
    "path": ".config/ags/scripts/color_generation/randomwall.sh",
    "chars": 248,
    "preview": "#!/usr/bin/env bash\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nCONFIG_DIR=\"$XDG_CONFIG_HOME/ags\"\n$CONFIG_DIR/sc"
  },
  {
    "path": ".config/ags/scripts/color_generation/schemes/scheme_morevibrant.py",
    "chars": 1895,
    "preview": "from materialyoucolor.scheme.dynamic_scheme import DynamicSchemeOptions, DynamicScheme\nfrom materialyoucolor.scheme.vari"
  },
  {
    "path": ".config/ags/scripts/color_generation/specials/_material_badapple-l.scss",
    "chars": 702,
    "preview": "$darkmode: false;\n$primary: #000000;\n$onPrimary: #FFFFFF ;\n$primaryContainer: #d4d4d4;\n$onPrimaryContainer: #000000;\n$se"
  },
  {
    "path": ".config/ags/scripts/color_generation/specials/_material_badapple.scss",
    "chars": 692,
    "preview": "$darkmode: true;\n$primary: #e2e2e2;\n$onPrimary: #000000;\n$primaryContainer: #6b6b6b;\n$onPrimaryContainer: #e2e2e2;\n$seco"
  },
  {
    "path": ".config/ags/scripts/color_generation/switchcolor.sh",
    "chars": 1138,
    "preview": "#!/usr/bin/env bash\n\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nXDG_CACHE_HOME=\"${XDG_CACHE_HOME:-$HOME/.cache}"
  },
  {
    "path": ".config/ags/scripts/color_generation/switchwall.sh",
    "chars": 1440,
    "preview": "#!/usr/bin/env bash\n\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nCONFIG_DIR=\"$XDG_CONFIG_HOME/ags\"\n\nswitch() {\n\t"
  },
  {
    "path": ".config/ags/scripts/fillThemes.js",
    "chars": 12321,
    "preview": "#!/usr/bin/env node\n\n/**\n * compare_themes.js\n *\n * A Node.js script to compare theme JSON files against base themes and"
  }
]

// ... and 549 more files (download for full content)

About this extraction

This page contains the full source code of the chikobara/dotfiles GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 749 files (2.5 MB), approximately 702.2k tokens, and a symbol index with 240 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!